Compare commits
845 Commits
developmen
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d162f297a | ||
|
|
3247de6cf6 | ||
|
|
f42ef0749a | ||
|
|
7032975709 | ||
|
|
7362d1b9db | ||
|
|
99c6ea30a9 | ||
|
|
0ba5553f77 | ||
|
|
e46d5b833b | ||
|
|
1b8a76d5e0 | ||
|
|
2e2c780671 | ||
|
|
f6adfb60e4 | ||
|
|
fa878f8155 | ||
|
|
0738b9e1c8 | ||
|
|
3945afc0dd | ||
|
|
5b439e1949 | ||
|
|
f6080a1d38 | ||
|
|
25f06ce713 | ||
|
|
127351249f | ||
|
|
94c4b07318 | ||
|
|
920c8f6910 | ||
|
|
8691ff05e1 | ||
|
|
ca846b02e0 | ||
|
|
91e70750d6 | ||
|
|
273456d1fd | ||
|
|
3c9f66c95c | ||
|
|
e052a0d232 | ||
|
|
a933a1d587 | ||
|
|
28cc092bb7 | ||
|
|
3b756beba6 | ||
|
|
1ae942988c | ||
|
|
7a49c61105 | ||
|
|
448b6c723d | ||
|
|
74b9eb40b1 | ||
|
|
53af7a916c | ||
|
|
35bb79cc59 | ||
|
|
a7c3d89531 | ||
|
|
09cd44905a | ||
|
|
2b635ba3bf | ||
|
|
4b5129e9cb | ||
|
|
cd191dae70 | ||
|
|
780d8b926d | ||
|
|
e624e257ff | ||
|
|
267b927a7f | ||
|
|
358365072d | ||
|
|
2c793c25ee | ||
|
|
eba50e3f9c | ||
|
|
58848481c9 | ||
|
|
5bb1231d5e | ||
|
|
932bbd8fde | ||
|
|
5f47a2cb6c | ||
|
|
76ea8ca2ed | ||
|
|
b37d8ae29d | ||
|
|
02fcbf7ffa | ||
|
|
1f7b53ee22 | ||
|
|
01977cefde | ||
|
|
fd621e49c4 | ||
|
|
26d22388c0 | ||
|
|
22a5c4a12d | ||
|
|
7522c4707e | ||
|
|
61edcf63be | ||
|
|
a09daf052b | ||
|
|
4393bf42ed | ||
|
|
df83acb5ed | ||
|
|
09cf49080b | ||
|
|
3b301efd27 | ||
|
|
2e843bbd8a | ||
|
|
b539ecaeb1 | ||
|
|
62cba80f82 | ||
|
|
7d7cd8d85e | ||
|
|
5518395533 | ||
|
|
1cf2851e39 | ||
|
|
cdbcef323f | ||
|
|
5125b20721 | ||
|
|
c644ed67fd | ||
|
|
48fd2b1461 | ||
|
|
2f1c168b3e | ||
|
|
a5aee28d42 | ||
|
|
3c9625b622 | ||
|
|
8d3c2f7af6 | ||
|
|
0109c9974f | ||
|
|
39ec9d92ec | ||
|
|
a77e664ab1 | ||
|
|
b601bf1c1f | ||
|
|
724898714d | ||
|
|
9fe535336c | ||
|
|
1483f5f7c8 | ||
|
|
4355a04ba4 | ||
|
|
cdc0c8bb37 | ||
|
|
85deec1c21 | ||
|
|
d4572a2d36 | ||
|
|
6f76c16994 | ||
|
|
97317c5179 | ||
|
|
5db43dd065 | ||
|
|
673654a9b7 | ||
|
|
53be0bbc1a | ||
|
|
ca6f4070d0 | ||
|
|
8c40d541c4 | ||
|
|
c3baee1fa9 | ||
|
|
dc6e5fe3aa | ||
|
|
b311a6df53 | ||
|
|
785f22c026 | ||
|
|
bfcc03850b | ||
|
|
65402c1420 | ||
|
|
b462b2fa03 | ||
|
|
112dfdf074 | ||
|
|
ac22e226b5 | ||
|
|
0c26b90591 | ||
|
|
ff5611e123 | ||
|
|
f8f2384c54 | ||
|
|
ef18cf0718 | ||
|
|
9d35fc85ad | ||
|
|
e98f9763fd | ||
|
|
95e5385cd1 | ||
|
|
46abf01366 | ||
|
|
87f06425e1 | ||
|
|
45ab7543d5 | ||
|
|
120e4fc94c | ||
|
|
fed16efd10 | ||
|
|
ea6277c586 | ||
|
|
49bf461c36 | ||
|
|
696781c857 | ||
|
|
5540872f62 | ||
|
|
dac53a56c3 | ||
|
|
69690f0184 | ||
|
|
f11a4c93ac | ||
|
|
d74870812e | ||
|
|
9eed33b5f2 | ||
|
|
55b7715e1c | ||
|
|
c129b5ba8c | ||
|
|
efc2844d99 | ||
|
|
ab38f85d38 | ||
|
|
485959c399 | ||
|
|
81eccba393 | ||
|
|
b3b49fd4ca | ||
|
|
b7a08db4e7 | ||
|
|
2d63c3d576 | ||
|
|
5f4a2392af | ||
|
|
f6fe8be7c4 | ||
|
|
89af6d23e8 | ||
|
|
7e1431d65e | ||
|
|
d50e845ba0 | ||
|
|
6796c35e5b | ||
|
|
4a68a10005 | ||
|
|
17088b3025 | ||
|
|
4e3c659b6d | ||
|
|
6afcf82cc4 | ||
|
|
f4ddb40bde | ||
|
|
6017e2172e | ||
|
|
bef9e64bf8 | ||
|
|
e8d95bdb68 | ||
|
|
10fb7d9d96 | ||
|
|
2ec196e664 | ||
|
|
1f38b98bfd | ||
|
|
122d21d4eb | ||
|
|
a7c76386bc | ||
|
|
042b67c531 | ||
|
|
2e72ed3698 | ||
|
|
e0157f6da4 | ||
|
|
bc01f46388 | ||
|
|
74f791541f | ||
|
|
84c7fdba5a | ||
|
|
630fa23f6c | ||
|
|
8f58f09c8c | ||
|
|
a0922f2944 | ||
|
|
b8f001625b | ||
|
|
53394efebf | ||
|
|
d8296e1d01 | ||
|
|
2c00e5ee79 | ||
|
|
34e220dcad | ||
|
|
fa1fffd8b9 | ||
|
|
67eb430ff9 | ||
|
|
ff53355b4a | ||
|
|
331b2c517b | ||
|
|
05d9f20a66 | ||
|
|
9e3a2e920d | ||
|
|
1511b87959 | ||
|
|
9c3e4b7b83 | ||
|
|
b718f49071 | ||
|
|
e7157119ae | ||
|
|
09187bdb7f | ||
|
|
2aed392fbe | ||
|
|
1a0054a911 | ||
|
|
6e6f3d3d3e | ||
|
|
29df140680 | ||
|
|
f37c67a122 | ||
|
|
e53c9aab72 | ||
|
|
385ad06adc | ||
|
|
d1e2d943a9 | ||
|
|
90aa3557b7 | ||
|
|
8891167183 | ||
|
|
6631e645df | ||
|
|
b7f202969b | ||
|
|
1dc3353ecc | ||
|
|
b1a3f1a7b8 | ||
|
|
89f3a26635 | ||
|
|
506fe9b1af | ||
|
|
37c898d3ce | ||
|
|
e4eac5714a | ||
|
|
9d4a59ca16 | ||
|
|
8ec524061a | ||
|
|
434ed46b5a | ||
|
|
3ece5e0ba2 | ||
|
|
52a383ffb7 | ||
|
|
8ad1d5929a | ||
|
|
445c01499b | ||
|
|
0b05be841d | ||
|
|
6bcb5f2af5 | ||
|
|
7482751c5b | ||
|
|
7a025fff42 | ||
|
|
602fe36638 | ||
|
|
da08fc74f1 | ||
|
|
14af45baf0 | ||
|
|
420a88c505 | ||
|
|
f3c44f8dd1 | ||
|
|
c72111e18b | ||
|
|
1ca2870912 | ||
|
|
db9744e1e5 | ||
|
|
e700095551 | ||
|
|
99196a77ed | ||
|
|
289a8222a0 | ||
|
|
dc10f8d35b | ||
|
|
f448232fe7 | ||
|
|
4baf4b4afa | ||
|
|
1785093023 | ||
|
|
0d65f8d894 | ||
|
|
3d8c390291 | ||
|
|
f0a13856bc | ||
|
|
ad6394783d | ||
|
|
16e9843298 | ||
|
|
a4c949c376 | ||
|
|
0e0d5316b7 | ||
|
|
60cb6ee8fb | ||
|
|
7d3279d21a | ||
|
|
402d13ad99 | ||
|
|
e803f5a2d4 | ||
|
|
3989d0f1e2 | ||
|
|
161d476ab3 | ||
|
|
ce84a89cf3 | ||
|
|
1d210a9e52 | ||
|
|
660f463aea | ||
|
|
ad9f01111c | ||
|
|
1b885e4114 | ||
|
|
b56742bcb2 | ||
|
|
40d4d69a9a | ||
|
|
b54d5beb76 | ||
|
|
5cbcd440f5 | ||
|
|
1cdc34249a | ||
|
|
8bbb218777 | ||
|
|
755ac7f657 | ||
|
|
d7b884ff86 | ||
|
|
fda3620ed0 | ||
|
|
61ad9f0d58 | ||
|
|
804c8ad40a | ||
|
|
0ddf009f8f | ||
|
|
14309b5c96 | ||
|
|
57d9de469a | ||
|
|
404ade396c | ||
|
|
bdad6da6d9 | ||
|
|
e7ef3b94c1 | ||
|
|
c19c92ab7e | ||
|
|
944229bae3 | ||
|
|
661b05d9e3 | ||
|
|
4d1d471a66 | ||
|
|
3e84fbbaf4 | ||
|
|
c4e59c1a5e | ||
|
|
9ee8e9007a | ||
|
|
4d52a5c44a | ||
|
|
fff9073f9d | ||
|
|
71f0b8a005 | ||
|
|
d2b965f79e | ||
|
|
a02aa71a95 | ||
|
|
7562bf5c95 | ||
|
|
f9521483e2 | ||
|
|
ca85858885 | ||
|
|
c7b3a94533 | ||
|
|
b010c9ecb0 | ||
|
|
0b98d04bac | ||
|
|
e25e388e59 | ||
|
|
10654b7916 | ||
|
|
ff049ad3e8 | ||
|
|
3572fff2c1 | ||
|
|
774e4cdf94 | ||
|
|
65ade5cab8 | ||
|
|
bf21a073fb | ||
|
|
851f1c265f | ||
|
|
51f3b5927b | ||
|
|
42c779f368 | ||
|
|
c104ee4fd9 | ||
|
|
0b2efa31b5 | ||
|
|
17baa8fcb2 | ||
|
|
e550baf59d | ||
|
|
fd53eb92e6 | ||
|
|
6521c0bfb8 | ||
|
|
50489dd682 | ||
|
|
220afa5add | ||
|
|
9d549b02fe | ||
|
|
ca2ded047b | ||
|
|
c423e61ce8 | ||
|
|
65550c7bf4 | ||
|
|
cdb4da9e5f | ||
|
|
b59a5303c6 | ||
|
|
9a72abbed0 | ||
|
|
762a5ff01b | ||
|
|
2f6571e703 | ||
|
|
80c90f1819 | ||
|
|
4b0c2c60a2 | ||
|
|
ee7d7d2f6a | ||
|
|
0ad670013b | ||
|
|
064a66aa66 | ||
|
|
f46c19b152 | ||
|
|
ea2c583b26 | ||
|
|
7bd2a90141 | ||
|
|
632549dd9d | ||
|
|
70ef274821 | ||
|
|
7d9759fda4 | ||
|
|
0fd06d5e4e | ||
|
|
4995e44e06 | ||
|
|
fd43d7d56d | ||
|
|
96f292f61c | ||
|
|
e899e4545f | ||
|
|
c62f5e3911 | ||
|
|
9f1d184081 | ||
|
|
29e596eedb | ||
|
|
6e28afda67 | ||
|
|
eca7e9fba1 | ||
|
|
aa2ac2b296 | ||
|
|
ce57752b95 | ||
|
|
63163c6459 | ||
|
|
2712ee5c0b | ||
|
|
2e28a4a790 | ||
|
|
4179943df6 | ||
|
|
8bb8eee384 | ||
|
|
85d79a8d7f | ||
|
|
d38dd67c2f | ||
|
|
e73d082eab | ||
|
|
2637538d9a | ||
|
|
0eacf9a840 | ||
|
|
eb58274f90 | ||
|
|
aa410d6847 | ||
|
|
97f1be9d6f | ||
|
|
a7c9dde5e3 | ||
|
|
8ec5bc049b | ||
|
|
1f2bec06ef | ||
|
|
1cad57bec2 | ||
|
|
10f3c01677 | ||
|
|
fc68b669db | ||
|
|
6e22091b81 | ||
|
|
545db54c14 | ||
|
|
aa69fef9ba | ||
|
|
1e30642d28 | ||
|
|
c1dfba949e | ||
|
|
dfa9592755 | ||
|
|
8f2b1f0f78 | ||
|
|
cf91ec14c0 | ||
|
|
891aa649e8 | ||
|
|
dfe0f99bea | ||
|
|
591022c097 | ||
|
|
a8a0167123 | ||
|
|
c76da54b93 | ||
|
|
186f6101ff | ||
|
|
e95cf0a026 | ||
|
|
3eaa3a0189 | ||
|
|
0ba445aad2 | ||
|
|
637c718b05 | ||
|
|
a01019b1b3 | ||
|
|
f6e2393a40 | ||
|
|
715857a587 | ||
|
|
186ad2d7a2 | ||
|
|
c64c49ab6e | ||
|
|
3e067e2103 | ||
|
|
4cc1f77b14 | ||
|
|
334dd5fe94 | ||
|
|
d73f37cacc | ||
|
|
c6a7e3dcb1 | ||
|
|
4bdc02d22c | ||
|
|
afa8e04008 | ||
|
|
990c1bb2bf | ||
|
|
a5a59c526c | ||
|
|
2d5bef4b7b | ||
|
|
5893b1e3b3 | ||
|
|
0af452b8a4 | ||
|
|
3d82198c90 | ||
|
|
01bca360c7 | ||
|
|
59e994ac29 | ||
|
|
d5f3105341 | ||
|
|
92920f69d4 | ||
|
|
61ac520192 | ||
|
|
45176cc2e2 | ||
|
|
6aacce5a58 | ||
|
|
7a515c35d2 | ||
|
|
80dc04669c | ||
|
|
a702c87986 | ||
|
|
1942103985 | ||
|
|
fd161fa9eb | ||
|
|
44a18f4ace | ||
|
|
3269c4f602 | ||
|
|
43cbf0084a | ||
|
|
28b1356f76 | ||
|
|
38456cb213 | ||
|
|
8c826eaaed | ||
|
|
f047556ab5 | ||
|
|
057b335e82 | ||
|
|
4b55719f86 | ||
|
|
30c7da2bf9 | ||
|
|
82fb4fc74c | ||
|
|
151f122b8c | ||
|
|
b198ca5051 | ||
|
|
d9abe84949 | ||
|
|
5387ff207c | ||
|
|
17f4d69e30 | ||
|
|
77d3fc359d | ||
|
|
86151f3337 | ||
|
|
ae4b5bca33 | ||
|
|
eb120a264e | ||
|
|
7e3f496ea1 | ||
|
|
4d33f16f13 | ||
|
|
d7ebefe7ab | ||
|
|
8dc2197677 | ||
|
|
e3804b103b | ||
|
|
fe993cba73 | ||
|
|
ef6cdf07d8 | ||
|
|
cdbde6f5fa | ||
|
|
4059aa9875 | ||
|
|
22e30ae5cb | ||
|
|
78c883743f | ||
|
|
e46307e715 | ||
|
|
f3e078b481 | ||
|
|
c03f54b3eb | ||
|
|
bb0234fb7d | ||
|
|
03f25c8c0e | ||
|
|
8e5005daa0 | ||
|
|
259458eec3 | ||
|
|
59e57aa274 | ||
|
|
de33bcd72b | ||
|
|
d72472ccc3 | ||
|
|
91efd170c8 | ||
|
|
6f1ddd51fd | ||
|
|
9f48a91a29 | ||
|
|
a7e2548e14 | ||
|
|
3294faaeaa | ||
|
|
06480159e3 | ||
|
|
6ce06ed5c0 | ||
|
|
71e535388a | ||
|
|
dbd265d368 | ||
|
|
c11f182f83 | ||
|
|
5f70cfd585 | ||
|
|
6e0675f28b | ||
|
|
96f45d2c80 | ||
|
|
091e44f471 | ||
|
|
00549d6a88 | ||
|
|
d940e0ee78 | ||
|
|
39a38d46ee | ||
|
|
71435ed75a | ||
|
|
e7ec408b98 | ||
|
|
9306064420 | ||
|
|
37a16edfb4 | ||
|
|
9ad5b9547f | ||
|
|
47edb0bdf4 | ||
|
|
5db47e879c | ||
|
|
54b46dd25e | ||
|
|
4cb92c8508 | ||
|
|
cb76e2dcde | ||
|
|
901c64ed85 | ||
|
|
f6f90d68fa | ||
|
|
05e295fcac | ||
|
|
c97df6dc61 | ||
|
|
61406aafa6 | ||
|
|
03210db711 | ||
|
|
b3a34c109a | ||
|
|
81daad35d8 | ||
|
|
529eb24d76 | ||
|
|
e81bf7b561 | ||
|
|
7a35dc9b38 | ||
|
|
c72ef97b82 | ||
|
|
5284ee2ef9 | ||
|
|
724c097d52 | ||
|
|
3c3da178ba | ||
|
|
db4e5d48af | ||
|
|
a7cf081ed5 | ||
|
|
db5b11f6d3 | ||
|
|
8d3d52485f | ||
|
|
edb58ebc81 | ||
|
|
971b518e8f | ||
|
|
8d9507dce1 | ||
|
|
748f8f472d | ||
|
|
db2b4739c2 | ||
|
|
6c12e5cb03 | ||
|
|
140e57a123 | ||
|
|
3ca6791939 | ||
|
|
1c473c95a2 | ||
|
|
7e145bdec7 | ||
|
|
44c17bd7a2 | ||
|
|
c493f6e31e | ||
|
|
5213b0b315 | ||
|
|
8bfd0a1c16 | ||
|
|
0541167cc5 | ||
|
|
834966ae96 | ||
|
|
e7d813c3f3 | ||
|
|
26e47ff203 | ||
|
|
d2b2a5399d | ||
|
|
5a4d6d3e8c | ||
|
|
61a5e180f4 | ||
|
|
d5b8ea3ac5 | ||
|
|
4e87ef179b | ||
|
|
3b7c31626d | ||
|
|
a57e35354d | ||
|
|
a269fd3ad8 | ||
|
|
86bee9ad0d | ||
|
|
f8b57ca9bd | ||
|
|
5f7b780195 | ||
|
|
ba5400d04a | ||
|
|
0190e737c1 | ||
|
|
db64d9b69f | ||
|
|
0d12ab36a9 | ||
|
|
8f52efbaca | ||
|
|
d6dc5db185 | ||
|
|
58d1859640 | ||
|
|
dba648aea2 | ||
|
|
12f6206f88 | ||
|
|
7d9fd06b6d | ||
|
|
d6fbf16272 | ||
|
|
b68de683b0 | ||
|
|
2f9d025fbe | ||
|
|
9c1ffaba17 | ||
|
|
142df39cd2 | ||
|
|
ef79ccc299 | ||
|
|
6d2d96be5c | ||
|
|
8ff2a6e6c4 | ||
|
|
b793aa3394 | ||
|
|
be2cfb908a | ||
|
|
e34084b146 | ||
|
|
c1d7168260 | ||
|
|
b3a3709b72 | ||
|
|
dd59f3d026 | ||
|
|
ccb00ff391 | ||
|
|
b37970a6df | ||
|
|
2cd7fcfbd8 | ||
|
|
77819b06fe | ||
|
|
4e936b4cff | ||
|
|
b2362a85fa | ||
|
|
f45f351678 | ||
|
|
311171fa0a | ||
|
|
7e05f03f4d | ||
|
|
76826c1e80 | ||
|
|
18618efdc0 | ||
|
|
d1952dfc25 | ||
|
|
fe5f4f2727 | ||
|
|
fd7c907b8f | ||
|
|
0273255c2c | ||
|
|
e86160e530 | ||
|
|
9f7e0d611a | ||
|
|
0b523efa95 | ||
|
|
6b64499e24 | ||
|
|
e78e628bec | ||
|
|
ed8eb51c2f | ||
|
|
124d68ef68 | ||
|
|
3e802c1465 | ||
|
|
ac18e78897 | ||
|
|
e37ee39e88 | ||
|
|
fed16a4aa3 | ||
|
|
8c94dfce9e | ||
|
|
69c13dd052 | ||
|
|
a5fe54164e | ||
|
|
5ecd5a5a5c | ||
|
|
ed45347c23 | ||
|
|
3e0385479f | ||
|
|
36f833be91 | ||
|
|
8fb39f9ea4 | ||
|
|
5b84ebbc25 | ||
|
|
b0ec7867b5 | ||
|
|
4e4c59ce4d | ||
|
|
e9bf1c05ad | ||
|
|
7ac1fa5abf | ||
|
|
a489ac1d26 | ||
|
|
4d7a7442ce | ||
|
|
a19bce5a37 | ||
|
|
35782244bf | ||
|
|
7407429344 | ||
|
|
55c532f6e2 | ||
|
|
d3c8b5d731 | ||
|
|
cf09f98d7e | ||
|
|
d8e8a8e4e9 | ||
|
|
65210dea2f | ||
|
|
0c9b850872 | ||
|
|
99486830b7 | ||
|
|
74a62a46d3 | ||
|
|
d306041bcf | ||
|
|
ae8a924cd6 | ||
|
|
6ab1b9f787 | ||
|
|
46ddc440fe | ||
|
|
6bf8eacfbd | ||
|
|
b2fa4f220d | ||
|
|
2f175c304c | ||
|
|
79714e5708 | ||
|
|
7c5aa9c913 | ||
|
|
59b8bae182 | ||
|
|
35323ba624 | ||
|
|
8ca3741a52 | ||
|
|
c3c021774e | ||
|
|
6b811d635b | ||
|
|
97aecd3ddc | ||
|
|
c4fdef445e | ||
|
|
e642087360 | ||
|
|
098754125b | ||
|
|
6ce2d2723b | ||
|
|
ae4a864533 | ||
|
|
27d9322ced | ||
|
|
f5003080db | ||
|
|
79e11dda4c | ||
|
|
3b992edc21 | ||
|
|
f75f88840f | ||
|
|
3e1663bf18 | ||
|
|
9a60149d75 | ||
|
|
11cfef904b | ||
|
|
a45dcd307b | ||
|
|
54b483333f | ||
|
|
7f4a36038e | ||
|
|
990ec1a553 | ||
|
|
12307cbd56 | ||
|
|
6bd49a461e | ||
|
|
c9ed8a9360 | ||
|
|
120d6f9f5f | ||
|
|
0d30fc0e32 | ||
|
|
6f64cb71f2 | ||
|
|
7ce4264309 | ||
|
|
5385e6918b | ||
|
|
a8ad65000d | ||
|
|
7a6a834998 | ||
|
|
ae9ca0ac3b | ||
|
|
9fd23e9181 | ||
|
|
a288a1a2a4 | ||
|
|
33e2201524 | ||
|
|
34422dfef7 | ||
|
|
7999895323 | ||
|
|
c6635845f5 | ||
|
|
e770232e1d | ||
|
|
51dcf3a7c6 | ||
|
|
afd745917d | ||
|
|
aa8e12ef58 | ||
|
|
41bbda7bcf | ||
|
|
f19289362d | ||
|
|
71ef3dadc5 | ||
|
|
2d546d92b5 | ||
|
|
1360a73028 | ||
|
|
7de224831f | ||
|
|
e9cda93898 | ||
|
|
2c1f5a9f34 | ||
|
|
f0d6c5e1b1 | ||
|
|
d88d7ebebd | ||
|
|
17dcc2efd8 | ||
|
|
991df9c48f | ||
|
|
3391d7d3f4 | ||
|
|
bccb5e353b | ||
|
|
84b39f3d2b | ||
|
|
4ab0947cc8 | ||
|
|
8cbef14ea3 | ||
|
|
8e05105917 | ||
|
|
81babca775 | ||
|
|
fe8dd2a920 | ||
|
|
105ecd4221 | ||
|
|
3176cfcc56 | ||
|
|
11af41f3c0 | ||
|
|
6a24c10225 | ||
|
|
8c50589eba | ||
|
|
eaa134d474 | ||
|
|
3d61d95e44 | ||
|
|
d9d3c899a1 | ||
|
|
00f71eba77 | ||
|
|
1e547f1815 | ||
|
|
4b7bbe686a | ||
|
|
f744acd131 | ||
|
|
2be61379f8 | ||
|
|
227a1034cd | ||
|
|
a2f3d9a1b6 | ||
|
|
33f863e1e6 | ||
|
|
630dacd8bf | ||
|
|
4e161248b3 | ||
|
|
2172cc2d04 | ||
|
|
b49555e111 | ||
|
|
d634fcd4cf | ||
|
|
a7e972b3ce | ||
|
|
35273c64bd | ||
|
|
5be2d7bd39 | ||
|
|
749dfc0fba | ||
|
|
4f6bb02ab7 | ||
|
|
5a109c5752 | ||
|
|
756e363e92 | ||
|
|
d90a0cd0c8 | ||
|
|
6de9007c3a | ||
|
|
0b2584e2f1 | ||
|
|
1f59d114e8 | ||
|
|
69ac8617da | ||
|
|
ed00b4550c | ||
|
|
12bc4faf48 | ||
|
|
471c918ac3 | ||
|
|
012f256b77 | ||
|
|
0c23c16f3b | ||
|
|
ae67033417 | ||
|
|
1489d5cd5a | ||
|
|
0adb34b4d3 | ||
|
|
989c7b2ba0 | ||
|
|
1575d5e3e7 | ||
|
|
859522b028 | ||
|
|
ba8c8bc976 | ||
|
|
145e3e5c44 | ||
|
|
914a7e3c7b | ||
|
|
e6cb804055 | ||
|
|
f20ef2d11d | ||
|
|
471df3b659 | ||
|
|
b12ad405c3 | ||
|
|
a218564a24 | ||
|
|
a42da5b6da | ||
|
|
db76992c70 | ||
|
|
4071abcb56 | ||
|
|
3ab31c8bee | ||
|
|
8d74ef275e | ||
|
|
5b9640a1de | ||
|
|
f8c1087360 | ||
|
|
2368aeb5e8 | ||
|
|
f81e026e12 | ||
|
|
bb2d62a11c | ||
|
|
21a1791e7a | ||
|
|
75606559c6 | ||
|
|
0615e46d8a | ||
|
|
a4b58b4bd9 | ||
|
|
41c30fe704 | ||
|
|
7745848961 | ||
|
|
7a8e8de724 | ||
|
|
a45bf6d959 | ||
|
|
c6df38e753 | ||
|
|
0fa214f029 | ||
|
|
ef06e67c9f | ||
|
|
9ddb83a761 | ||
|
|
9b881ee11a | ||
|
|
87d2618020 | ||
|
|
bd2f22f059 | ||
|
|
170f03979e | ||
|
|
66f98656b0 | ||
|
|
e801a03984 | ||
|
|
979ba1c142 | ||
|
|
784c58e295 | ||
|
|
7c6b2faa1a | ||
|
|
fb5a146dee | ||
|
|
a8b555b773 | ||
|
|
dbe3944089 | ||
|
|
aa60424eae | ||
|
|
95ba0e1f8a | ||
|
|
afeb2b94cd | ||
|
|
0b50f424fa | ||
|
|
786d76bb73 | ||
|
|
8427ea208b | ||
|
|
701a52dd22 | ||
|
|
b897795c27 | ||
|
|
9dfff36edf | ||
|
|
9d4f98d3ee | ||
|
|
8770e95ee3 | ||
|
|
9ff9baa78c | ||
|
|
28326f2628 | ||
|
|
7c35a2e790 | ||
|
|
61c57e1866 | ||
|
|
488d1be1cc | ||
|
|
11d3e3c7ad | ||
|
|
a61b4a47cf | ||
|
|
0108135fe9 | ||
|
|
372b7e8e30 | ||
|
|
74b3ceec63 | ||
|
|
144fe06e60 | ||
|
|
bef01385b2 | ||
|
|
fa3ccf0fea | ||
|
|
d2bb7121cb | ||
|
|
2dbcd203ce | ||
|
|
1eb65dbc43 | ||
|
|
b066e08511 | ||
|
|
214d07f2ef | ||
|
|
16746dd2a0 | ||
|
|
bcec0cd902 | ||
|
|
6faf69a875 | ||
|
|
6f229a859b | ||
|
|
092904377f | ||
|
|
7277688de4 | ||
|
|
9e5ff432d7 | ||
|
|
5817daa4b3 | ||
|
|
51292f50dc | ||
|
|
b5e9e75751 | ||
|
|
f778b964fd | ||
|
|
06c14d2742 | ||
|
|
7441288cf5 | ||
|
|
7524cdf0b1 | ||
|
|
46dff9f52c | ||
|
|
afb0c85e9f | ||
|
|
af6bb18db2 | ||
|
|
c28d4c15a0 | ||
|
|
0c167a1833 | ||
|
|
f7938df5e4 | ||
|
|
5717677339 | ||
|
|
cffe9cd4f6 | ||
|
|
5da8c77b3a | ||
|
|
3cc652d113 | ||
|
|
7d82fb8f04 | ||
|
|
f1cbc9f775 | ||
|
|
58c6ba2f87 | ||
|
|
0fbd4b495b | ||
|
|
343274e1e2 | ||
|
|
bc729c0f8c | ||
|
|
09ce5ac892 | ||
|
|
2536b0b986 | ||
|
|
c8506387f6 | ||
|
|
79f2c7dd3d | ||
|
|
d91a83a137 | ||
|
|
0b21b8d976 | ||
|
|
842cb54867 | ||
|
|
a5628188d8 | ||
|
|
1b0e37be45 | ||
|
|
48ecfe0d98 | ||
|
|
b5b4a3a4f9 | ||
|
|
585d585cd3 | ||
|
|
42356c4e99 | ||
|
|
cd9aeba9f7 | ||
|
|
8a7a5f35c1 | ||
|
|
b24c5e7cf1 | ||
|
|
e8b7e2f0b9 | ||
|
|
b75e14e4f5 | ||
|
|
3e59c60477 | ||
|
|
e89b4fe2a4 | ||
|
|
73b0542b62 | ||
|
|
c9812c36c0 | ||
|
|
d62a2c0aaf | ||
|
|
ee15f063ce | ||
|
|
5f0a683ec1 | ||
|
|
6ae9de7df3 | ||
|
|
19aa41ab5b | ||
|
|
0494b3a9a6 | ||
|
|
01d9dc9033 | ||
|
|
47b8d8d8b2 | ||
|
|
6e3453cd90 | ||
|
|
4e10451bea | ||
|
|
81d5c8f449 | ||
|
|
79fa71fc84 | ||
|
|
f6378daa89 | ||
|
|
f2a4eb1b65 | ||
|
|
2d19c35177 | ||
|
|
9787f7e377 | ||
|
|
3abac3e7ac | ||
|
|
fddf75b40b | ||
|
|
a7878243ee |
@@ -16,5 +16,6 @@
|
||||
"rules": {
|
||||
"no-console": "off"
|
||||
},
|
||||
"settings": {}
|
||||
"settings": {},
|
||||
"plugins": ["cypress"]
|
||||
}
|
||||
|
||||
1
.gitignore
vendored
@@ -112,3 +112,4 @@ firebase/.env
|
||||
.elasticbeanstalk/*
|
||||
!.elasticbeanstalk/*.cfg.yml
|
||||
!.elasticbeanstalk/*.global.yml
|
||||
logs/oAuthClient-log.log
|
||||
|
||||
@@ -1 +1 @@
|
||||
client_max_body_size 15M;
|
||||
client_max_body_size 50M;
|
||||
12
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"xml.fileAssociations": [
|
||||
{
|
||||
"pattern": "**/Test.xml",
|
||||
"systemId": "file:///Users/pfic/Downloads/IMEX.xsd"
|
||||
},
|
||||
{
|
||||
"pattern": "**/IMEX.xml",
|
||||
"systemId": "logs/IMEX.xsd"
|
||||
}
|
||||
]
|
||||
}
|
||||
17689
_reference/CDK Testing Accounts
Normal file
586
_reference/OEC/Audatex.xsl
Normal file
@@ -0,0 +1,586 @@
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
|
||||
<xsl:template match="/">
|
||||
<xsl:for-each select="//TranslatedData">
|
||||
<xsl:element name="TranslatedData">
|
||||
<xsl:attribute name="TranslationOutputFile">
|
||||
<xsl:value-of select="@TranslationOutputFile"/>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="Details/@PrgID">
|
||||
<xsl:copy-of select="Details" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:element name="Details">
|
||||
<xsl:attribute name="PrgID">OECTrans.ImportTrans</xsl:attribute>
|
||||
<xsl:for-each select="Details/@*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="Details/*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:element name="Header">
|
||||
<xsl:attribute name="RONum">
|
||||
<xsl:value-of select="//Envelope/@RONum" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerFName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerLName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VIN">
|
||||
<xsl:value-of select="//Vehicle/@TransVIN" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Mileage">
|
||||
<xsl:value-of select="//Vehicle/@TransMileage" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Year">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Make">
|
||||
<xsl:if test="//Vehicle/@ManufName[. != '']" >
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Vehicle/@ManufName[. = 'Geo']">CHEV</xsl:when>
|
||||
<xsl:when test="//Vehicle/@ManufName[. = 'Chev-GMC Truck']">CHEV</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:if>
|
||||
<xsl:if test="//Vehicle/@ManufName[. = '']" >
|
||||
<xsl:value-of select="//Vehicle/@ManufCode" />
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Model">
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Description">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LastSupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Envelope/@TransactionType = 'E'">0</xsl:when>
|
||||
<xsl:when test="substring(//Envelope/@SupplementNum, 1, 1) = 'S'">
|
||||
<xsl:value-of select="substring(//Envelope/@SupplementNum, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:apply-templates select="PartsList" />
|
||||
<xsl:element name="Envelope">
|
||||
<xsl:element name="Software">
|
||||
<xsl:attribute name="Manifest">Audatex.xml</xsl:attribute>
|
||||
<xsl:attribute name="Descriptor">Audatex.xsl</xsl:attribute>
|
||||
<xsl:attribute name="System">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Version">
|
||||
<xsl:value-of select="//Envelope/@SoftwareVersion"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SystemName">
|
||||
<xsl:value-of select="//Envelope/@SystemName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFileID">
|
||||
<xsl:value-of select="//Envelope/@EstimateFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="UniqueFileID">
|
||||
<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateID">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@SoftwareVersion"/>-<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateIDv2">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFormatVersion">
|
||||
<xsl:value-of select="//Envelope/@EMSVersion"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
<xsl:element name="Totals">
|
||||
<xsl:attribute name="GrandTotalAmount">
|
||||
<xsl:value-of select="//Total/@GrandTotalAmount"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Administrative">
|
||||
<xsl:element name="Owner">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCompanyName"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr1"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr2"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCity"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@OwnerState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@OwnerZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@OwnerZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@OwnerZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@OwnerZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@OwnerZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCountry"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/> x<xsl:value-of select="//Admin/@OwnerPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/> x<xsl:value-of select="//Admin/@OwnerPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/> x<xsl:value-of select="//Admin/@OwnerFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerEmail"/>-->
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="InsuranceCompany">
|
||||
<xsl:attribute name="Id">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Name">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin/@InsuranceCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@InsuranceState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@InsuranceZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@InsuranceZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@InsuranceZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@InsuranceZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@InsuranceZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin/@InsuranceCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/> x<xsl:value-of select="//Admin/@InsurancePhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/> x<xsl:value-of select="//Admin/@InsurancePhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsuranceFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/> x<xsl:value-of select="//Admin/@InsuranceFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin/@InsuranceEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Insured">
|
||||
<xsl:attribute name="LastName">
|
||||
<xsl:value-of select="//Admin/@InsuranceLName" />
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Claim">
|
||||
<xsl:attribute name="Number">
|
||||
<xsl:value-of select="//Admin/@ClaimNumber"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Estimator">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="BodyShopCity">
|
||||
<xsl:value-of select="//Admin2/@BodyShopCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="BodyShopName">
|
||||
<xsl:value-of select="//Admin2/@BodyShopName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin2/@EstimatorState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin2/@EstimatorZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin2/@EstimatorZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin2/@EstimatorZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin2/@EstimatorZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)=9">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin2/@EstimatorZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)>4">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/> x<xsl:value-of select="//Admin2/@EstimatorPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/> x<xsl:value-of select="//Admin2/@EstimatorPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/> x<xsl:value-of select="//Admin2/@EstimatorFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin2/@EstimatorEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="RepairInformation">
|
||||
<xsl:attribute name="VehicleDateIn">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleInDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleInTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleInTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimatedVehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@TargetVehicleOutDate,' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleOutDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template match="PartsList">
|
||||
<xsl:element name="PartsList" >
|
||||
<xsl:for-each select="Part">
|
||||
<xsl:element name="Part" >
|
||||
<!-- Part number translation rules -->
|
||||
<xsl:variable name="OEMPartNumber">
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) != ' GM PART'">
|
||||
<xsl:value-of select="@TDPartNum" />
|
||||
</xsl:if>
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) = ' GM PART'">
|
||||
<xsl:value-of select="substring-before(@TDPartNum,' GM PART')" />
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="AltPartNumber">
|
||||
<xsl:value-of select="@AltPartNum"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartType">
|
||||
<xsl:value-of select="@PartType"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN' or @PartType='PAG'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType!='PAN' and @PartType!='PAG'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$AltPartNumber!=''">
|
||||
<xsl:value-of select="$AltPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="$OEMPartNumber!=''">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>Salvage or Assembly</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType!='PAN'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAA'">PAN</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:attribute name="TDPartNum">
|
||||
<xsl:value-of select="$PrimaryPartNumber"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartNum">
|
||||
<xsl:value-of select="$SecondaryPartNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalPartType">
|
||||
<xsl:value-of select="$PrimaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalAltPartType">
|
||||
<xsl:value-of select="$SecondaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$PrimaryPartType='PAN' or $PrimaryPartType='PAP'">1</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAA' or $PrimaryPartType='PATR'">2</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAM' or $PrimaryPartType='PAC' or $PrimaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$SecondaryPartType='PAN'">1</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAA' or $SecondaryPartType='PATR'">2</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAM' or $SecondaryPartType='PAC' or $SecondaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartDesc">
|
||||
<xsl:value-of select="@TDPartDesc" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDEstimate">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN'">
|
||||
<xsl:value-of select="@TDEstimate" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAM'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAA'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAL'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartQty">
|
||||
<xsl:value-of select="@TDPartQty" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LineNumber">
|
||||
<xsl:value-of select="@LineNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SequenceNumber">
|
||||
<xsl:value-of select="@SequenceNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@SupplementLevel = 'E'">0</xsl:when>
|
||||
<xsl:when test="substring(@SupplementLevel, 1, 1) = 'S'">
|
||||
<xsl:value-of select="substring(@SupplementLevel, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborType">
|
||||
<xsl:value-of select="@LaborType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborHours">
|
||||
<xsl:value-of select="@LaborHours" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OperationCode">
|
||||
<xsl:value-of select="@LaborOp" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="PriceIncluded">
|
||||
<xsl:value-of select="@PriceIncluded" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="MarkUp">
|
||||
<xsl:value-of select="@MarkUp" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="CLPart">
|
||||
<!-- CLPart is false if TRAN_CODE == 2 or TRAN_CODE == 3 -->
|
||||
<!-- CLPart is false if PartType is not 'PAN','PAP','PAL','PAG', 'PAM', or 'PAA', or 'PAC' or 'PATR' -->
|
||||
<!-- CLPart is false if LaborCode is only labor -->
|
||||
<!-- CLPart is false if OpCode is not "Remove/Replace" or "Remove/Replace Partial" -->
|
||||
<!-- If LaborOp is OP1, then allow the part to import CP 12/28/08 for Shop Client Release 4.1.4 -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="@TransactionCode='3'">False</xsl:when>
|
||||
<xsl:when test="@TransactionCode='1' or @TransactionCode=' ' or @TransactionCode='' or @TransactionCode='2'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN' or @PartType='PAG' or @PartType='PAM' or @PartType='PAP' or @PartType='PAL' or @PartType='PAA' or @PartType='PAC' or @PartType='PATR'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@LaborType='LAD' or @LaborType='LAE' or @LaborType='LAU' or @LaborType='LAT'">False</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:choose>
|
||||
<!--xsl:when test="@LaborOp='OP0'">False</xsl:when -->
|
||||
<xsl:when test="@LaborOp='OP1'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP2'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP3'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP4'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP5'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP6'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP7'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP8'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP9'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP10'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP13'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP14'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP15'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP16'">False</xsl:when>
|
||||
<xsl:otherwise>True</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
131
_reference/OEC/AudatexMapping.xml
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TranslationDescriptor>
|
||||
<FileTranslations FormatName="ADP EMS" ElementName="Estimate" Description="Translation Descriptor for a ADP ShopLink Estimate, Version EMS 2.0">
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.env">
|
||||
<DBFFileTranslation ID="ID1" ElementName="Envelope" Description="Envelope Table">
|
||||
<DBFFieldSpec FieldName="RO_ID" Form="attribute" Name="RONum" FieldType="" Description="RO Number"/>
|
||||
<DBFFieldSpec FieldName="UNQFILE_ID" Form="attribute" Name="UniqueFileID" FieldType="" Description="Unique File Identifier"/>
|
||||
<DBFFieldSpec FieldName="ESTFILE_ID" Form="attribute" Name="EstimateFileID" FieldType="" Description="Estimate File Identifier"/>
|
||||
<DBFFieldSpec FieldName="INCL_ADMIN" Form="attribute" Name="IncludesAdminInfo" FieldType="Boolean" Description="Includes Admin Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VEH" Form="attribute" Name="IncludesVehicleInfo" FieldType="Boolean" Description="Includes Vehicle Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_EST" Form="attribute" Name="IncludesEstimateInfo" FieldType="Boolean" Description="Includes Estimate Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_PROFL" Form="attribute" Name="IncludesProfileInfo" FieldType="Boolean" Description="Includes Profile Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_TOTAL" Form="attribute" Name="IncludesTotalsInfo" FieldType="Boolean" Description="Includes Totals Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VENDR" Form="attribute" Name="IncludesVendorInfo" FieldType="Boolean" Description="Includes Vendor Info Flag"/>
|
||||
<DBFFieldSpec FieldName="EMS_VER" Form="attribute" Name="EMSVersion" FieldType="" Description="EMS Version Number"/>
|
||||
<DBFFieldSpec FieldName="SUPP_NO" Form="attribute" Name="SupplementNum" FieldType="" Description="Supplement Number"/>
|
||||
<DBFFieldSpec FieldName="TRANS_TYPE" Form="attribute" Name="TransactionType" FieldType="" Description="Transaction Type"/>
|
||||
<DBFFieldSpec FieldName="EST_SYSTEM" Form="attribute" Name="EstimatingSystem" FieldType="" Description="Estimating System Software"/>
|
||||
<DBFFieldSpec FieldName="SW_VERSION" Form="attribute" Name="SoftwareVersion" FieldType="" Description="Software Version Identifier"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.LIN">
|
||||
<DBFFileTranslation ID="ID2" ElementSetName="PartsList" ElementName="Part" Description="Parts List Table">
|
||||
<DBFFieldSpec FieldName="OEM_PARTNO" Form="attribute" Name="TDPartNum" FieldType="" Description="Part Number"/>
|
||||
<DBFFieldSpec FieldName="ALT_PARTNO" Form="attribute" Name="AltPartNum" FieldType="" Description="Alternate Part Number"/>
|
||||
<DBFFieldSpec FieldName="ACT_PRICE" Form="attribute" Name="ActPrice" FieldType="" Description="Actual Part Price"/>
|
||||
<DBFFieldSpec FieldName="LINE_DESC" Form="attribute" Name="TDPartDesc" FieldType="" Description="Part Description"/>
|
||||
<DBFFieldSpec FieldName="DB_PRICE" Form="attribute" Name="TDEstimate" FieldType="" Description="DB_Price"/>
|
||||
<DBFFieldSpec FieldName="PART_QTY" Form="attribute" Name="TDPartQty" FieldType="" Description="Part Quantity"/>
|
||||
<DBFFieldSpec FieldName="PART_TYPE" Form="attribute" Name="PartType" FieldType="" Description="Part Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LBR_TY" Form="attribute" Name="LaborType" FieldType="" Description="Labor Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LB_HRS" Form="attribute" Name="LaborHours" FieldType="" Description="Labor Hours"/>
|
||||
<DBFFieldSpec FieldName="LBR_OP" Form="attribute" Name="LaborOp" FieldType="" Description="Labor Op"/>
|
||||
<DBFFieldSpec FieldName="LINE_NO" Form="attribute" Name="LineNumber" FieldType="" Description="Line number"/>
|
||||
<DBFFieldSpec FieldName="UNQ_SEQ" Form="attribute" Name="SequenceNumber" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="LINE_IND" Form="attribute" Name="SupplementLevel" FieldType="" Description="Supplement Level"/>
|
||||
<DBFFieldSpec FieldName="TRAN_CODE" Form="attribute" Name="TransactionCode" FieldType="" Description="Transaction Code"/>
|
||||
<DBFFieldSpec FieldName="PRICE_INC" Form="attribute" Name="PriceIncluded" FieldType="" Description="Price Included"/>
|
||||
<DBFFieldSpec FieldName="PRT_DSMK_P" Form="attribute" Name="MarkUp" FieldType="" Description="Price Mark up for non OEM parts"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.VEH">
|
||||
<DBFFileTranslation ID="ID3" ElementName="Vehicle" Description="Vehicle Table">
|
||||
<DBFFieldSpec FieldName="V_VIN" Form="attribute" Name="TransVIN" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="V_MODEL_YR" Form="attribute" Name="TransYear" FieldType="" Description="V_MODEL_YR"/>
|
||||
<DBFFieldSpec FieldName="V_MAKEDESC" Form="attribute" Name="ManufName" FieldType="" Description="V_MAKEDESC"/>
|
||||
<DBFFieldSpec FieldName="V_MAKECODE" Form="attribute" Name="ManufCode" FieldType="" Description="V_MAKECODE"/>
|
||||
<DBFFieldSpec FieldName="V_MODEL" Form="attribute" Name="TransModel" FieldType="" Description="V_MODEL"/>
|
||||
<DBFFieldSpec FieldName="V_MILEAGE" Form="attribute" Name="TransMileage" FieldType="" Description="V_MILEAGE"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD1">
|
||||
<DBFFileTranslation ID="ID4" ElementName="Admin" Description="Administrative information">
|
||||
<DBFFieldSpec FieldName="OWNR_LN" Form="attribute" Name="OwnerL" FieldType="" Description="Owner Lastname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FN" Form="attribute" Name="OwnerF" FieldType="" Description="Owner Firstname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CO_NM" Form="attribute" Name="OwnerCompanyName" FieldType="" Description="Owner Company Name"/>
|
||||
<DBFFieldSpec FieldName="OWNR_TITLE" Form="attribute" Name="OwnerTitle" FieldType="" Description="Owner Title"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR1" Form="attribute" Name="OwnerAddr1" FieldType="" Description="Owner Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR2" Form="attribute" Name="OwnerAddr2" FieldType="" Description="Owner Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CITY" Form="attribute" Name="OwnerCity" FieldType="" Description="Owner City"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ST" Form="attribute" Name="OwnerState" FieldType="" Description="Owner State"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ZIP" Form="attribute" Name="OwnerZip" FieldType="" Description="Owner Zip"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CTRY" Form="attribute" Name="OwnerCountry" FieldType="" Description="Owner Country"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1" Form="attribute" Name="OwnerPhone1" FieldType="" Description="Owner Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1X" Form="attribute" Name="OwnerPhone1Ext" FieldType="" Description="Owner Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2" Form="attribute" Name="OwnerPhone2" FieldType="" Description="Owner Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2X" Form="attribute" Name="OwnerPhone2Ext" FieldType="" Description="Owner Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAX" Form="attribute" Name="OwnerFax" FieldType="" Description="Owner Fax"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAXX" Form="attribute" Name="OwnerFaxExt" FieldType="" Description="Owner Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_EA" Form="attribute" Name="OwnerEmail" FieldType="" Description="Owner Email Address"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_NM" Form="attribute" Name="InsuranceCompanyName" FieldType="" Description="Insurance Company Name"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_ID" Form="attribute" Name="InsuranceCompanyID" FieldType="" Description="Insurance Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR1" Form="attribute" Name="InsuranceAddr1" FieldType="" Description="Insurance Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR2" Form="attribute" Name="InsuranceAddr2" FieldType="" Description="Insurance Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="INS_CITY" Form="attribute" Name="InsuranceCity" FieldType="" Description="Insurance City"/>
|
||||
<DBFFieldSpec FieldName="INS_ST" Form="attribute" Name="InsuranceState" FieldType="" Description="Insurance State"/>
|
||||
<DBFFieldSpec FieldName="INS_ZIP" Form="attribute" Name="InsuranceZip" FieldType="" Description="Insurance Zip"/>
|
||||
<DBFFieldSpec FieldName="INS_CTRY" Form="attribute" Name="InsuranceCountry" FieldType="" Description="Insurance Country"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1" Form="attribute" Name="InsurancePhone1" FieldType="" Description="Insurance Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1X" Form="attribute" Name="InsurancePhone1Ext" FieldType="" Description="Insurance Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2" Form="attribute" Name="InsurancePhone2" FieldType="" Description="Insurance Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2X" Form="attribute" Name="InsurancePhone2Ext" FieldType="" Description="Insurance Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_FAX" Form="attribute" Name="InsuranceFax" FieldType="" Description="Insurance Fax"/>
|
||||
<DBFFieldSpec FieldName="INS_FAXX" Form="attribute" Name="InsuranceFaxExt" FieldType="" Description="Insurance Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_EA" Form="attribute" Name="InsuranceEmail" FieldType="" Description="Insurance Email Address"/>
|
||||
<DBFFieldSpec FieldName="INSD_LN" Form="attribute" Name="InsuranceLName" FieldType="" Description="Insurance Last Name"/>
|
||||
<DBFFieldSpec FieldName="CLM_NO" Form="attribute" Name="ClaimNumber" FieldType="" Description="Claim Number"/>
|
||||
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD2">
|
||||
<DBFFileTranslation ID="ID5" ElementName="Admin2" Description="Administrative information2">
|
||||
<DBFFieldSpec FieldName="EST_CT_LN" Form="attribute" Name="EstimatorL" FieldType="" Description="Estimator Lastname"/>
|
||||
<DBFFieldSpec FieldName="EST_CT_FN" Form="attribute" Name="EstimatorF" FieldType="" Description="Estimator Firstname"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_NM" Form="attribute" Name="EstimatorCompanyName" FieldType="" Description="Estimator Company Name"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_ID" Form="attribute" Name="EstimatorCompanyID" FieldType="" Description="Estimator Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR1" Form="attribute" Name="EstimatorAddr1" FieldType="" Description="Estimator Address1"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR2" Form="attribute" Name="EstimatorAddr2" FieldType="" Description="Estimator Address2"/>
|
||||
<DBFFieldSpec FieldName="EST_CITY" Form="attribute" Name="EstimatorCity" FieldType="" Description="Estimator City"/>
|
||||
<DBFFieldSpec FieldName="EST_ST" Form="attribute" Name="EstimatorState" FieldType="" Description="Estimator State"/>
|
||||
<DBFFieldSpec FieldName="EST_ZIP" Form="attribute" Name="EstimatorZip" FieldType="" Description="Estimator Zip"/>
|
||||
<DBFFieldSpec FieldName="EST_CTRY" Form="attribute" Name="EstimatorCountry" FieldType="" Description="Estimator Country"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1" Form="attribute" Name="EstimatorPhone1" FieldType="" Description="Estimator Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1X" Form="attribute" Name="EstimatorPhone1Ext" FieldType="" Description="Estimator Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2" Form="attribute" Name="EstimatorPhone2" FieldType="" Description="Estimator Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2X" Form="attribute" Name="EstimatorPhone2Ext" FieldType="" Description="Estimator Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_FAX" Form="attribute" Name="EstimatorFax" FieldType="" Description="Estimator Fax"/>
|
||||
<DBFFieldSpec FieldName="EST_FAXX" Form="attribute" Name="EstimatorFaxExt" FieldType="" Description="Estimator Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_EA" Form="attribute" Name="EstimatorEmail" FieldType="" Description="Estimator Email Address"/>
|
||||
<DBFFieldSpec FieldName="EST_LIC_NO" Form="attribute" Name="EstimatorLicenseNumber" FieldType="" Description="Estimator License Number"/>
|
||||
<DBFFieldSpec FieldName="EST_FILENO" Form="attribute" Name="EstimatorFileNumber" FieldType="" Description="Estimator File Number"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_DATE" Form="attribute" Name="VehicleInDate" FieldType="" Description="Date arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_TIME" Form="attribute" Name="VehicleInTime" FieldType="" Description="Time arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="TAR_DATE" Form="attribute" Name="TargetVehicleOutDate" FieldType="" Description="Target date to be completed"/>
|
||||
<DBFFieldSpec FieldName="TAR_TIME" Form="attribute" Name="TargetVehicleOutTime" FieldType="" Description="Target time to be completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPDATE" Form="attribute" Name="VehicleOutDate" FieldType="" Description="Date completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPTIME" Form="attribute" Name="VehicleOutTime" FieldType="" Description="Time completed"/>
|
||||
<DBFFieldSpec FieldName="RF_CITY" Form="attribute" Name="BodyShopCity" FieldType="" Description="Body Shop City"/>
|
||||
<DBFFieldSpec FieldName="RF_CO_NM" Form="attribute" Name="BodyShopName" FieldType="" Description="Body Shop Name"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.TTL">
|
||||
<DBFFileTranslation ID="ID6" ElementName="Total" Description="Total Table">
|
||||
<DBFFieldSpec FieldName="G_TTL_AMT" Form="attribute" Name="GrandTotalAmount" FieldType="" Description=""/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
</FileTranslations>
|
||||
<StyleSheetTranslation>
|
||||
<StyleSheetURL>Audatex.xsl</StyleSheetURL>
|
||||
</StyleSheetTranslation>
|
||||
</TranslationDescriptor>
|
||||
607
_reference/OEC/CCC.xsl
Normal file
@@ -0,0 +1,607 @@
|
||||
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
|
||||
<xsl:template match="/">
|
||||
<xsl:for-each select="//TranslatedData">
|
||||
<xsl:element name="TranslatedData">
|
||||
<xsl:attribute name="TranslationOutputFile">
|
||||
<xsl:value-of select="@TranslationOutputFile"/>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="Details/@PrgID">
|
||||
<xsl:copy-of select="Details" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:element name="Details">
|
||||
<xsl:attribute name="PrgID">OECTrans.ImportTrans</xsl:attribute>
|
||||
<xsl:for-each select="Details/@*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="Details/*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:element name="Header">
|
||||
<xsl:attribute name="RONum">
|
||||
<xsl:value-of select="//Envelope/@RONum" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerFName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerLName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VIN">
|
||||
<xsl:value-of select="//Vehicle/@TransVIN" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Mileage">
|
||||
<xsl:value-of select="//Vehicle/@TransMileage" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Year">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Make">
|
||||
<xsl:if test="//Vehicle/@ManufName[. != '']" >
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
</xsl:if>
|
||||
<xsl:if test="//Vehicle/@ManufName[. = '']" >
|
||||
<xsl:value-of select="//Vehicle/@ManufCode" />
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Model">
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Description">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LastSupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Envelope/@TransactionType = 'E'">0</xsl:when>
|
||||
<xsl:when test="//Envelope/@TransactionType = 'S'">
|
||||
<xsl:value-of select="substring(//Envelope/@SupplementNum, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:apply-templates select="PartsList" />
|
||||
<xsl:element name="Envelope">
|
||||
<xsl:element name="Software">
|
||||
<xsl:attribute name="Manifest">CCC.xml</xsl:attribute>
|
||||
<xsl:attribute name="Descriptor">CCC.xsl</xsl:attribute>
|
||||
<xsl:attribute name="System">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Version">
|
||||
<xsl:value-of select="//Envelope/@SoftwareVersion"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SystemName">
|
||||
<xsl:value-of select="//Envelope/@SystemName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFileID">
|
||||
<xsl:value-of select="//Envelope/@EstimateFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="UniqueFileID">
|
||||
<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateID">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@SoftwareVersion"/>-<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateIDv2">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFormatVersion">
|
||||
<xsl:value-of select="//Envelope/@EMSVersion"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
<xsl:element name="Totals">
|
||||
<xsl:attribute name="GrandTotalAmount">
|
||||
<xsl:value-of select="//Total/@GrandTotalAmount"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Administrative">
|
||||
<xsl:element name="Owner">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCompanyName"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr1"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr2"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCity"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@OwnerState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@OwnerZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@OwnerZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@OwnerZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@OwnerZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@OwnerZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCountry"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/> x<xsl:value-of select="//Admin/@OwnerPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/> x<xsl:value-of select="//Admin/@OwnerPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/> x<xsl:value-of select="//Admin/@OwnerFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerEmail"/>-->
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="InsuranceCompany">
|
||||
<xsl:attribute name="Id">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Name">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin/@InsuranceCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@InsuranceState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@InsuranceZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@InsuranceZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@InsuranceZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@InsuranceZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@InsuranceZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin/@InsuranceCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/> x<xsl:value-of select="//Admin/@InsurancePhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/> x<xsl:value-of select="//Admin/@InsurancePhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsuranceFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/> x<xsl:value-of select="//Admin/@InsuranceFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin/@InsuranceEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Insured">
|
||||
<xsl:attribute name="LastName">
|
||||
<xsl:value-of select="//Admin/@InsuranceLName" />
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Claim">
|
||||
<xsl:attribute name="Number">
|
||||
<xsl:value-of select="//Admin/@ClaimNumber"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Estimator">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin2/@EstimatorState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin2/@EstimatorZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin2/@EstimatorZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin2/@EstimatorZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin2/@EstimatorZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)=9">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin2/@EstimatorZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)>4">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/> x<xsl:value-of select="//Admin2/@EstimatorPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/> x<xsl:value-of select="//Admin2/@EstimatorPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/> x<xsl:value-of select="//Admin2/@EstimatorFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin2/@EstimatorEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="RepairInformation">
|
||||
<xsl:attribute name="VehicleDateIn">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleInDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleInTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleInTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimatedVehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@TargetVehicleOutDate,' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleOutDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template match="PartsList">
|
||||
<xsl:element name="PartsList" >
|
||||
<xsl:for-each select="Part">
|
||||
<xsl:element name="Part" >
|
||||
<!-- Part number translation rules -->
|
||||
<xsl:variable name="OEMPartNumber">
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) != ' GM PART'">
|
||||
<xsl:value-of select="@TDPartNum" />
|
||||
</xsl:if>
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) = ' GM PART'">
|
||||
<xsl:value-of select="substring-before(@TDPartNum,' GM PART')" />
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="AltPartNumber">
|
||||
<xsl:value-of select="@AltPartNum"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartType">
|
||||
<!-- RoseP modified to convert PAP to PAN -->
|
||||
<!--<xsl:value-of select="@PartType"/>-->
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAP'">PAN</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@PartType"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAA'">
|
||||
<xsl:value-of select="$AltPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAL'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$AltPartNumber!=''">
|
||||
<xsl:value-of select="$AltPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="$OEMPartNumber!=''">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>Salvage or Assembly</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAG'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<!-- RoseP added Dec 08, 06 -->
|
||||
<xsl:when test="@PartType='PAP'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAM'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$AltPartNumber!=''">
|
||||
<xsl:value-of select="$AltPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAA'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAM'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAA'">PAN</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:attribute name="TDPartNum">
|
||||
<xsl:value-of select="$PrimaryPartNumber"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartNum">
|
||||
<xsl:value-of select="$SecondaryPartNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalPartType">
|
||||
<xsl:value-of select="$PrimaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalAltPartType">
|
||||
<xsl:value-of select="$SecondaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$PrimaryPartType='PAN'">1</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAA'">2</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAM'">4</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$SecondaryPartType='PAN'">1</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAA'">2</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAM'">4</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartDesc">
|
||||
<xsl:value-of select="@TDPartDesc" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDLineRef">
|
||||
<xsl:value-of select="@TDLineRef" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDEstimate">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN'">
|
||||
<xsl:value-of select="@TDEstimate" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAM'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAA'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAL'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartQty">
|
||||
<xsl:value-of select="@TDPartQty" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LineNumber">
|
||||
<xsl:value-of select="@LineNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SequenceNumber">
|
||||
<xsl:value-of select="@SequenceNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@SupplementLevel = 'E01'">0</xsl:when>
|
||||
<xsl:when test="substring(@SupplementLevel, 1, 1) = 'S'">
|
||||
<xsl:value-of select="substring(@SupplementLevel, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborType">
|
||||
<xsl:value-of select="@LaborType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborHours">
|
||||
<xsl:value-of select="@LaborHours" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OperationCode">
|
||||
<xsl:value-of select="@LaborOp" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="CLPart">
|
||||
<!-- CLPart is false if TRAN_CODE == 2 or TRAN_CODE == 3 -->
|
||||
<!-- CLPart is false if PartType is not 'PAN','PAP','PAL','PAG', 'PAM', 'PAA', 'PAO', 'PAR', or '' -->
|
||||
<!-- CLPart is false if LaborCode is only labor -->
|
||||
<!-- CLPart is false if OpCode is not "Remove/Replace" or "Remove/Replace Partial" or "Repair, Partial" -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="@TransactionCode='3'">False</xsl:when>
|
||||
<xsl:when test="@TransactionCode='1' or @TransactionCode ='2'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN' or @PartType='PAG' or @PartType='PAM' or @PartType='PAP' or @PartType='PAL' or @PartType='PAA' or @PartType='PAO' or @PartType='PAR' or @PartType=''" >
|
||||
<!-- we now handle blank part types-->
|
||||
<xsl:choose>
|
||||
<xsl:when test="@LaborType='LAD' or @LaborType='LAE' or @LaborType='LAU' or @LaborType='LAT'">False</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:choose>
|
||||
<xsl:when test="@LaborOp=''">False</xsl:when>
|
||||
<!--Needed for Blank Part Type-->
|
||||
<xsl:when test="@LaborOp='OP0'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP1'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP2'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP3'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP4'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP5'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP6'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP7'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP8'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP9'">False</xsl:when>
|
||||
<!-- RoseP removed OP10 Dec 08, 06 -->
|
||||
<!-- <xsl:when test="@LaborOp='OP10'">False</xsl:when> -->
|
||||
<xsl:when test="@LaborOp='OP13'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP14'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP15'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP16'">False</xsl:when>
|
||||
<xsl:otherwise>True</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
129
_reference/OEC/CCCMapping.xml
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TranslationDescriptor>
|
||||
<FileTranslations FormatName="CCC" ElementName="Estimate" Description="Translation Descriptor for a CCC Estimate, Version 2.0">
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.env">
|
||||
<DBFFileTranslation ID="ID1" ElementName="Envelope" Description="Envelope Table">
|
||||
<DBFFieldSpec FieldName="RO_ID" Form="attribute" Name="RONum" FieldType="" Description="RO Number"/>
|
||||
<DBFFieldSpec FieldName="UNQFILE_ID" Form="attribute" Name="UniqueFileID" FieldType="" Description="Unique File Identifier"/>
|
||||
<DBFFieldSpec FieldName="ESTFILE_ID" Form="attribute" Name="EstimateFileID" FieldType="" Description="Estimate File Identifier"/>
|
||||
<DBFFieldSpec FieldName="INCL_ADMIN" Form="attribute" Name="IncludesAdminInfo" FieldType="Boolean" Description="Includes Admin Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VEH" Form="attribute" Name="IncludesVehicleInfo" FieldType="Boolean" Description="Includes Vehicle Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_EST" Form="attribute" Name="IncludesEstimateInfo" FieldType="Boolean" Description="Includes Estimate Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_PROFL" Form="attribute" Name="IncludesProfileInfo" FieldType="Boolean" Description="Includes Profile Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_TOTAL" Form="attribute" Name="IncludesTotalsInfo" FieldType="Boolean" Description="Includes Totals Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VENDR" Form="attribute" Name="IncludesVendorInfo" FieldType="Boolean" Description="Includes Vendor Info Flag"/>
|
||||
<DBFFieldSpec FieldName="EMS_VER" Form="attribute" Name="EMSVersion" FieldType="" Description="EMS Version Number"/>
|
||||
<DBFFieldSpec FieldName="SUPP_NO" Form="attribute" Name="SupplementNum" FieldType="" Description="Supplement Number"/>
|
||||
<DBFFieldSpec FieldName="TRANS_TYPE" Form="attribute" Name="TransactionType" FieldType="" Description="Transaction Type"/>
|
||||
<DBFFieldSpec FieldName="EST_SYSTEM" Form="attribute" Name="EstimatingSystem" FieldType="" Description="Estimating System Software"/>
|
||||
<DBFFieldSpec FieldName="SW_VERSION" Form="attribute" Name="SoftwareVersion" FieldType="" Description="Software Version Identifier"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.LIN">
|
||||
<DBFFileTranslation ID="ID2" ElementSetName="PartsList" ElementName="Part" Description="Parts List Table">
|
||||
<DBFFieldSpec FieldName="OEM_PARTNO" Form="attribute" Name="TDPartNum" FieldType="" Description="Part Number"/>
|
||||
<DBFFieldSpec FieldName="ALT_PARTNO" Form="attribute" Name="AltPartNum" FieldType="" Description="Alternate Part Number"/>
|
||||
<DBFFieldSpec FieldName="ACT_PRICE" Form="attribute" Name="ActPrice" FieldType="" Description="Actual Part Price"/>
|
||||
<DBFFieldSpec FieldName="LINE_DESC" Form="attribute" Name="TDPartDesc" FieldType="" Description="Part Description"/>
|
||||
<DBFFieldSpec FieldName="DB_PRICE" Form="attribute" Name="TDEstimate" FieldType="" Description="DB_Price"/>
|
||||
<DBFFieldSpec FieldName="PART_QTY" Form="attribute" Name="TDPartQty" FieldType="" Description="PART_QTY"/>
|
||||
<DBFFieldSpec FieldName="LINE_NO" Form="attribute" Name="LineNumber" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="UNQ_SEQ" Form="attribute" Name="SequenceNumber" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="PART_TYPE" Form="attribute" Name="PartType" FieldType="" Description="Part Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LBR_TY" Form="attribute" Name="LaborType" FieldType="" Description="Labor Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LB_HRS" Form="attribute" Name="LaborHours" FieldType="" Description="Labor Hours"/>
|
||||
<DBFFieldSpec FieldName="LBR_OP" Form="attribute" Name="LaborOp" FieldType="" Description="Labor Op"/>
|
||||
<DBFFieldSpec FieldName="LINE_IND" Form="attribute" Name="SupplementLevel" FieldType="" Description="Supplement Level"/>
|
||||
<DBFFieldSpec FieldName="TRAN_CODE" Form="attribute" Name="TransactionCode" FieldType="" Description="Transaction Code"/>
|
||||
<DBFFieldSpec FieldName="LINE_REF" Form="attribute" Name="TDLineRef" FieldType="" Description="Line Reference Number"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.VEH">
|
||||
<DBFFileTranslation ID="ID3" ElementName="Vehicle" Description="Vehicle Table">
|
||||
<DBFFieldSpec FieldName="V_VIN" Form="attribute" Name="TransVIN" FieldType="" Description="V_VIN"/>
|
||||
<DBFFieldSpec FieldName="V_MODEL_YR" Form="attribute" Name="TransYear" FieldType="" Description="V_MODEL_YR"/>
|
||||
<DBFFieldSpec FieldName="V_MAKEDESC" Form="attribute" Name="ManufName" FieldType="" Description="V_MAKEDESC"/>
|
||||
<DBFFieldSpec FieldName="V_MAKECODE" Form="attribute" Name="ManufCode" FieldType="" Description="V_MAKECODE"/>
|
||||
<DBFFieldSpec FieldName="V_MODEL" Form="attribute" Name="TransModel" FieldType="" Description="V_MODEL"/>
|
||||
<DBFFieldSpec FieldName="V_MILEAGE" Form="attribute" Name="TransMileage" FieldType="" Description="V_MILEAGE"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD1">
|
||||
<DBFFileTranslation ID="ID4" ElementName="Admin" Description="Administrative information">
|
||||
<DBFFieldSpec FieldName="OWNR_LN" Form="attribute" Name="OwnerL" FieldType="" Description="Owner Lastname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FN" Form="attribute" Name="OwnerF" FieldType="" Description="Owner Firstname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CO_NM" Form="attribute" Name="OwnerCompanyName" FieldType="" Description="Owner Company Name"/>
|
||||
<DBFFieldSpec FieldName="OWNR_TITLE" Form="attribute" Name="OwnerTitle" FieldType="" Description="Owner Title"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR1" Form="attribute" Name="OwnerAddr1" FieldType="" Description="Owner Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR2" Form="attribute" Name="OwnerAddr2" FieldType="" Description="Owner Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CITY" Form="attribute" Name="OwnerCity" FieldType="" Description="Owner City"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ST" Form="attribute" Name="OwnerState" FieldType="" Description="Owner State"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ZIP" Form="attribute" Name="OwnerZip" FieldType="" Description="Owner Zip"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CTRY" Form="attribute" Name="OwnerCountry" FieldType="" Description="Owner Country"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1" Form="attribute" Name="OwnerPhone1" FieldType="" Description="Owner Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1X" Form="attribute" Name="OwnerPhone1Ext" FieldType="" Description="Owner Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2" Form="attribute" Name="OwnerPhone2" FieldType="" Description="Owner Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2X" Form="attribute" Name="OwnerPhone2Ext" FieldType="" Description="Owner Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAX" Form="attribute" Name="OwnerFax" FieldType="" Description="Owner Fax"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAXX" Form="attribute" Name="OwnerFaxExt" FieldType="" Description="Owner Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_EA" Form="attribute" Name="OwnerEmail" FieldType="" Description="Owner Email Address"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_NM" Form="attribute" Name="InsuranceCompanyName" FieldType="" Description="Insurance Company Name"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_ID" Form="attribute" Name="InsuranceCompanyID" FieldType="" Description="Insurance Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR1" Form="attribute" Name="InsuranceAddr1" FieldType="" Description="Insurance Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR2" Form="attribute" Name="InsuranceAddr2" FieldType="" Description="Insurance Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="INS_CITY" Form="attribute" Name="InsuranceCity" FieldType="" Description="Insurance City"/>
|
||||
<DBFFieldSpec FieldName="INS_ST" Form="attribute" Name="InsuranceState" FieldType="" Description="Insurance State"/>
|
||||
<DBFFieldSpec FieldName="INS_ZIP" Form="attribute" Name="InsuranceZip" FieldType="" Description="Insurance Zip"/>
|
||||
<DBFFieldSpec FieldName="INS_CTRY" Form="attribute" Name="InsuranceCountry" FieldType="" Description="Insurance Country"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1" Form="attribute" Name="InsurancePhone1" FieldType="" Description="Insurance Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1X" Form="attribute" Name="InsurancePhone1Ext" FieldType="" Description="Insurance Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2" Form="attribute" Name="InsurancePhone2" FieldType="" Description="Insurance Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2X" Form="attribute" Name="InsurancePhone2Ext" FieldType="" Description="Insurance Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_FAX" Form="attribute" Name="InsuranceFax" FieldType="" Description="Insurance Fax"/>
|
||||
<DBFFieldSpec FieldName="INS_FAXX" Form="attribute" Name="InsuranceFaxExt" FieldType="" Description="Insurance Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_EA" Form="attribute" Name="InsuranceEmail" FieldType="" Description="Insurance Email Address"/>
|
||||
<DBFFieldSpec FieldName="INSD_LN" Form="attribute" Name="InsuranceLName" FieldType="" Description="Insurance Last Name"/>
|
||||
<DBFFieldSpec FieldName="CLM_NO" Form="attribute" Name="ClaimNumber" FieldType="" Description="Claim Number"/>
|
||||
|
||||
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD2">
|
||||
<DBFFileTranslation ID="ID5" ElementName="Admin2" Description="Administrative information2">
|
||||
<DBFFieldSpec FieldName="EST_CT_LN" Form="attribute" Name="EstimatorL" FieldType="" Description="Estimator Lastname"/>
|
||||
<DBFFieldSpec FieldName="EST_CT_FN" Form="attribute" Name="EstimatorF" FieldType="" Description="Estimator Firstname"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_NM" Form="attribute" Name="EstimatorCompanyName" FieldType="" Description="Estimator Company Name"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_ID" Form="attribute" Name="EstimatorCompanyID" FieldType="" Description="Estimator Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR1" Form="attribute" Name="EstimatorAddr1" FieldType="" Description="Estimator Address1"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR2" Form="attribute" Name="EstimatorAddr2" FieldType="" Description="Estimator Address2"/>
|
||||
<DBFFieldSpec FieldName="EST_CITY" Form="attribute" Name="EstimatorCity" FieldType="" Description="Estimator City"/>
|
||||
<DBFFieldSpec FieldName="EST_ST" Form="attribute" Name="EstimatorState" FieldType="" Description="Estimator State"/>
|
||||
<DBFFieldSpec FieldName="EST_ZIP" Form="attribute" Name="EstimatorZip" FieldType="" Description="Estimator Zip"/>
|
||||
<DBFFieldSpec FieldName="EST_CTRY" Form="attribute" Name="EstimatorCountry" FieldType="" Description="Estimator Country"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1" Form="attribute" Name="EstimatorPhone1" FieldType="" Description="Estimator Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1X" Form="attribute" Name="EstimatorPhone1Ext" FieldType="" Description="Estimator Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2" Form="attribute" Name="EstimatorPhone2" FieldType="" Description="Estimator Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2X" Form="attribute" Name="EstimatorPhone2Ext" FieldType="" Description="Estimator Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_FAX" Form="attribute" Name="EstimatorFax" FieldType="" Description="Estimator Fax"/>
|
||||
<DBFFieldSpec FieldName="EST_FAXX" Form="attribute" Name="EstimatorFaxExt" FieldType="" Description="Estimator Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_EA" Form="attribute" Name="EstimatorEmail" FieldType="" Description="Estimator Email Address"/>
|
||||
<DBFFieldSpec FieldName="EST_LIC_NO" Form="attribute" Name="EstimatorLicenseNumber" FieldType="" Description="Estimator License Number"/>
|
||||
<DBFFieldSpec FieldName="EST_FILENO" Form="attribute" Name="EstimatorFileNumber" FieldType="" Description="Estimator File Number"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_DATE" Form="attribute" Name="VehicleInDate" FieldType="" Description="Date arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_TIME" Form="attribute" Name="VehicleInTime" FieldType="" Description="Time arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="TAR_DATE" Form="attribute" Name="TargetVehicleOutDate" FieldType="" Description="Target date to be completed"/>
|
||||
<DBFFieldSpec FieldName="TAR_TIME" Form="attribute" Name="TargetVehicleOutTime" FieldType="" Description="Target time to be completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPDATE" Form="attribute" Name="VehicleOutDate" FieldType="" Description="Date completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPTIME" Form="attribute" Name="VehicleOutTime" FieldType="" Description="Time completed"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.TTL">
|
||||
<DBFFileTranslation ID="ID6" ElementName="Total" Description="Total Table">
|
||||
<DBFFieldSpec FieldName="G_TTL_AMT" Form="attribute" Name="GrandTotalAmount" FieldType="" Description=""/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
</FileTranslations>
|
||||
<StyleSheetTranslation>
|
||||
<StyleSheetURL>ccc.xsl</StyleSheetURL>
|
||||
</StyleSheetTranslation>
|
||||
</TranslationDescriptor>
|
||||
580
_reference/OEC/Mitchell.xsl
Normal file
@@ -0,0 +1,580 @@
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
|
||||
|
||||
<xsl:template match="/">
|
||||
<xsl:for-each select="//TranslatedData">
|
||||
<xsl:element name="TranslatedData">
|
||||
<xsl:attribute name="TranslationOutputFile">
|
||||
<xsl:value-of select="@TranslationOutputFile"/>
|
||||
</xsl:attribute>
|
||||
<xsl:choose>
|
||||
<xsl:when test="Details/@PrgID">
|
||||
<xsl:copy-of select="Details" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:element name="Details">
|
||||
<xsl:attribute name="PrgID">OECTrans.ImportTrans</xsl:attribute>
|
||||
<xsl:for-each select="Details/@*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="Details/*">
|
||||
<xsl:copy-of select="." />
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:element name="Header">
|
||||
<xsl:attribute name="RONum">
|
||||
<xsl:value-of select="//Envelope/@RONum" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerFName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OwnerLName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VIN">
|
||||
<xsl:value-of select="//Vehicle/@TransVIN" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Mileage">
|
||||
<xsl:value-of select="//Vehicle/@TransMileage" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Year">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Make">
|
||||
<xsl:if test="//Vehicle/@ManufName[. != '']" >
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
</xsl:if>
|
||||
<xsl:if test="//Vehicle/@ManufName[. = '']" >
|
||||
<xsl:value-of select="//Vehicle/@ManufCode" />
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Model">
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Description">
|
||||
<xsl:value-of select="//Vehicle/@TransYear" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@ManufName" />
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//Vehicle/@TransModel" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LastSupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(//Envelope/@SupplementNum) > 0">
|
||||
<xsl:value-of select="//Envelope/@SupplementNum" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:apply-templates select="PartsList" />
|
||||
<xsl:element name="Envelope">
|
||||
<xsl:element name="Software">
|
||||
<xsl:attribute name="Manifest">Mitchell.xml</xsl:attribute>
|
||||
<xsl:attribute name="Descriptor">Mitchell.xsl</xsl:attribute>
|
||||
<xsl:attribute name="System">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Version">
|
||||
<xsl:value-of select="//Envelope/@SoftwareVersion"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SystemName">
|
||||
<xsl:value-of select="//Envelope/@SystemName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFileID">
|
||||
<xsl:value-of select="//Envelope/@EstimateFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="UniqueFileID">
|
||||
<xsl:value-of select="//Envelope/@UniqueFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateID">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@SoftwareVersion"/>-<xsl:value-of select="//Envelope/@EstimateFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateIDv2">
|
||||
<xsl:value-of select="//Envelope/@EstimatingSystem"/>-<xsl:value-of select="//Envelope/@EstimateFileID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimateFormatVersion">
|
||||
<xsl:value-of select="//Envelope/@EMSVersion"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
<xsl:element name="Totals">
|
||||
<xsl:attribute name="GrandTotalAmount">
|
||||
<xsl:value-of select="//Total/@GrandTotalAmount"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Administrative">
|
||||
<xsl:element name="Owner">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin/@OwnerF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin/@OwnerL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCompanyName"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr1"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerAddr2"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCity"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@OwnerState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@OwnerZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@OwnerZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@OwnerZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@OwnerZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@OwnerZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@OwnerZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@OwnerZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerCountry"/>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/> x<xsl:value-of select="//Admin/@OwnerPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/> x<xsl:value-of select="//Admin/@OwnerPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<!--<xsl:choose>
|
||||
<xsl:when test="//Admin/@OwnerFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/> x<xsl:value-of select="//Admin/@OwnerFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@OwnerFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>-->
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<!--<xsl:value-of select="//Admin/@OwnerEmail"/>-->
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="InsuranceCompany">
|
||||
<xsl:attribute name="Id">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyID"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Name">
|
||||
<xsl:value-of select="//Admin/@InsuranceCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin/@InsuranceAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin/@InsuranceCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin/@InsuranceState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin/@InsuranceZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin/@InsuranceZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin/@InsuranceZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin/@InsuranceZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)=9">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin/@InsuranceZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin/@InsuranceZip)>4">
|
||||
<xsl:value-of select="substring(//Admin/@InsuranceZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin/@InsuranceCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/> x<xsl:value-of select="//Admin/@InsurancePhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsurancePhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/> x<xsl:value-of select="//Admin/@InsurancePhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsurancePhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin/@InsuranceFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/> x<xsl:value-of select="//Admin/@InsuranceFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin/@InsuranceFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin/@InsuranceEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Insured">
|
||||
<xsl:attribute name="LastName">
|
||||
<xsl:value-of select="//Admin/@InsuranceLName"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Claim">
|
||||
<xsl:attribute name="Number">
|
||||
<xsl:value-of select="//Admin/@ClaimNumber"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="Estimator">
|
||||
<xsl:attribute name="FName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorF"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LName">
|
||||
<xsl:value-of select="//Admin2/@EstimatorL"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Company">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCompanyName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="BodyShopName">
|
||||
<xsl:value-of select="//Admin2/@BodyShopName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr1"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Address2">
|
||||
<xsl:value-of select="//Admin2/@EstimatorAddr2"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="City">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCity"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="State">
|
||||
<xsl:value-of select="//Admin2/@EstimatorState"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Zip">
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains(//Admin2/@EstimatorZip, '-')">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-before(//Admin2/@EstimatorZip, '-'))=5">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length(substring-after(//Admin2/@EstimatorZip, '-'))=4">
|
||||
<xsl:value-of select="//Admin2/@EstimatorZip"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)=9">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>-<xsl:value-of select="substring(//Admin2/@EstimatorZip, 6, 4)"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="string-length(//Admin2/@EstimatorZip)>4">
|
||||
<xsl:value-of select="substring(//Admin2/@EstimatorZip, 1, 5)"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Country">
|
||||
<xsl:value-of select="//Admin2/@EstimatorCountry"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone1Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/> x<xsl:value-of select="//Admin2/@EstimatorPhone1Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Phone2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorPhone2Ext[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/> x<xsl:value-of select="//Admin2/@EstimatorPhone2Ext"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorPhone2"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Fax">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//Admin2/@EstimatorFaxExt[. != '']">
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/> x<xsl:value-of select="//Admin2/@EstimatorFaxExt"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="//Admin2/@EstimatorFax"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="Email">
|
||||
<xsl:value-of select="//Admin2/@EstimatorEmail"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
<xsl:element name="RepairInformation">
|
||||
<xsl:attribute name="VehicleDateIn">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleInDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleInTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleInTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleInTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="EstimatedVehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@TargetVehicleOutDate,' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@TargetVehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@TargetVehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="VehicleDateOut">
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutDate)>6">
|
||||
<xsl:value-of select="substring-before(//Admin2/@VehicleOutDate, ' ')"/>
|
||||
<xsl:if test="string-length(//Admin2/@VehicleOutTime)=4">
|
||||
 <xsl:value-of select="substring(//Admin2/@VehicleOutTime, 1, 2)"/>:<xsl:value-of select="substring(//Admin2/@VehicleOutTime, 3, 2)"/>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template match="PartsList">
|
||||
<xsl:element name="PartsList" >
|
||||
<xsl:for-each select="Part">
|
||||
<xsl:element name="Part" >
|
||||
<!-- Part number translation rules -->
|
||||
<xsl:variable name="OEMPartNumber">
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) != ' GM PART'">
|
||||
<xsl:value-of select="@TDPartNum" />
|
||||
</xsl:if>
|
||||
<xsl:if test="substring(@TDPartNum, string-length(@TDPartNum) - 7) = ' GM PART'">
|
||||
<xsl:value-of select="substring-before(@TDPartNum,' GM PART')" />
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="AltPartNumber">
|
||||
<xsl:value-of select="@AltPartNum"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartType">
|
||||
<xsl:value-of select="@PartType"/>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="PrimaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType!='PAN'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$AltPartNumber!=''">
|
||||
<xsl:value-of select="$AltPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="$OEMPartNumber!=''">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>Salvage or Assembly</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartNumber">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType!='PAN'">
|
||||
<xsl:value-of select="$OEMPartNumber"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="SecondaryPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAA'">PAN</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:attribute name="TDPartNum">
|
||||
<xsl:value-of select="$PrimaryPartNumber"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartNum">
|
||||
<xsl:value-of select="$SecondaryPartNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalPartType">
|
||||
<xsl:value-of select="$PrimaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="ExternalAltPartType">
|
||||
<xsl:value-of select="$SecondaryPartType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$PrimaryPartType='PAN'">1</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAA'">2</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAM'">4</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:when test="$PrimaryPartType='PAC'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="AltPartType">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$SecondaryPartType='PAN'">1</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAA'">2</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAL'">3</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAM'">4</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAC'">4</xsl:when>
|
||||
<xsl:when test="$SecondaryPartType='PAR'">4</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartDesc">
|
||||
<xsl:value-of select="@TDPartDesc" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDEstimate">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN'">
|
||||
<xsl:value-of select="@TDEstimate" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAM'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAA'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:when test="@PartType='PAL'">
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="@ActPrice" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="TDPartQty">
|
||||
<xsl:value-of select="@TDPartQty" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LineNumber">
|
||||
<xsl:value-of select="@LineNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SequenceNumber">
|
||||
<xsl:value-of select="@SequenceNumber" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="SupplLevel">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@SupplementLevel = 'E'">0</xsl:when>
|
||||
<xsl:when test="substring(@SupplementLevel, 1, 1) = 'S'">
|
||||
<xsl:value-of select="substring(@SupplementLevel, 2)" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborType">
|
||||
<xsl:value-of select="@LaborType" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="LaborHours">
|
||||
<xsl:value-of select="@LaborHours" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="OperationCode">
|
||||
<xsl:value-of select="@LaborOp" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="GlassFlag">
|
||||
<xsl:value-of select="@GlassFlag" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="MarkUp">
|
||||
<xsl:value-of select="@MarkUp" />
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="CLPart">
|
||||
<!-- CLPart is false if TRAN_CODE == 2 or TRAN_CODE == 3 -->
|
||||
<!-- CLPart is false if PartType is not 'PAN','PAP','PAL','PAG', 'PAM', or 'PAA' or 'PAC' or 'PAR' -->
|
||||
<!-- CLPart is false if LaborCode is only labor -->
|
||||
<!-- CLPart is false if OpCode is not "Remove/Replace" or "Remove/Replace Partial" -->
|
||||
<xsl:choose>
|
||||
<xsl:when test="@TransactionCode='3'">False</xsl:when>
|
||||
<xsl:when test="@TransactionCode='1' or @TransactionCode='2'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@PartType='PAN' or @PartType='PAG' or @PartType='PAM' or @PartType='PAP' or @PartType='PAL' or @PartType='PAA' or @PartType='PAR' or @PartType='PAC'">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@LaborType='LAD' or @LaborType='LAE' or @LaborType='LAU' or @LaborType='LAT'">False</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:choose>
|
||||
<xsl:when test="@LaborOp='OP0'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP1'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP2'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP3'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP4'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP5'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP6'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP7'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP8'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP9'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP10'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP13'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP14'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP15'">False</xsl:when>
|
||||
<xsl:when test="@LaborOp='OP16'">False</xsl:when>
|
||||
<xsl:otherwise>True</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>False</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
132
_reference/OEC/MitchellMapping.xml
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TranslationDescriptor>
|
||||
<FileTranslations FormatName="Mitchell" ElementName="Estimate" Description="Translation Descriptor for a Mitchell Estimate, Version EMS 2.0">
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.env">
|
||||
<DBFFileTranslation ID="ID1" ElementName="Envelope" Description="Envelope Table">
|
||||
<DBFFieldSpec FieldName="RO_ID" Form="attribute" Name="RONum" FieldType="" Description="RO Number"/>
|
||||
<DBFFieldSpec FieldName="UNQFILE_ID" Form="attribute" Name="UniqueFileID" FieldType="" Description="Unique File Identifier"/>
|
||||
<DBFFieldSpec FieldName="ESTFILE_ID" Form="attribute" Name="EstimateFileID" FieldType="" Description="Estimate File Identifier"/>
|
||||
<DBFFieldSpec FieldName="INCL_ADMIN" Form="attribute" Name="IncludesAdminInfo" FieldType="Boolean" Description="Includes Admin Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VEH" Form="attribute" Name="IncludesVehicleInfo" FieldType="Boolean" Description="Includes Vehicle Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_EST" Form="attribute" Name="IncludesEstimateInfo" FieldType="Boolean" Description="Includes Estimate Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_PROFL" Form="attribute" Name="IncludesProfileInfo" FieldType="Boolean" Description="Includes Profile Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_TOTAL" Form="attribute" Name="IncludesTotalsInfo" FieldType="Boolean" Description="Includes Totals Info Flag"/>
|
||||
<DBFFieldSpec FieldName="INCL_VENDR" Form="attribute" Name="IncludesVendorInfo" FieldType="Boolean" Description="Includes Vendor Info Flag"/>
|
||||
<DBFFieldSpec FieldName="EMS_VER" Form="attribute" Name="EMSVersion" FieldType="" Description="EMS Version Number"/>
|
||||
<DBFFieldSpec FieldName="SUPP_NO" Form="attribute" Name="SupplementNum" FieldType="" Description="Supplement Number"/>
|
||||
<DBFFieldSpec FieldName="TRANS_TYPE" Form="attribute" Name="TransactionType" FieldType="" Description="Transaction Type"/>
|
||||
<DBFFieldSpec FieldName="EST_SYSTEM" Form="attribute" Name="EstimatingSystem" FieldType="" Description="Estimating System Software"/>
|
||||
<DBFFieldSpec FieldName="SW_VERSION" Form="attribute" Name="SoftwareVersion" FieldType="" Description="Software Version Identifier"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.LIN">
|
||||
<DBFFileTranslation ID="ID2" ElementSetName="PartsList" ElementName="Part" Description="Parts List Table">
|
||||
<DBFFieldSpec FieldName="OEM_PARTNO" Form="attribute" Name="TDPartNum" FieldType="" Description="Part Number"/>
|
||||
<DBFFieldSpec FieldName="ALT_PARTNO" Form="attribute" Name="AltPartNum" FieldType="" Description="Alternate Part Number"/>
|
||||
<DBFFieldSpec FieldName="ACT_PRICE" Form="attribute" Name="ActPrice" FieldType="" Description="Actual Part Price"/>
|
||||
<DBFFieldSpec FieldName="LINE_DESC" Form="attribute" Name="TDPartDesc" FieldType="" Description="Part Description"/>
|
||||
<DBFFieldSpec FieldName="DB_PRICE" Form="attribute" Name="TDEstimate" FieldType="" Description="DB_Price"/>
|
||||
<DBFFieldSpec FieldName="PART_QTY" Form="attribute" Name="TDPartQty" FieldType="" Description="Part Quantity"/>
|
||||
<DBFFieldSpec FieldName="LINE_NO" Form="attribute" Name="LineNumber" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="UNQ_SEQ" Form="attribute" Name="SequenceNumber" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="PART_TYPE" Form="attribute" Name="PartType" FieldType="" Description="Part Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LBR_TY" Form="attribute" Name="LaborType" FieldType="" Description="Labor Type"/>
|
||||
<DBFFieldSpec FieldName="MOD_LB_HRS" Form="attribute" Name="LaborHours" FieldType="" Description="Labor Hours"/>
|
||||
<DBFFieldSpec FieldName="LBR_OP" Form="attribute" Name="LaborOp" FieldType="" Description="Labor Op"/>
|
||||
<DBFFieldSpec FieldName="LINE_IND" Form="attribute" Name="SupplementLevel" FieldType="" Description="Supplement Level"/>
|
||||
<DBFFieldSpec FieldName="TRAN_CODE" Form="attribute" Name="TransactionCode" FieldType="" Description="Transaction Code"/>
|
||||
<DBFFieldSpec FieldName="GLASS_FLAG" Form="attribute" Name="GlassFlag" FieldType="" Description="Glass Flag"/>
|
||||
<DBFFieldSpec FieldName="PRT_DSMK_M" Form="attribute" Name="MarkUp" FieldType="" Description="Price Mark up for non OEM parts"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.VEH">
|
||||
<DBFFileTranslation ID="ID3" ElementName="Vehicle" Description="Vehicle Table">
|
||||
<DBFFieldSpec FieldName="V_VIN" Form="attribute" Name="TransVIN" FieldType="" Description=""/>
|
||||
<DBFFieldSpec FieldName="V_MODEL_YR" Form="attribute" Name="TransYear" FieldType="" Description="V_MODEL_YR"/>
|
||||
<DBFFieldSpec FieldName="V_MAKEDESC" Form="attribute" Name="ManufName" FieldType="" Description="V_MAKEDESC"/>
|
||||
<DBFFieldSpec FieldName="V_MAKECODE" Form="attribute" Name="ManufCode" FieldType="" Description="V_MAKECODE"/>
|
||||
<DBFFieldSpec FieldName="V_MODEL" Form="attribute" Name="TransModel" FieldType="" Description="V_MODEL"/>
|
||||
<DBFFieldSpec FieldName="V_MILEAGE" Form="attribute" Name="TransMileage" FieldType="" Description="V_MILEAGE"/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD1">
|
||||
<DBFFileTranslation ID="ID4" ElementName="Admin" Description="Administrative information">
|
||||
<DBFFieldSpec FieldName="OWNR_LN" Form="attribute" Name="OwnerL" FieldType="" Description="Owner Lastname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FN" Form="attribute" Name="OwnerF" FieldType="" Description="Owner Firstname"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CO_NM" Form="attribute" Name="OwnerCompanyName" FieldType="" Description="Owner Company Name"/>
|
||||
<DBFFieldSpec FieldName="OWNR_TITLE" Form="attribute" Name="OwnerTitle" FieldType="" Description="Owner Title"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR1" Form="attribute" Name="OwnerAddr1" FieldType="" Description="Owner Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ADDR2" Form="attribute" Name="OwnerAddr2" FieldType="" Description="Owner Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CITY" Form="attribute" Name="OwnerCity" FieldType="" Description="Owner City"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ST" Form="attribute" Name="OwnerState" FieldType="" Description="Owner State"/>
|
||||
<DBFFieldSpec FieldName="OWNR_ZIP" Form="attribute" Name="OwnerZip" FieldType="" Description="Owner Zip"/>
|
||||
<DBFFieldSpec FieldName="OWNR_CTRY" Form="attribute" Name="OwnerCountry" FieldType="" Description="Owner Country"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1" Form="attribute" Name="OwnerPhone1" FieldType="" Description="Owner Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH1X" Form="attribute" Name="OwnerPhone1Ext" FieldType="" Description="Owner Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2" Form="attribute" Name="OwnerPhone2" FieldType="" Description="Owner Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="OWNR_PH2X" Form="attribute" Name="OwnerPhone2Ext" FieldType="" Description="Owner Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAX" Form="attribute" Name="OwnerFax" FieldType="" Description="Owner Fax"/>
|
||||
<DBFFieldSpec FieldName="OWNR_FAXX" Form="attribute" Name="OwnerFaxExt" FieldType="" Description="Owner Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="OWNR_EA" Form="attribute" Name="OwnerEmail" FieldType="" Description="Owner Email Address"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_NM" Form="attribute" Name="InsuranceCompanyName" FieldType="" Description="Insurance Company Name"/>
|
||||
<DBFFieldSpec FieldName="INS_CO_ID" Form="attribute" Name="InsuranceCompanyID" FieldType="" Description="Insurance Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR1" Form="attribute" Name="InsuranceAddr1" FieldType="" Description="Insurance Address Line 1"/>
|
||||
<DBFFieldSpec FieldName="INS_ADDR2" Form="attribute" Name="InsuranceAddr2" FieldType="" Description="Insurance Address Line 2"/>
|
||||
<DBFFieldSpec FieldName="INS_CITY" Form="attribute" Name="InsuranceCity" FieldType="" Description="Insurance City"/>
|
||||
<DBFFieldSpec FieldName="INS_ST" Form="attribute" Name="InsuranceState" FieldType="" Description="Insurance State"/>
|
||||
<DBFFieldSpec FieldName="INS_ZIP" Form="attribute" Name="InsuranceZip" FieldType="" Description="Insurance Zip"/>
|
||||
<DBFFieldSpec FieldName="INS_CTRY" Form="attribute" Name="InsuranceCountry" FieldType="" Description="Insurance Country"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1" Form="attribute" Name="InsurancePhone1" FieldType="" Description="Insurance Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH1X" Form="attribute" Name="InsurancePhone1Ext" FieldType="" Description="Insurance Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2" Form="attribute" Name="InsurancePhone2" FieldType="" Description="Insurance Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="INS_PH2X" Form="attribute" Name="InsurancePhone2Ext" FieldType="" Description="Insurance Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_FAX" Form="attribute" Name="InsuranceFax" FieldType="" Description="Insurance Fax"/>
|
||||
<DBFFieldSpec FieldName="INS_FAXX" Form="attribute" Name="InsuranceFaxExt" FieldType="" Description="Insurance Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="INS_EA" Form="attribute" Name="InsuranceEmail" FieldType="" Description="Insurance Email Address"/>
|
||||
<DBFFieldSpec FieldName="INSD_LN" Form="attribute" Name="InsuranceLName" FieldType="" Description="Insurance Last Name"/>
|
||||
<DBFFieldSpec FieldName="CLM_NO" Form="attribute" Name="ClaimNumber" FieldType="" Description="Claim Number"/>
|
||||
|
||||
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.AD2">
|
||||
<DBFFileTranslation ID="ID5" ElementName="Admin2" Description="Administrative information2">
|
||||
<DBFFieldSpec FieldName="EST_CT_LN" Form="attribute" Name="EstimatorL" FieldType="" Description="Estimator Lastname"/>
|
||||
<DBFFieldSpec FieldName="EST_CT_FN" Form="attribute" Name="EstimatorF" FieldType="" Description="Estimator Firstname"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_NM" Form="attribute" Name="EstimatorCompanyName" FieldType="" Description="Estimator Company Name"/>
|
||||
<DBFFieldSpec FieldName="EST_CO_ID" Form="attribute" Name="EstimatorCompanyID" FieldType="" Description="Estimator Company Identifier"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR1" Form="attribute" Name="EstimatorAddr1" FieldType="" Description="Estimator Address1"/>
|
||||
<DBFFieldSpec FieldName="EST_ADDR2" Form="attribute" Name="EstimatorAddr2" FieldType="" Description="Estimator Address2"/>
|
||||
<DBFFieldSpec FieldName="EST_CITY" Form="attribute" Name="EstimatorCity" FieldType="" Description="Estimator City"/>
|
||||
<DBFFieldSpec FieldName="EST_ST" Form="attribute" Name="EstimatorState" FieldType="" Description="Estimator State"/>
|
||||
<DBFFieldSpec FieldName="EST_ZIP" Form="attribute" Name="EstimatorZip" FieldType="" Description="Estimator Zip"/>
|
||||
<DBFFieldSpec FieldName="EST_CTRY" Form="attribute" Name="EstimatorCountry" FieldType="" Description="Estimator Country"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1" Form="attribute" Name="EstimatorPhone1" FieldType="" Description="Estimator Primary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH1X" Form="attribute" Name="EstimatorPhone1Ext" FieldType="" Description="Estimator Primary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2" Form="attribute" Name="EstimatorPhone2" FieldType="" Description="Estimator Secondary Phone"/>
|
||||
<DBFFieldSpec FieldName="EST_PH2X" Form="attribute" Name="EstimatorPhone2Ext" FieldType="" Description="Estimator Secondary Phone Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_FAX" Form="attribute" Name="EstimatorFax" FieldType="" Description="Estimator Fax"/>
|
||||
<DBFFieldSpec FieldName="EST_FAXX" Form="attribute" Name="EstimatorFaxExt" FieldType="" Description="Estimator Fax Extension"/>
|
||||
<DBFFieldSpec FieldName="EST_EA" Form="attribute" Name="EstimatorEmail" FieldType="" Description="Estimator Email Address"/>
|
||||
<DBFFieldSpec FieldName="EST_LIC_NO" Form="attribute" Name="EstimatorLicenseNumber" FieldType="" Description="Estimator License Number"/>
|
||||
<DBFFieldSpec FieldName="EST_FILENO" Form="attribute" Name="EstimatorFileNumber" FieldType="" Description="Estimator File Number"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_DATE" Form="attribute" Name="VehicleInDate" FieldType="" Description="Date arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="RO_IN_TIME" Form="attribute" Name="VehicleInTime" FieldType="" Description="Time arrived in shop"/>
|
||||
<DBFFieldSpec FieldName="TAR_DATE" Form="attribute" Name="TargetVehicleOutDate" FieldType="" Description="Target date to be completed"/>
|
||||
<DBFFieldSpec FieldName="TAR_TIME" Form="attribute" Name="TargetVehicleOutTime" FieldType="" Description="Target time to be completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPDATE" Form="attribute" Name="VehicleOutDate" FieldType="" Description="Date completed"/>
|
||||
<DBFFieldSpec FieldName="RO_CMPTIME" Form="attribute" Name="VehicleOutTime" FieldType="" Description="Time completed"/>
|
||||
<DBFFieldSpec FieldName="RF_CO_NM" Form="attribute" Name="BodyShopName" FieldType="" Description="Body Shop Name"/>
|
||||
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
<FileTranslation TranslatorID="OECImportEngine.DBFTranslator" FileNameMask="*.TTL">
|
||||
<DBFFileTranslation ID="ID6" ElementName="Total" Description="Total Table">
|
||||
<DBFFieldSpec FieldName="G_TTL_AMT" Form="attribute" Name="GrandTotalAmount" FieldType="" Description=""/>
|
||||
</DBFFileTranslation>
|
||||
</FileTranslation>
|
||||
</FileTranslations>
|
||||
<StyleSheetTranslation>
|
||||
<StyleSheetURL>Mitchell.xsl</StyleSheetURL>
|
||||
</StyleSheetTranslation>
|
||||
</TranslationDescriptor>
|
||||
6
_reference/Responsibility Center Setup.md
Normal file
1
_reference/Test_CDK_Acct Config.json
Normal file
@@ -22,7 +22,7 @@ hooks.js:
|
||||
module.exports = [
|
||||
{
|
||||
path: "/pull",
|
||||
command: "git pull && npm i",
|
||||
command: "git pull && yarn && pm2 restart 0",
|
||||
cwd: "/home/ubuntu/io/",
|
||||
method: "post",
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ import JobsShow from "../jobs/jobs.show";
|
||||
const httpLink = new HttpLink({
|
||||
uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
||||
headers: {
|
||||
"x-hasura-admin-secret": `Dev-BodyShopAppBySnaptSoftware!`,
|
||||
"x-hasura-admin-secret": `Dev-BodyShopApp!`,
|
||||
// 'Authorization': `Bearer xxxx`,
|
||||
},
|
||||
});
|
||||
@@ -67,7 +67,7 @@ const client = new ApolloClient({
|
||||
// uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
||||
// cache: new InMemoryCache(),
|
||||
// headers: {
|
||||
// "x-hasura-admin-secret": `Dev-BodyShopAppBySnaptSoftware!`,
|
||||
// "x-hasura-admin-secret": `Dev-BodyShopApp!`,
|
||||
// // 'Authorization': `Bearer xxxx`,
|
||||
// },
|
||||
// });
|
||||
|
||||
@@ -44,7 +44,10 @@ const JobsList = (props) => (
|
||||
);
|
||||
|
||||
const JobsFilter = (props) => {
|
||||
const { loading, error, data } = useQuery(QUERY_ALL_SHOPS);
|
||||
const { loading, error, data } = useQuery(QUERY_ALL_SHOPS, {
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
if (loading) return <CircularProgress />;
|
||||
if (error) return JSON.stringify(error);
|
||||
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
// craco.config.js
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const CracoLessPlugin = require("craco-less");
|
||||
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
|
||||
|
||||
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: {
|
||||
@@ -12,7 +28,9 @@ module.exports = {
|
||||
modifyVars: {
|
||||
...(process.env.NODE_ENV === "development"
|
||||
? { "@primary-color": "#a51d1d" }
|
||||
: { "@primary-color": "#1DA57A" }),
|
||||
: {
|
||||
//"@primary-color": "#1DA57A"
|
||||
}),
|
||||
// "@primary-color": " #1890ff", // primary color for all components
|
||||
// "@link-color": "#1890ff", // link color
|
||||
// "@success-color": "#52c41a", // success state color
|
||||
@@ -51,4 +69,5 @@ module.exports = {
|
||||
},
|
||||
}),
|
||||
},
|
||||
devtool: "source-map",
|
||||
};
|
||||
|
||||
8
client/cypress.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"experimentalStudio": true,
|
||||
"env": {
|
||||
"FIREBASE_USERNAME": "cypress@imex.test",
|
||||
"FIREBASE_PASSWORD": "cypress"
|
||||
}
|
||||
}
|
||||
5
client/cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
5
client/cypress/fixtures/profile.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": 8739,
|
||||
"name": "Jane",
|
||||
"email": "jane@example.com"
|
||||
}
|
||||
232
client/cypress/fixtures/users.json
Normal file
@@ -0,0 +1,232 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Leanne Graham",
|
||||
"username": "Bret",
|
||||
"email": "Sincere@april.biz",
|
||||
"address": {
|
||||
"street": "Kulas Light",
|
||||
"suite": "Apt. 556",
|
||||
"city": "Gwenborough",
|
||||
"zipcode": "92998-3874",
|
||||
"geo": {
|
||||
"lat": "-37.3159",
|
||||
"lng": "81.1496"
|
||||
}
|
||||
},
|
||||
"phone": "1-770-736-8031 x56442",
|
||||
"website": "hildegard.org",
|
||||
"company": {
|
||||
"name": "Romaguera-Crona",
|
||||
"catchPhrase": "Multi-layered client-server neural-net",
|
||||
"bs": "harness real-time e-markets"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Ervin Howell",
|
||||
"username": "Antonette",
|
||||
"email": "Shanna@melissa.tv",
|
||||
"address": {
|
||||
"street": "Victor Plains",
|
||||
"suite": "Suite 879",
|
||||
"city": "Wisokyburgh",
|
||||
"zipcode": "90566-7771",
|
||||
"geo": {
|
||||
"lat": "-43.9509",
|
||||
"lng": "-34.4618"
|
||||
}
|
||||
},
|
||||
"phone": "010-692-6593 x09125",
|
||||
"website": "anastasia.net",
|
||||
"company": {
|
||||
"name": "Deckow-Crist",
|
||||
"catchPhrase": "Proactive didactic contingency",
|
||||
"bs": "synergize scalable supply-chains"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Clementine Bauch",
|
||||
"username": "Samantha",
|
||||
"email": "Nathan@yesenia.net",
|
||||
"address": {
|
||||
"street": "Douglas Extension",
|
||||
"suite": "Suite 847",
|
||||
"city": "McKenziehaven",
|
||||
"zipcode": "59590-4157",
|
||||
"geo": {
|
||||
"lat": "-68.6102",
|
||||
"lng": "-47.0653"
|
||||
}
|
||||
},
|
||||
"phone": "1-463-123-4447",
|
||||
"website": "ramiro.info",
|
||||
"company": {
|
||||
"name": "Romaguera-Jacobson",
|
||||
"catchPhrase": "Face to face bifurcated interface",
|
||||
"bs": "e-enable strategic applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Patricia Lebsack",
|
||||
"username": "Karianne",
|
||||
"email": "Julianne.OConner@kory.org",
|
||||
"address": {
|
||||
"street": "Hoeger Mall",
|
||||
"suite": "Apt. 692",
|
||||
"city": "South Elvis",
|
||||
"zipcode": "53919-4257",
|
||||
"geo": {
|
||||
"lat": "29.4572",
|
||||
"lng": "-164.2990"
|
||||
}
|
||||
},
|
||||
"phone": "493-170-9623 x156",
|
||||
"website": "kale.biz",
|
||||
"company": {
|
||||
"name": "Robel-Corkery",
|
||||
"catchPhrase": "Multi-tiered zero tolerance productivity",
|
||||
"bs": "transition cutting-edge web services"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Chelsey Dietrich",
|
||||
"username": "Kamren",
|
||||
"email": "Lucio_Hettinger@annie.ca",
|
||||
"address": {
|
||||
"street": "Skiles Walks",
|
||||
"suite": "Suite 351",
|
||||
"city": "Roscoeview",
|
||||
"zipcode": "33263",
|
||||
"geo": {
|
||||
"lat": "-31.8129",
|
||||
"lng": "62.5342"
|
||||
}
|
||||
},
|
||||
"phone": "(254)954-1289",
|
||||
"website": "demarco.info",
|
||||
"company": {
|
||||
"name": "Keebler LLC",
|
||||
"catchPhrase": "User-centric fault-tolerant solution",
|
||||
"bs": "revolutionize end-to-end systems"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Mrs. Dennis Schulist",
|
||||
"username": "Leopoldo_Corkery",
|
||||
"email": "Karley_Dach@jasper.info",
|
||||
"address": {
|
||||
"street": "Norberto Crossing",
|
||||
"suite": "Apt. 950",
|
||||
"city": "South Christy",
|
||||
"zipcode": "23505-1337",
|
||||
"geo": {
|
||||
"lat": "-71.4197",
|
||||
"lng": "71.7478"
|
||||
}
|
||||
},
|
||||
"phone": "1-477-935-8478 x6430",
|
||||
"website": "ola.org",
|
||||
"company": {
|
||||
"name": "Considine-Lockman",
|
||||
"catchPhrase": "Synchronised bottom-line interface",
|
||||
"bs": "e-enable innovative applications"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Kurtis Weissnat",
|
||||
"username": "Elwyn.Skiles",
|
||||
"email": "Telly.Hoeger@billy.biz",
|
||||
"address": {
|
||||
"street": "Rex Trail",
|
||||
"suite": "Suite 280",
|
||||
"city": "Howemouth",
|
||||
"zipcode": "58804-1099",
|
||||
"geo": {
|
||||
"lat": "24.8918",
|
||||
"lng": "21.8984"
|
||||
}
|
||||
},
|
||||
"phone": "210.067.6132",
|
||||
"website": "elvis.io",
|
||||
"company": {
|
||||
"name": "Johns Group",
|
||||
"catchPhrase": "Configurable multimedia task-force",
|
||||
"bs": "generate enterprise e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Nicholas Runolfsdottir V",
|
||||
"username": "Maxime_Nienow",
|
||||
"email": "Sherwood@rosamond.me",
|
||||
"address": {
|
||||
"street": "Ellsworth Summit",
|
||||
"suite": "Suite 729",
|
||||
"city": "Aliyaview",
|
||||
"zipcode": "45169",
|
||||
"geo": {
|
||||
"lat": "-14.3990",
|
||||
"lng": "-120.7677"
|
||||
}
|
||||
},
|
||||
"phone": "586.493.6943 x140",
|
||||
"website": "jacynthe.com",
|
||||
"company": {
|
||||
"name": "Abernathy Group",
|
||||
"catchPhrase": "Implemented secondary concept",
|
||||
"bs": "e-enable extensible e-tailers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Glenna Reichert",
|
||||
"username": "Delphine",
|
||||
"email": "Chaim_McDermott@dana.io",
|
||||
"address": {
|
||||
"street": "Dayna Park",
|
||||
"suite": "Suite 449",
|
||||
"city": "Bartholomebury",
|
||||
"zipcode": "76495-3109",
|
||||
"geo": {
|
||||
"lat": "24.6463",
|
||||
"lng": "-168.8889"
|
||||
}
|
||||
},
|
||||
"phone": "(775)976-6794 x41206",
|
||||
"website": "conrad.com",
|
||||
"company": {
|
||||
"name": "Yost and Sons",
|
||||
"catchPhrase": "Switchable contextually-based project",
|
||||
"bs": "aggregate real-time technologies"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Clementina DuBuque",
|
||||
"username": "Moriah.Stanton",
|
||||
"email": "Rey.Padberg@karina.biz",
|
||||
"address": {
|
||||
"street": "Kattie Turnpike",
|
||||
"suite": "Suite 198",
|
||||
"city": "Lebsackbury",
|
||||
"zipcode": "31428-2261",
|
||||
"geo": {
|
||||
"lat": "-38.2386",
|
||||
"lng": "57.2232"
|
||||
}
|
||||
},
|
||||
"phone": "024-648-3804",
|
||||
"website": "ambrose.net",
|
||||
"company": {
|
||||
"name": "Hoeger LLC",
|
||||
"catchPhrase": "Centralized empowering task-force",
|
||||
"bs": "target end-to-end models"
|
||||
}
|
||||
}
|
||||
]
|
||||
23
client/cypress/integration/01-General Render/01-home.spec.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/// <reference types="Cypress" />
|
||||
const { FIREBASE_USERNAME, FIREBASE_PASSWORcD } = Cypress.env();
|
||||
describe("Renders the General Page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
it("Renders Correctly", () => {});
|
||||
it("Has the Slogan", () => {
|
||||
cy.findByText("A whole x22new kind of shop management system.").should(
|
||||
"exist"
|
||||
);
|
||||
/* ==== Generated with Cypress Studio ==== */
|
||||
cy.get(
|
||||
".ant-menu-item-active > .ant-menu-title-content > .header0-item-block"
|
||||
).click();
|
||||
cy.get("#email").clear();
|
||||
cy.get("#email").type("patrick@imex.dev");
|
||||
cy.get("#password").clear();
|
||||
cy.get("#password").type("patrick123{enter}");
|
||||
cy.get(".ant-form > .ant-btn").click();
|
||||
/* ==== End Cypress Studio ==== */
|
||||
});
|
||||
});
|
||||
143
client/cypress/integration/1-getting-started/todo.spec.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
// Welcome to Cypress!
|
||||
//
|
||||
// This spec file contains a variety of sample tests
|
||||
// for a todo list app that are designed to demonstrate
|
||||
// the power of writing tests in Cypress.
|
||||
//
|
||||
// To learn more about how Cypress works and
|
||||
// what makes it such an awesome testing tool,
|
||||
// please read our getting started guide:
|
||||
// https://on.cypress.io/introduction-to-cypress
|
||||
|
||||
describe('example to-do app', () => {
|
||||
beforeEach(() => {
|
||||
// Cypress starts out with a blank slate for each test
|
||||
// so we must tell it to visit our website with the `cy.visit()` command.
|
||||
// Since we want to visit the same URL at the start of all our tests,
|
||||
// we include it in our beforeEach function so that it runs before each test
|
||||
cy.visit('https://example.cypress.io/todo')
|
||||
})
|
||||
|
||||
it('displays two todo items by default', () => {
|
||||
// We use the `cy.get()` command to get all elements that match the selector.
|
||||
// Then, we use `should` to assert that there are two matched items,
|
||||
// which are the two default items.
|
||||
cy.get('.todo-list li').should('have.length', 2)
|
||||
|
||||
// We can go even further and check that the default todos each contain
|
||||
// the correct text. We use the `first` and `last` functions
|
||||
// to get just the first and last matched elements individually,
|
||||
// and then perform an assertion with `should`.
|
||||
cy.get('.todo-list li').first().should('have.text', 'Pay electric bill')
|
||||
cy.get('.todo-list li').last().should('have.text', 'Walk the dog')
|
||||
})
|
||||
|
||||
it('can add new todo items', () => {
|
||||
// We'll store our item text in a variable so we can reuse it
|
||||
const newItem = 'Feed the cat'
|
||||
|
||||
// Let's get the input element and use the `type` command to
|
||||
// input our new list item. After typing the content of our item,
|
||||
// we need to type the enter key as well in order to submit the input.
|
||||
// This input has a data-test attribute so we'll use that to select the
|
||||
// element in accordance with best practices:
|
||||
// https://on.cypress.io/selecting-elements
|
||||
cy.get('[data-test=new-todo]').type(`${newItem}{enter}`)
|
||||
|
||||
// Now that we've typed our new item, let's check that it actually was added to the list.
|
||||
// Since it's the newest item, it should exist as the last element in the list.
|
||||
// In addition, with the two default items, we should have a total of 3 elements in the list.
|
||||
// Since assertions yield the element that was asserted on,
|
||||
// we can chain both of these assertions together into a single statement.
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 3)
|
||||
.last()
|
||||
.should('have.text', newItem)
|
||||
})
|
||||
|
||||
it('can check off an item as completed', () => {
|
||||
// In addition to using the `get` command to get an element by selector,
|
||||
// we can also use the `contains` command to get an element by its contents.
|
||||
// However, this will yield the <label>, which is lowest-level element that contains the text.
|
||||
// In order to check the item, we'll find the <input> element for this <label>
|
||||
// by traversing up the dom to the parent element. From there, we can `find`
|
||||
// the child checkbox <input> element and use the `check` command to check it.
|
||||
cy.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find('input[type=checkbox]')
|
||||
.check()
|
||||
|
||||
// Now that we've checked the button, we can go ahead and make sure
|
||||
// that the list element is now marked as completed.
|
||||
// Again we'll use `contains` to find the <label> element and then use the `parents` command
|
||||
// to traverse multiple levels up the dom until we find the corresponding <li> element.
|
||||
// Once we get that element, we can assert that it has the completed class.
|
||||
cy.contains('Pay electric bill')
|
||||
.parents('li')
|
||||
.should('have.class', 'completed')
|
||||
})
|
||||
|
||||
context('with a checked task', () => {
|
||||
beforeEach(() => {
|
||||
// We'll take the command we used above to check off an element
|
||||
// Since we want to perform multiple tests that start with checking
|
||||
// one element, we put it in the beforeEach hook
|
||||
// so that it runs at the start of every test.
|
||||
cy.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find('input[type=checkbox]')
|
||||
.check()
|
||||
})
|
||||
|
||||
it('can filter for uncompleted tasks', () => {
|
||||
// We'll click on the "active" button in order to
|
||||
// display only incomplete items
|
||||
cy.contains('Active').click()
|
||||
|
||||
// After filtering, we can assert that there is only the one
|
||||
// incomplete item in the list.
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should('have.text', 'Walk the dog')
|
||||
|
||||
// For good measure, let's also assert that the task we checked off
|
||||
// does not exist on the page.
|
||||
cy.contains('Pay electric bill').should('not.exist')
|
||||
})
|
||||
|
||||
it('can filter for completed tasks', () => {
|
||||
// We can perform similar steps as the test above to ensure
|
||||
// that only completed tasks are shown
|
||||
cy.contains('Completed').click()
|
||||
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should('have.text', 'Pay electric bill')
|
||||
|
||||
cy.contains('Walk the dog').should('not.exist')
|
||||
})
|
||||
|
||||
it('can delete all completed tasks', () => {
|
||||
// First, let's click the "Clear completed" button
|
||||
// `contains` is actually serving two purposes here.
|
||||
// First, it's ensuring that the button exists within the dom.
|
||||
// This button only appears when at least one task is checked
|
||||
// so this command is implicitly verifying that it does exist.
|
||||
// Second, it selects the button so we can click it.
|
||||
cy.contains('Clear completed').click()
|
||||
|
||||
// Then we can make sure that there is only one element
|
||||
// in the list and our element does not exist
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.should('not.have.text', 'Pay electric bill')
|
||||
|
||||
// Finally, make sure that the clear button no longer exists.
|
||||
cy.contains('Clear completed').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
299
client/cypress/integration/2-advanced-examples/actions.spec.js
Normal file
@@ -0,0 +1,299 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Actions', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/actions')
|
||||
})
|
||||
|
||||
// https://on.cypress.io/interacting-with-elements
|
||||
|
||||
it('.type() - type into a DOM element', () => {
|
||||
// https://on.cypress.io/type
|
||||
cy.get('.action-email')
|
||||
.type('fake@email.com').should('have.value', 'fake@email.com')
|
||||
|
||||
// .type() with special character sequences
|
||||
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
|
||||
.type('{del}{selectall}{backspace}')
|
||||
|
||||
// .type() with key modifiers
|
||||
.type('{alt}{option}') //these are equivalent
|
||||
.type('{ctrl}{control}') //these are equivalent
|
||||
.type('{meta}{command}{cmd}') //these are equivalent
|
||||
.type('{shift}')
|
||||
|
||||
// Delay each keypress by 0.1 sec
|
||||
.type('slow.typing@email.com', { delay: 100 })
|
||||
.should('have.value', 'slow.typing@email.com')
|
||||
|
||||
cy.get('.action-disabled')
|
||||
// Ignore error checking prior to type
|
||||
// like whether the input is visible or disabled
|
||||
.type('disabled error checking', { force: true })
|
||||
.should('have.value', 'disabled error checking')
|
||||
})
|
||||
|
||||
it('.focus() - focus on a DOM element', () => {
|
||||
// https://on.cypress.io/focus
|
||||
cy.get('.action-focus').focus()
|
||||
.should('have.class', 'focus')
|
||||
.prev().should('have.attr', 'style', 'color: orange;')
|
||||
})
|
||||
|
||||
it('.blur() - blur off a DOM element', () => {
|
||||
// https://on.cypress.io/blur
|
||||
cy.get('.action-blur').type('About to blur').blur()
|
||||
.should('have.class', 'error')
|
||||
.prev().should('have.attr', 'style', 'color: red;')
|
||||
})
|
||||
|
||||
it('.clear() - clears an input or textarea element', () => {
|
||||
// https://on.cypress.io/clear
|
||||
cy.get('.action-clear').type('Clear this text')
|
||||
.should('have.value', 'Clear this text')
|
||||
.clear()
|
||||
.should('have.value', '')
|
||||
})
|
||||
|
||||
it('.submit() - submit a form', () => {
|
||||
// https://on.cypress.io/submit
|
||||
cy.get('.action-form')
|
||||
.find('[type="text"]').type('HALFOFF')
|
||||
|
||||
cy.get('.action-form').submit()
|
||||
.next().should('contain', 'Your form has been submitted!')
|
||||
})
|
||||
|
||||
it('.click() - click on a DOM element', () => {
|
||||
// https://on.cypress.io/click
|
||||
cy.get('.action-btn').click()
|
||||
|
||||
// You can click on 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
|
||||
// clicking in the center of the element is the default
|
||||
cy.get('#action-canvas').click()
|
||||
|
||||
cy.get('#action-canvas').click('topLeft')
|
||||
cy.get('#action-canvas').click('top')
|
||||
cy.get('#action-canvas').click('topRight')
|
||||
cy.get('#action-canvas').click('left')
|
||||
cy.get('#action-canvas').click('right')
|
||||
cy.get('#action-canvas').click('bottomLeft')
|
||||
cy.get('#action-canvas').click('bottom')
|
||||
cy.get('#action-canvas').click('bottomRight')
|
||||
|
||||
// .click() accepts an x and y coordinate
|
||||
// that controls where the click occurs :)
|
||||
|
||||
cy.get('#action-canvas')
|
||||
.click(80, 75) // click 80px on x coord and 75px on y coord
|
||||
.click(170, 75)
|
||||
.click(80, 165)
|
||||
.click(100, 185)
|
||||
.click(125, 190)
|
||||
.click(150, 185)
|
||||
.click(170, 165)
|
||||
|
||||
// click multiple elements by passing multiple: true
|
||||
cy.get('.action-labels>.label').click({ multiple: true })
|
||||
|
||||
// Ignore error checking prior to clicking
|
||||
cy.get('.action-opacity>.btn').click({ force: true })
|
||||
})
|
||||
|
||||
it('.dblclick() - double click on a DOM element', () => {
|
||||
// https://on.cypress.io/dblclick
|
||||
|
||||
// Our app has a listener on 'dblclick' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on double click
|
||||
cy.get('.action-div').dblclick().should('not.be.visible')
|
||||
cy.get('.action-input-hidden').should('be.visible')
|
||||
})
|
||||
|
||||
it('.rightclick() - right click on a DOM element', () => {
|
||||
// https://on.cypress.io/rightclick
|
||||
|
||||
// Our app has a listener on 'contextmenu' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on right click
|
||||
cy.get('.rightclick-action-div').rightclick().should('not.be.visible')
|
||||
cy.get('.rightclick-action-input-hidden').should('be.visible')
|
||||
})
|
||||
|
||||
it('.check() - check a checkbox or radio element', () => {
|
||||
// https://on.cypress.io/check
|
||||
|
||||
// By default, .check() will check all
|
||||
// matching checkbox or radio elements in succession, one after another
|
||||
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]')
|
||||
.check().should('be.checked')
|
||||
|
||||
cy.get('.action-radios [type="radio"]').not('[disabled]')
|
||||
.check().should('be.checked')
|
||||
|
||||
// .check() accepts a value argument
|
||||
cy.get('.action-radios [type="radio"]')
|
||||
.check('radio1').should('be.checked')
|
||||
|
||||
// .check() accepts an array of values
|
||||
cy.get('.action-multiple-checkboxes [type="checkbox"]')
|
||||
.check(['checkbox1', 'checkbox2']).should('be.checked')
|
||||
|
||||
// Ignore error checking prior to checking
|
||||
cy.get('.action-checkboxes [disabled]')
|
||||
.check({ force: true }).should('be.checked')
|
||||
|
||||
cy.get('.action-radios [type="radio"]')
|
||||
.check('radio3', { force: true }).should('be.checked')
|
||||
})
|
||||
|
||||
it('.uncheck() - uncheck a checkbox element', () => {
|
||||
// https://on.cypress.io/uncheck
|
||||
|
||||
// By default, .uncheck() will uncheck all matching
|
||||
// checkbox elements in succession, one after another
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.not('[disabled]')
|
||||
.uncheck().should('not.be.checked')
|
||||
|
||||
// .uncheck() accepts a value argument
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.check('checkbox1')
|
||||
.uncheck('checkbox1').should('not.be.checked')
|
||||
|
||||
// .uncheck() accepts an array of values
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.check(['checkbox1', 'checkbox3'])
|
||||
.uncheck(['checkbox1', 'checkbox3']).should('not.be.checked')
|
||||
|
||||
// Ignore error checking prior to unchecking
|
||||
cy.get('.action-check [disabled]')
|
||||
.uncheck({ force: true }).should('not.be.checked')
|
||||
})
|
||||
|
||||
it('.select() - select an option in a <select> element', () => {
|
||||
// https://on.cypress.io/select
|
||||
|
||||
// at first, no option should be selected
|
||||
cy.get('.action-select')
|
||||
.should('have.value', '--Select a fruit--')
|
||||
|
||||
// Select option(s) with matching text content
|
||||
cy.get('.action-select').select('apples')
|
||||
// confirm the apples were selected
|
||||
// note that each value starts with "fr-" in our HTML
|
||||
cy.get('.action-select').should('have.value', 'fr-apples')
|
||||
|
||||
cy.get('.action-select-multiple')
|
||||
.select(['apples', 'oranges', 'bananas'])
|
||||
// when getting multiple values, invoke "val" method first
|
||||
.invoke('val')
|
||||
.should('deep.equal', ['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
|
||||
// Select option(s) with matching value
|
||||
cy.get('.action-select').select('fr-bananas')
|
||||
// can attach an assertion right away to the element
|
||||
.should('have.value', 'fr-bananas')
|
||||
|
||||
cy.get('.action-select-multiple')
|
||||
.select(['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
.invoke('val')
|
||||
.should('deep.equal', ['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
|
||||
// assert the selected values include oranges
|
||||
cy.get('.action-select-multiple')
|
||||
.invoke('val').should('include', 'fr-oranges')
|
||||
})
|
||||
|
||||
it('.scrollIntoView() - scroll an element into view', () => {
|
||||
// https://on.cypress.io/scrollintoview
|
||||
|
||||
// normally all of these buttons are hidden,
|
||||
// because they're not within
|
||||
// the viewable area of their parent
|
||||
// (we need to scroll to see them)
|
||||
cy.get('#scroll-horizontal button')
|
||||
.should('not.be.visible')
|
||||
|
||||
// scroll the button into view, as if the user had scrolled
|
||||
cy.get('#scroll-horizontal button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
|
||||
cy.get('#scroll-vertical button')
|
||||
.should('not.be.visible')
|
||||
|
||||
// Cypress handles the scroll direction needed
|
||||
cy.get('#scroll-vertical button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
|
||||
cy.get('#scroll-both button')
|
||||
.should('not.be.visible')
|
||||
|
||||
// Cypress knows to scroll to the right and down
|
||||
cy.get('#scroll-both button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
})
|
||||
|
||||
it('.trigger() - trigger an event on a DOM element', () => {
|
||||
// https://on.cypress.io/trigger
|
||||
|
||||
// To interact with a range input (slider)
|
||||
// we need to set its value & trigger the
|
||||
// event to signal it changed
|
||||
|
||||
// Here, we invoke jQuery's val() method to set
|
||||
// the value and trigger the 'change' event
|
||||
cy.get('.trigger-input-range')
|
||||
.invoke('val', 25)
|
||||
.trigger('change')
|
||||
.get('input[type=range]').siblings('p')
|
||||
.should('have.text', '25')
|
||||
})
|
||||
|
||||
it('cy.scrollTo() - scroll the window or element to a position', () => {
|
||||
// https://on.cypress.io/scrollto
|
||||
|
||||
// You can scroll to 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
|
||||
// if you chain .scrollTo() off of cy, we will
|
||||
// scroll the entire window
|
||||
cy.scrollTo('bottom')
|
||||
|
||||
cy.get('#scrollable-horizontal').scrollTo('right')
|
||||
|
||||
// or you can scroll to a specific coordinate:
|
||||
// (x axis, y axis) in pixels
|
||||
cy.get('#scrollable-vertical').scrollTo(250, 250)
|
||||
|
||||
// or you can scroll to a specific percentage
|
||||
// of the (width, height) of the element
|
||||
cy.get('#scrollable-both').scrollTo('75%', '25%')
|
||||
|
||||
// control the easing of the scroll (default is 'swing')
|
||||
cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' })
|
||||
|
||||
// control the duration of the scroll (in ms)
|
||||
cy.get('#scrollable-both').scrollTo('center', { duration: 2000 })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Aliasing', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/aliasing')
|
||||
})
|
||||
|
||||
it('.as() - alias a DOM element for later use', () => {
|
||||
// https://on.cypress.io/as
|
||||
|
||||
// Alias a DOM element for use later
|
||||
// We don't have to traverse to the element
|
||||
// later in our code, we reference it with @
|
||||
|
||||
cy.get('.as-table').find('tbody>tr')
|
||||
.first().find('td').first()
|
||||
.find('button').as('firstBtn')
|
||||
|
||||
// when we reference the alias, we place an
|
||||
// @ in front of its name
|
||||
cy.get('@firstBtn').click()
|
||||
|
||||
cy.get('@firstBtn')
|
||||
.should('have.class', 'btn-success')
|
||||
.and('contain', 'Changed')
|
||||
})
|
||||
|
||||
it('.as() - alias a route for later use', () => {
|
||||
// Alias the route to wait for its response
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait('@getComment').its('response.statusCode').should('eq', 200)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,177 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Assertions', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/assertions')
|
||||
})
|
||||
|
||||
describe('Implicit Assertions', () => {
|
||||
it('.should() - make an assertion about the current subject', () => {
|
||||
// https://on.cypress.io/should
|
||||
cy.get('.assertion-table')
|
||||
.find('tbody tr:last')
|
||||
.should('have.class', 'success')
|
||||
.find('td')
|
||||
.first()
|
||||
// checking the text of the <td> element in various ways
|
||||
.should('have.text', 'Column content')
|
||||
.should('contain', 'Column content')
|
||||
.should('have.html', 'Column content')
|
||||
// chai-jquery uses "is()" to check if element matches selector
|
||||
.should('match', 'td')
|
||||
// to match text content against a regular expression
|
||||
// first need to invoke jQuery method text()
|
||||
// and then match using regular expression
|
||||
.invoke('text')
|
||||
.should('match', /column content/i)
|
||||
|
||||
// a better way to check element's text content against a regular expression
|
||||
// is to use "cy.contains"
|
||||
// https://on.cypress.io/contains
|
||||
cy.get('.assertion-table')
|
||||
.find('tbody tr:last')
|
||||
// finds first <td> element with text content matching regular expression
|
||||
.contains('td', /column content/i)
|
||||
.should('be.visible')
|
||||
|
||||
// for more information about asserting element's text
|
||||
// see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
|
||||
})
|
||||
|
||||
it('.and() - chain multiple assertions together', () => {
|
||||
// https://on.cypress.io/and
|
||||
cy.get('.assertions-link')
|
||||
.should('have.class', 'active')
|
||||
.and('have.attr', 'href')
|
||||
.and('include', 'cypress.io')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Explicit Assertions', () => {
|
||||
// https://on.cypress.io/assertions
|
||||
it('expect - make an assertion about a specified subject', () => {
|
||||
// We can use Chai's BDD style assertions
|
||||
expect(true).to.be.true
|
||||
const o = { foo: 'bar' }
|
||||
|
||||
expect(o).to.equal(o)
|
||||
expect(o).to.deep.equal({ foo: 'bar' })
|
||||
// matching text using regular expression
|
||||
expect('FooBar').to.match(/bar$/i)
|
||||
})
|
||||
|
||||
it('pass your own callback function to should()', () => {
|
||||
// Pass a function to should that can have any number
|
||||
// of explicit assertions within it.
|
||||
// The ".should(cb)" function will be retried
|
||||
// automatically until it passes all your explicit assertions or times out.
|
||||
cy.get('.assertions-p')
|
||||
.find('p')
|
||||
.should(($p) => {
|
||||
// https://on.cypress.io/$
|
||||
// return an array of texts from all of the p's
|
||||
// @ts-ignore TS6133 unused variable
|
||||
const texts = $p.map((i, el) => Cypress.$(el).text())
|
||||
|
||||
// jquery map returns jquery object
|
||||
// and .get() convert this to simple array
|
||||
const paragraphs = texts.get()
|
||||
|
||||
// array should have length of 3
|
||||
expect(paragraphs, 'has 3 paragraphs').to.have.length(3)
|
||||
|
||||
// use second argument to expect(...) to provide clear
|
||||
// message with each assertion
|
||||
expect(paragraphs, 'has expected text in each paragraph').to.deep.eq([
|
||||
'Some text from first p',
|
||||
'More text from second p',
|
||||
'And even more text from third p',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
it('finds element by class name regex', () => {
|
||||
cy.get('.docs-header')
|
||||
.find('div')
|
||||
// .should(cb) callback function will be retried
|
||||
.should(($div) => {
|
||||
expect($div).to.have.length(1)
|
||||
|
||||
const className = $div[0].className
|
||||
|
||||
expect(className).to.match(/heading-/)
|
||||
})
|
||||
// .then(cb) callback is not retried,
|
||||
// it either passes or fails
|
||||
.then(($div) => {
|
||||
expect($div, 'text content').to.have.text('Introduction')
|
||||
})
|
||||
})
|
||||
|
||||
it('can throw any error', () => {
|
||||
cy.get('.docs-header')
|
||||
.find('div')
|
||||
.should(($div) => {
|
||||
if ($div.length !== 1) {
|
||||
// you can throw your own errors
|
||||
throw new Error('Did not find 1 element')
|
||||
}
|
||||
|
||||
const className = $div[0].className
|
||||
|
||||
if (!className.match(/heading-/)) {
|
||||
throw new Error(`Could not find class "heading-" in ${className}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('matches unknown text between two elements', () => {
|
||||
/**
|
||||
* Text from the first element.
|
||||
* @type {string}
|
||||
*/
|
||||
let text
|
||||
|
||||
/**
|
||||
* Normalizes passed text,
|
||||
* useful before comparing text with spaces and different capitalization.
|
||||
* @param {string} s Text to normalize
|
||||
*/
|
||||
const normalizeText = (s) => s.replace(/\s/g, '').toLowerCase()
|
||||
|
||||
cy.get('.two-elements')
|
||||
.find('.first')
|
||||
.then(($first) => {
|
||||
// save text from the first element
|
||||
text = normalizeText($first.text())
|
||||
})
|
||||
|
||||
cy.get('.two-elements')
|
||||
.find('.second')
|
||||
.should(($div) => {
|
||||
// we can massage text before comparing
|
||||
const secondText = normalizeText($div.text())
|
||||
|
||||
expect(secondText, 'second text').to.equal(text)
|
||||
})
|
||||
})
|
||||
|
||||
it('assert - assert shape of an object', () => {
|
||||
const person = {
|
||||
name: 'Joe',
|
||||
age: 20,
|
||||
}
|
||||
|
||||
assert.isObject(person, 'value is object')
|
||||
})
|
||||
|
||||
it('retries the should callback until assertions pass', () => {
|
||||
cy.get('#random-number')
|
||||
.should(($div) => {
|
||||
const n = parseFloat($div.text())
|
||||
|
||||
expect(n).to.be.gte(1).and.be.lte(10)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,97 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Connectors', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/connectors')
|
||||
})
|
||||
|
||||
it('.each() - iterate over an array of elements', () => {
|
||||
// https://on.cypress.io/each
|
||||
cy.get('.connectors-each-ul>li')
|
||||
.each(($el, index, $list) => {
|
||||
console.log($el, index, $list)
|
||||
})
|
||||
})
|
||||
|
||||
it('.its() - get properties on the current subject', () => {
|
||||
// https://on.cypress.io/its
|
||||
cy.get('.connectors-its-ul>li')
|
||||
// calls the 'length' property yielding that value
|
||||
.its('length')
|
||||
.should('be.gt', 2)
|
||||
})
|
||||
|
||||
it('.invoke() - invoke a function on the current subject', () => {
|
||||
// our div is hidden in our script.js
|
||||
// $('.connectors-div').hide()
|
||||
|
||||
// https://on.cypress.io/invoke
|
||||
cy.get('.connectors-div').should('be.hidden')
|
||||
// call the jquery method 'show' on the 'div.container'
|
||||
.invoke('show')
|
||||
.should('be.visible')
|
||||
})
|
||||
|
||||
it('.spread() - spread an array as individual args to callback function', () => {
|
||||
// https://on.cypress.io/spread
|
||||
const arr = ['foo', 'bar', 'baz']
|
||||
|
||||
cy.wrap(arr).spread((foo, bar, baz) => {
|
||||
expect(foo).to.eq('foo')
|
||||
expect(bar).to.eq('bar')
|
||||
expect(baz).to.eq('baz')
|
||||
})
|
||||
})
|
||||
|
||||
describe('.then()', () => {
|
||||
it('invokes a callback function with the current subject', () => {
|
||||
// https://on.cypress.io/then
|
||||
cy.get('.connectors-list > li')
|
||||
.then(($lis) => {
|
||||
expect($lis, '3 items').to.have.length(3)
|
||||
expect($lis.eq(0), 'first item').to.contain('Walk the dog')
|
||||
expect($lis.eq(1), 'second item').to.contain('Feed the cat')
|
||||
expect($lis.eq(2), 'third item').to.contain('Write JavaScript')
|
||||
})
|
||||
})
|
||||
|
||||
it('yields the returned value to the next command', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
|
||||
return 2
|
||||
})
|
||||
.then((num) => {
|
||||
expect(num).to.equal(2)
|
||||
})
|
||||
})
|
||||
|
||||
it('yields the original subject without return', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
// note that nothing is returned from this callback
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the original unchanged value 1
|
||||
expect(num).to.equal(1)
|
||||
})
|
||||
})
|
||||
|
||||
it('yields the value yielded by the last Cypress command inside', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
// note how we run a Cypress command
|
||||
// the result yielded by this Cypress command
|
||||
// will be passed to the second ".then"
|
||||
cy.wrap(2)
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the value yielded by "cy.wrap(2)"
|
||||
expect(num).to.equal(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,77 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Cookies', () => {
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.debug(true)
|
||||
|
||||
cy.visit('https://example.cypress.io/commands/cookies')
|
||||
|
||||
// clear cookies again after visiting to remove
|
||||
// any 3rd party cookies picked up such as cloudflare
|
||||
cy.clearCookies()
|
||||
})
|
||||
|
||||
it('cy.getCookie() - get a browser cookie', () => {
|
||||
// https://on.cypress.io/getcookie
|
||||
cy.get('#getCookie .set-a-cookie').click()
|
||||
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie('token').should('have.property', 'value', '123ABC')
|
||||
})
|
||||
|
||||
it('cy.getCookies() - get browser cookies', () => {
|
||||
// https://on.cypress.io/getcookies
|
||||
cy.getCookies().should('be.empty')
|
||||
|
||||
cy.get('#getCookies .set-a-cookie').click()
|
||||
|
||||
// cy.getCookies() yields an array of cookies
|
||||
cy.getCookies().should('have.length', 1).should((cookies) => {
|
||||
// each cookie has these properties
|
||||
expect(cookies[0]).to.have.property('name', 'token')
|
||||
expect(cookies[0]).to.have.property('value', '123ABC')
|
||||
expect(cookies[0]).to.have.property('httpOnly', false)
|
||||
expect(cookies[0]).to.have.property('secure', false)
|
||||
expect(cookies[0]).to.have.property('domain')
|
||||
expect(cookies[0]).to.have.property('path')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.setCookie() - set a browser cookie', () => {
|
||||
// https://on.cypress.io/setcookie
|
||||
cy.getCookies().should('be.empty')
|
||||
|
||||
cy.setCookie('foo', 'bar')
|
||||
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie('foo').should('have.property', 'value', 'bar')
|
||||
})
|
||||
|
||||
it('cy.clearCookie() - clear a browser cookie', () => {
|
||||
// https://on.cypress.io/clearcookie
|
||||
cy.getCookie('token').should('be.null')
|
||||
|
||||
cy.get('#clearCookie .set-a-cookie').click()
|
||||
|
||||
cy.getCookie('token').should('have.property', 'value', '123ABC')
|
||||
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookie('token').should('be.null')
|
||||
|
||||
cy.getCookie('token').should('be.null')
|
||||
})
|
||||
|
||||
it('cy.clearCookies() - clear browser cookies', () => {
|
||||
// https://on.cypress.io/clearcookies
|
||||
cy.getCookies().should('be.empty')
|
||||
|
||||
cy.get('#clearCookies .set-a-cookie').click()
|
||||
|
||||
cy.getCookies().should('have.length', 1)
|
||||
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookies()
|
||||
|
||||
cy.getCookies().should('be.empty')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,202 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Cypress.Commands', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
// https://on.cypress.io/custom-commands
|
||||
|
||||
it('.add() - create a custom command', () => {
|
||||
Cypress.Commands.add('console', {
|
||||
prevSubject: true,
|
||||
}, (subject, method) => {
|
||||
// the previous subject is automatically received
|
||||
// and the commands arguments are shifted
|
||||
|
||||
// allow us to change the console method used
|
||||
method = method || 'log'
|
||||
|
||||
// log the subject to the console
|
||||
// @ts-ignore TS7017
|
||||
console[method]('The subject is', subject)
|
||||
|
||||
// whatever we return becomes the new subject
|
||||
// we don't want to change the subject so
|
||||
// we return whatever was passed in
|
||||
return subject
|
||||
})
|
||||
|
||||
// @ts-ignore TS2339
|
||||
cy.get('button').console('info').then(($button) => {
|
||||
// subject is still $button
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.Cookies', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
// https://on.cypress.io/cookies
|
||||
it('.debug() - enable or disable debugging', () => {
|
||||
Cypress.Cookies.debug(true)
|
||||
|
||||
// Cypress will now log in the console when
|
||||
// cookies are set or cleared
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
cy.clearCookie('fakeCookie')
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
cy.clearCookie('fakeCookie')
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
})
|
||||
|
||||
it('.preserveOnce() - preserve cookies by key', () => {
|
||||
// normally cookies are reset after each test
|
||||
cy.getCookie('fakeCookie').should('not.be.ok')
|
||||
|
||||
// preserving a cookie will not clear it when
|
||||
// the next test starts
|
||||
cy.setCookie('lastCookie', '789XYZ')
|
||||
Cypress.Cookies.preserveOnce('lastCookie')
|
||||
})
|
||||
|
||||
it('.defaults() - set defaults for all cookies', () => {
|
||||
// now any cookie with the name 'session_id' will
|
||||
// not be cleared before each new test runs
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: 'session_id',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.arch', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Get CPU architecture name of underlying OS', () => {
|
||||
// https://on.cypress.io/arch
|
||||
expect(Cypress.arch).to.exist
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.config()', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Get and set configuration options', () => {
|
||||
// https://on.cypress.io/config
|
||||
let myConfig = Cypress.config()
|
||||
|
||||
expect(myConfig).to.have.property('animationDistanceThreshold', 5)
|
||||
expect(myConfig).to.have.property('baseUrl', null)
|
||||
expect(myConfig).to.have.property('defaultCommandTimeout', 4000)
|
||||
expect(myConfig).to.have.property('requestTimeout', 5000)
|
||||
expect(myConfig).to.have.property('responseTimeout', 30000)
|
||||
expect(myConfig).to.have.property('viewportHeight', 660)
|
||||
expect(myConfig).to.have.property('viewportWidth', 1000)
|
||||
expect(myConfig).to.have.property('pageLoadTimeout', 60000)
|
||||
expect(myConfig).to.have.property('waitForAnimations', true)
|
||||
|
||||
expect(Cypress.config('pageLoadTimeout')).to.eq(60000)
|
||||
|
||||
// this will change the config for the rest of your tests!
|
||||
Cypress.config('pageLoadTimeout', 20000)
|
||||
|
||||
expect(Cypress.config('pageLoadTimeout')).to.eq(20000)
|
||||
|
||||
Cypress.config('pageLoadTimeout', 60000)
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.dom', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
// https://on.cypress.io/dom
|
||||
it('.isHidden() - determine if a DOM element is hidden', () => {
|
||||
let hiddenP = Cypress.$('.dom-p p.hidden').get(0)
|
||||
let visibleP = Cypress.$('.dom-p p.visible').get(0)
|
||||
|
||||
// our first paragraph has css class 'hidden'
|
||||
expect(Cypress.dom.isHidden(hiddenP)).to.be.true
|
||||
expect(Cypress.dom.isHidden(visibleP)).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.env()', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
// We can set environment variables for highly dynamic values
|
||||
|
||||
// https://on.cypress.io/environment-variables
|
||||
it('Get environment variables', () => {
|
||||
// https://on.cypress.io/env
|
||||
// set multiple environment variables
|
||||
Cypress.env({
|
||||
host: 'veronica.dev.local',
|
||||
api_server: 'http://localhost:8888/v1/',
|
||||
})
|
||||
|
||||
// get environment variable
|
||||
expect(Cypress.env('host')).to.eq('veronica.dev.local')
|
||||
|
||||
// set environment variable
|
||||
Cypress.env('api_server', 'http://localhost:8888/v2/')
|
||||
expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/')
|
||||
|
||||
// get all environment variable
|
||||
expect(Cypress.env()).to.have.property('host', 'veronica.dev.local')
|
||||
expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/')
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.log', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Control what is printed to the Command Log', () => {
|
||||
// https://on.cypress.io/cypress-log
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.platform', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Get underlying OS name', () => {
|
||||
// https://on.cypress.io/platform
|
||||
expect(Cypress.platform).to.be.exist
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.version', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Get current version of Cypress being run', () => {
|
||||
// https://on.cypress.io/version
|
||||
expect(Cypress.version).to.be.exist
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.spec', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
|
||||
it('Get current spec information', () => {
|
||||
// https://on.cypress.io/spec
|
||||
// wrap the object so we can inspect it easily by clicking in the command log
|
||||
cy.wrap(Cypress.spec).should('include.keys', ['name', 'relative', 'absolute'])
|
||||
})
|
||||
})
|
||||
88
client/cypress/integration/2-advanced-examples/files.spec.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
/// JSON fixture file can be loaded directly using
|
||||
// the built-in JavaScript bundler
|
||||
// @ts-ignore
|
||||
const requiredExample = require('../../fixtures/example')
|
||||
|
||||
context('Files', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/files')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// load example.json fixture file and store
|
||||
// in the test context object
|
||||
cy.fixture('example.json').as('example')
|
||||
})
|
||||
|
||||
it('cy.fixture() - load a fixture', () => {
|
||||
// https://on.cypress.io/fixture
|
||||
|
||||
// Instead of writing a response inline you can
|
||||
// use a fixture file's content.
|
||||
|
||||
// when application makes an Ajax request matching "GET **/comments/*"
|
||||
// Cypress will intercept it and reply with the object in `example.json` fixture
|
||||
cy.intercept('GET', '**/comments/*', { fixture: 'example.json' }).as('getComment')
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.fixture-btn').click()
|
||||
|
||||
cy.wait('@getComment').its('response.body')
|
||||
.should('have.property', 'name')
|
||||
.and('include', 'Using fixtures to represent data')
|
||||
})
|
||||
|
||||
it('cy.fixture() or require - load a fixture', function () {
|
||||
// we are inside the "function () { ... }"
|
||||
// callback and can use test context object "this"
|
||||
// "this.example" was loaded in "beforeEach" function callback
|
||||
expect(this.example, 'fixture in the test context')
|
||||
.to.deep.equal(requiredExample)
|
||||
|
||||
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
|
||||
cy.wrap(this.example)
|
||||
.should('deep.equal', requiredExample)
|
||||
})
|
||||
|
||||
it('cy.readFile() - read file contents', () => {
|
||||
// https://on.cypress.io/readfile
|
||||
|
||||
// You can read a file and yield its contents
|
||||
// The filePath is relative to your project's root.
|
||||
cy.readFile('cypress.json').then((json) => {
|
||||
expect(json).to.be.an('object')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.writeFile() - write to a file', () => {
|
||||
// https://on.cypress.io/writefile
|
||||
|
||||
// You can write to a file
|
||||
|
||||
// Use a response from a request to automatically
|
||||
// generate a fixture file for use later
|
||||
cy.request('https://jsonplaceholder.cypress.io/users')
|
||||
.then((response) => {
|
||||
cy.writeFile('cypress/fixtures/users.json', response.body)
|
||||
})
|
||||
|
||||
cy.fixture('users').should((users) => {
|
||||
expect(users[0].name).to.exist
|
||||
})
|
||||
|
||||
// JavaScript arrays and objects are stringified
|
||||
// and formatted into text.
|
||||
cy.writeFile('cypress/fixtures/profile.json', {
|
||||
id: 8739,
|
||||
name: 'Jane',
|
||||
email: 'jane@example.com',
|
||||
})
|
||||
|
||||
cy.fixture('profile').should((profile) => {
|
||||
expect(profile.name).to.eq('Jane')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,52 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Local Storage', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/local-storage')
|
||||
})
|
||||
// Although local storage is automatically cleared
|
||||
// in between tests to maintain a clean state
|
||||
// sometimes we need to clear the local storage manually
|
||||
|
||||
it('cy.clearLocalStorage() - clear all data in local storage', () => {
|
||||
// https://on.cypress.io/clearlocalstorage
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
|
||||
// clearLocalStorage() yields the localStorage object
|
||||
cy.clearLocalStorage().should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.be.null
|
||||
expect(ls.getItem('prop3')).to.be.null
|
||||
})
|
||||
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
|
||||
// Clear key matching string in Local Storage
|
||||
cy.clearLocalStorage('prop1').should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.eq('blue')
|
||||
expect(ls.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
|
||||
// Clear keys matching regex in Local Storage
|
||||
cy.clearLocalStorage(/prop1|2/).should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.be.null
|
||||
expect(ls.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Location', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/location')
|
||||
})
|
||||
|
||||
it('cy.hash() - get the current URL hash', () => {
|
||||
// https://on.cypress.io/hash
|
||||
cy.hash().should('be.empty')
|
||||
})
|
||||
|
||||
it('cy.location() - get window.location', () => {
|
||||
// https://on.cypress.io/location
|
||||
cy.location().should((location) => {
|
||||
expect(location.hash).to.be.empty
|
||||
expect(location.href).to.eq('https://example.cypress.io/commands/location')
|
||||
expect(location.host).to.eq('example.cypress.io')
|
||||
expect(location.hostname).to.eq('example.cypress.io')
|
||||
expect(location.origin).to.eq('https://example.cypress.io')
|
||||
expect(location.pathname).to.eq('/commands/location')
|
||||
expect(location.port).to.eq('')
|
||||
expect(location.protocol).to.eq('https:')
|
||||
expect(location.search).to.be.empty
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.url() - get the current URL', () => {
|
||||
// https://on.cypress.io/url
|
||||
cy.url().should('eq', 'https://example.cypress.io/commands/location')
|
||||
})
|
||||
})
|
||||
104
client/cypress/integration/2-advanced-examples/misc.spec.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Misc', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/misc')
|
||||
})
|
||||
|
||||
it('.end() - end the command chain', () => {
|
||||
// https://on.cypress.io/end
|
||||
|
||||
// cy.end is useful when you want to end a chain of commands
|
||||
// and force Cypress to re-query from the root element
|
||||
cy.get('.misc-table').within(() => {
|
||||
// ends the current chain and yields null
|
||||
cy.contains('Cheryl').click().end()
|
||||
|
||||
// queries the entire table again
|
||||
cy.contains('Charles').click()
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.exec() - execute a system command', () => {
|
||||
// execute a system command.
|
||||
// so you can take actions necessary for
|
||||
// your test outside the scope of Cypress.
|
||||
// https://on.cypress.io/exec
|
||||
|
||||
// we can use Cypress.platform string to
|
||||
// select appropriate command
|
||||
// https://on.cypress/io/platform
|
||||
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`)
|
||||
|
||||
// on CircleCI Windows build machines we have a failure to run bash shell
|
||||
// https://github.com/cypress-io/cypress/issues/5169
|
||||
// so skip some of the tests by passing flag "--env circle=true"
|
||||
const isCircleOnWindows = Cypress.platform === 'win32' && Cypress.env('circle')
|
||||
|
||||
if (isCircleOnWindows) {
|
||||
cy.log('Skipping test on CircleCI')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// cy.exec problem on Shippable CI
|
||||
// https://github.com/cypress-io/cypress/issues/6718
|
||||
const isShippable = Cypress.platform === 'linux' && Cypress.env('shippable')
|
||||
|
||||
if (isShippable) {
|
||||
cy.log('Skipping test on ShippableCI')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cy.exec('echo Jane Lane')
|
||||
.its('stdout').should('contain', 'Jane Lane')
|
||||
|
||||
if (Cypress.platform === 'win32') {
|
||||
cy.exec('print cypress.json')
|
||||
.its('stderr').should('be.empty')
|
||||
} else {
|
||||
cy.exec('cat cypress.json')
|
||||
.its('stderr').should('be.empty')
|
||||
|
||||
cy.exec('pwd')
|
||||
.its('code').should('eq', 0)
|
||||
}
|
||||
})
|
||||
|
||||
it('cy.focused() - get the DOM element that has focus', () => {
|
||||
// https://on.cypress.io/focused
|
||||
cy.get('.misc-form').find('#name').click()
|
||||
cy.focused().should('have.id', 'name')
|
||||
|
||||
cy.get('.misc-form').find('#description').click()
|
||||
cy.focused().should('have.id', 'description')
|
||||
})
|
||||
|
||||
context('Cypress.Screenshot', function () {
|
||||
it('cy.screenshot() - take a screenshot', () => {
|
||||
// https://on.cypress.io/screenshot
|
||||
cy.screenshot('my-image')
|
||||
})
|
||||
|
||||
it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
|
||||
Cypress.Screenshot.defaults({
|
||||
blackout: ['.foo'],
|
||||
capture: 'viewport',
|
||||
clip: { x: 0, y: 0, width: 200, height: 200 },
|
||||
scale: false,
|
||||
disableTimersAndAnimations: true,
|
||||
screenshotOnRunFailure: true,
|
||||
onBeforeScreenshot () { },
|
||||
onAfterScreenshot () { },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.wrap() - wrap an object', () => {
|
||||
// https://on.cypress.io/wrap
|
||||
cy.wrap({ foo: 'bar' })
|
||||
.should('have.property', 'foo')
|
||||
.and('include', 'bar')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,56 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Navigation', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io')
|
||||
cy.get('.navbar-nav').contains('Commands').click()
|
||||
cy.get('.dropdown-menu').contains('Navigation').click()
|
||||
})
|
||||
|
||||
it('cy.go() - go back or forward in the browser\'s history', () => {
|
||||
// https://on.cypress.io/go
|
||||
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
|
||||
cy.go('back')
|
||||
cy.location('pathname').should('not.include', 'navigation')
|
||||
|
||||
cy.go('forward')
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
|
||||
// clicking back
|
||||
cy.go(-1)
|
||||
cy.location('pathname').should('not.include', 'navigation')
|
||||
|
||||
// clicking forward
|
||||
cy.go(1)
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
})
|
||||
|
||||
it('cy.reload() - reload the page', () => {
|
||||
// https://on.cypress.io/reload
|
||||
cy.reload()
|
||||
|
||||
// reload the page without using the cache
|
||||
cy.reload(true)
|
||||
})
|
||||
|
||||
it('cy.visit() - visit a remote url', () => {
|
||||
// https://on.cypress.io/visit
|
||||
|
||||
// Visit any sub-domain of your current domain
|
||||
|
||||
// Pass options to the visit
|
||||
cy.visit('https://example.cypress.io/commands/navigation', {
|
||||
timeout: 50000, // increase total time for the visit to resolve
|
||||
onBeforeLoad (contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === 'object').to.be.true
|
||||
},
|
||||
onLoad (contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === 'object').to.be.true
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,163 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Network Requests', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/network-requests')
|
||||
})
|
||||
|
||||
// Manage HTTP requests in your app
|
||||
|
||||
it('cy.request() - make an XHR request', () => {
|
||||
// https://on.cypress.io/request
|
||||
cy.request('https://jsonplaceholder.cypress.io/comments')
|
||||
.should((response) => {
|
||||
expect(response.status).to.eq(200)
|
||||
// the server sometimes gets an extra comment posted from another machine
|
||||
// which gets returned as 1 extra object
|
||||
expect(response.body).to.have.property('length').and.be.oneOf([500, 501])
|
||||
expect(response).to.have.property('headers')
|
||||
expect(response).to.have.property('duration')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.request() - verify response using BDD syntax', () => {
|
||||
cy.request('https://jsonplaceholder.cypress.io/comments')
|
||||
.then((response) => {
|
||||
// https://on.cypress.io/assertions
|
||||
expect(response).property('status').to.equal(200)
|
||||
expect(response).property('body').to.have.property('length').and.be.oneOf([500, 501])
|
||||
expect(response).to.include.keys('headers', 'duration')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.request() with query parameters', () => {
|
||||
// will execute request
|
||||
// https://jsonplaceholder.cypress.io/comments?postId=1&id=3
|
||||
cy.request({
|
||||
url: 'https://jsonplaceholder.cypress.io/comments',
|
||||
qs: {
|
||||
postId: 1,
|
||||
id: 3,
|
||||
},
|
||||
})
|
||||
.its('body')
|
||||
.should('be.an', 'array')
|
||||
.and('have.length', 1)
|
||||
.its('0') // yields first element of the array
|
||||
.should('contain', {
|
||||
postId: 1,
|
||||
id: 3,
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.request() - pass result to the second request', () => {
|
||||
// first, let's find out the userId of the first user we have
|
||||
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
||||
.its('body') // yields the response object
|
||||
.its('0') // yields the first element of the returned list
|
||||
// the above two commands its('body').its('0')
|
||||
// can be written as its('body.0')
|
||||
// if you do not care about TypeScript checks
|
||||
.then((user) => {
|
||||
expect(user).property('id').to.be.a('number')
|
||||
// make a new post on behalf of the user
|
||||
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
||||
userId: user.id,
|
||||
title: 'Cypress Test Runner',
|
||||
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
||||
})
|
||||
})
|
||||
// note that the value here is the returned value of the 2nd request
|
||||
// which is the new post object
|
||||
.then((response) => {
|
||||
expect(response).property('status').to.equal(201) // new entity created
|
||||
expect(response).property('body').to.contain({
|
||||
title: 'Cypress Test Runner',
|
||||
})
|
||||
|
||||
// we don't know the exact post id - only that it will be > 100
|
||||
// since JSONPlaceholder has built-in 100 posts
|
||||
expect(response.body).property('id').to.be.a('number')
|
||||
.and.to.be.gt(100)
|
||||
|
||||
// we don't know the user id here - since it was in above closure
|
||||
// so in this test just confirm that the property is there
|
||||
expect(response.body).property('userId').to.be.a('number')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.request() - save response in the shared test context', () => {
|
||||
// https://on.cypress.io/variables-and-aliases
|
||||
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
||||
.its('body').its('0') // yields the first element of the returned list
|
||||
.as('user') // saves the object in the test context
|
||||
.then(function () {
|
||||
// NOTE 👀
|
||||
// By the time this callback runs the "as('user')" command
|
||||
// has saved the user object in the test context.
|
||||
// To access the test context we need to use
|
||||
// the "function () { ... }" callback form,
|
||||
// otherwise "this" points at a wrong or undefined object!
|
||||
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
||||
userId: this.user.id,
|
||||
title: 'Cypress Test Runner',
|
||||
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
||||
})
|
||||
.its('body').as('post') // save the new post from the response
|
||||
})
|
||||
.then(function () {
|
||||
// When this callback runs, both "cy.request" API commands have finished
|
||||
// and the test context has "user" and "post" objects set.
|
||||
// Let's verify them.
|
||||
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id)
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.intercept() - route responses to matching requests', () => {
|
||||
// https://on.cypress.io/intercept
|
||||
|
||||
let message = 'whoa, this comment does not exist'
|
||||
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
|
||||
// Listen to POST to comments
|
||||
cy.intercept('POST', '**/comments').as('postComment')
|
||||
|
||||
// we have code that posts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-post').click()
|
||||
cy.wait('@postComment').should(({ request, response }) => {
|
||||
expect(request.body).to.include('email')
|
||||
expect(request.headers).to.have.property('content-type')
|
||||
expect(response && response.body).to.have.property('name', 'Using POST in cy.intercept()')
|
||||
})
|
||||
|
||||
// Stub a response to PUT comments/ ****
|
||||
cy.intercept({
|
||||
method: 'PUT',
|
||||
url: '**/comments/*',
|
||||
}, {
|
||||
statusCode: 404,
|
||||
body: { error: message },
|
||||
headers: { 'access-control-allow-origin': '*' },
|
||||
delayMs: 500,
|
||||
}).as('putComment')
|
||||
|
||||
// we have code that puts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-put').click()
|
||||
|
||||
cy.wait('@putComment')
|
||||
|
||||
// our 404 statusCode logic in scripts.js executed
|
||||
cy.get('.network-put-comment').should('contain', message)
|
||||
})
|
||||
})
|
||||
114
client/cypress/integration/2-advanced-examples/querying.spec.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Querying', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/querying')
|
||||
})
|
||||
|
||||
// The most commonly used query is 'cy.get()', you can
|
||||
// think of this like the '$' in jQuery
|
||||
|
||||
it('cy.get() - query DOM elements', () => {
|
||||
// https://on.cypress.io/get
|
||||
|
||||
cy.get('#query-btn').should('contain', 'Button')
|
||||
|
||||
cy.get('.query-btn').should('contain', 'Button')
|
||||
|
||||
cy.get('#querying .well>button:first').should('contain', 'Button')
|
||||
// ↲
|
||||
// Use CSS selectors just like jQuery
|
||||
|
||||
cy.get('[data-test-id="test-example"]').should('have.class', 'example')
|
||||
|
||||
// 'cy.get()' yields jQuery object, you can get its attribute
|
||||
// by invoking `.attr()` method
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'test-example')
|
||||
|
||||
// or you can get element's CSS property
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.invoke('css', 'position')
|
||||
.should('equal', 'static')
|
||||
|
||||
// or use assertions directly during 'cy.get()'
|
||||
// https://on.cypress.io/assertions
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.should('have.attr', 'data-test-id', 'test-example')
|
||||
.and('have.css', 'position', 'static')
|
||||
})
|
||||
|
||||
it('cy.contains() - query DOM elements with matching content', () => {
|
||||
// https://on.cypress.io/contains
|
||||
cy.get('.query-list')
|
||||
.contains('bananas')
|
||||
.should('have.class', 'third')
|
||||
|
||||
// we can pass a regexp to `.contains()`
|
||||
cy.get('.query-list')
|
||||
.contains(/^b\w+/)
|
||||
.should('have.class', 'third')
|
||||
|
||||
cy.get('.query-list')
|
||||
.contains('apples')
|
||||
.should('have.class', 'first')
|
||||
|
||||
// passing a selector to contains will
|
||||
// yield the selector containing the text
|
||||
cy.get('#querying')
|
||||
.contains('ul', 'oranges')
|
||||
.should('have.class', 'query-list')
|
||||
|
||||
cy.get('.query-button')
|
||||
.contains('Save Form')
|
||||
.should('have.class', 'btn')
|
||||
})
|
||||
|
||||
it('.within() - query DOM elements within a specific element', () => {
|
||||
// https://on.cypress.io/within
|
||||
cy.get('.query-form').within(() => {
|
||||
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
|
||||
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
|
||||
})
|
||||
})
|
||||
|
||||
it('cy.root() - query the root DOM element', () => {
|
||||
// https://on.cypress.io/root
|
||||
|
||||
// By default, root is the document
|
||||
cy.root().should('match', 'html')
|
||||
|
||||
cy.get('.query-ul').within(() => {
|
||||
// In this within, the root is now the ul DOM element
|
||||
cy.root().should('have.class', 'query-ul')
|
||||
})
|
||||
})
|
||||
|
||||
it('best practices - selecting elements', () => {
|
||||
// https://on.cypress.io/best-practices#Selecting-Elements
|
||||
cy.get('[data-cy=best-practices-selecting-elements]').within(() => {
|
||||
// Worst - too generic, no context
|
||||
cy.get('button').click()
|
||||
|
||||
// Bad. Coupled to styling. Highly subject to change.
|
||||
cy.get('.btn.btn-large').click()
|
||||
|
||||
// Average. Coupled to the `name` attribute which has HTML semantics.
|
||||
cy.get('[name=submission]').click()
|
||||
|
||||
// Better. But still coupled to styling or JS event listeners.
|
||||
cy.get('#main').click()
|
||||
|
||||
// Slightly better. Uses an ID but also ensures the element
|
||||
// has an ARIA role attribute
|
||||
cy.get('#main[role=button]').click()
|
||||
|
||||
// Much better. But still coupled to text content that may change.
|
||||
cy.contains('Submit').click()
|
||||
|
||||
// Best. Insulated from all changes.
|
||||
cy.get('[data-cy=submit]').click()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,205 @@
|
||||
/// <reference types="cypress" />
|
||||
// remove no check once Cypress.sinon is typed
|
||||
// https://github.com/cypress-io/cypress/issues/6720
|
||||
|
||||
context('Spies, Stubs, and Clock', () => {
|
||||
it('cy.spy() - wrap a method in a spy', () => {
|
||||
// https://on.cypress.io/spy
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
|
||||
const obj = {
|
||||
foo () {},
|
||||
}
|
||||
|
||||
const spy = cy.spy(obj, 'foo').as('anyArgs')
|
||||
|
||||
obj.foo()
|
||||
|
||||
expect(spy).to.be.called
|
||||
})
|
||||
|
||||
it('cy.spy() retries until assertions pass', () => {
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
|
||||
const obj = {
|
||||
/**
|
||||
* Prints the argument passed
|
||||
* @param x {any}
|
||||
*/
|
||||
foo (x) {
|
||||
console.log('obj.foo called with', x)
|
||||
},
|
||||
}
|
||||
|
||||
cy.spy(obj, 'foo').as('foo')
|
||||
|
||||
setTimeout(() => {
|
||||
obj.foo('first')
|
||||
}, 500)
|
||||
|
||||
setTimeout(() => {
|
||||
obj.foo('second')
|
||||
}, 2500)
|
||||
|
||||
cy.get('@foo').should('have.been.calledTwice')
|
||||
})
|
||||
|
||||
it('cy.stub() - create a stub and/or replace a function with stub', () => {
|
||||
// https://on.cypress.io/stub
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
|
||||
const obj = {
|
||||
/**
|
||||
* prints both arguments to the console
|
||||
* @param a {string}
|
||||
* @param b {string}
|
||||
*/
|
||||
foo (a, b) {
|
||||
console.log('a', a, 'b', b)
|
||||
},
|
||||
}
|
||||
|
||||
const stub = cy.stub(obj, 'foo').as('foo')
|
||||
|
||||
obj.foo('foo', 'bar')
|
||||
|
||||
expect(stub).to.be.called
|
||||
})
|
||||
|
||||
it('cy.clock() - control time in the browser', () => {
|
||||
// https://on.cypress.io/clock
|
||||
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
|
||||
|
||||
cy.clock(now)
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
cy.get('#clock-div').click()
|
||||
.should('have.text', '1489449600')
|
||||
})
|
||||
|
||||
it('cy.tick() - move time in the browser', () => {
|
||||
// https://on.cypress.io/tick
|
||||
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
|
||||
|
||||
cy.clock(now)
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
cy.get('#tick-div').click()
|
||||
.should('have.text', '1489449600')
|
||||
|
||||
cy.tick(10000) // 10 seconds passed
|
||||
cy.get('#tick-div').click()
|
||||
.should('have.text', '1489449610')
|
||||
})
|
||||
|
||||
it('cy.stub() matches depending on arguments', () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const greeter = {
|
||||
/**
|
||||
* Greets a person
|
||||
* @param {string} name
|
||||
*/
|
||||
greet (name) {
|
||||
return `Hello, ${name}!`
|
||||
},
|
||||
}
|
||||
|
||||
cy.stub(greeter, 'greet')
|
||||
.callThrough() // if you want non-matched calls to call the real method
|
||||
.withArgs(Cypress.sinon.match.string).returns('Hi')
|
||||
.withArgs(Cypress.sinon.match.number).throws(new Error('Invalid name'))
|
||||
|
||||
expect(greeter.greet('World')).to.equal('Hi')
|
||||
// @ts-ignore
|
||||
expect(() => greeter.greet(42)).to.throw('Invalid name')
|
||||
expect(greeter.greet).to.have.been.calledTwice
|
||||
|
||||
// non-matched calls goes the actual method
|
||||
// @ts-ignore
|
||||
expect(greeter.greet()).to.equal('Hello, undefined!')
|
||||
})
|
||||
|
||||
it('matches call arguments using Sinon matchers', () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const calculator = {
|
||||
/**
|
||||
* returns the sum of two arguments
|
||||
* @param a {number}
|
||||
* @param b {number}
|
||||
*/
|
||||
add (a, b) {
|
||||
return a + b
|
||||
},
|
||||
}
|
||||
|
||||
const spy = cy.spy(calculator, 'add').as('add')
|
||||
|
||||
expect(calculator.add(2, 3)).to.equal(5)
|
||||
|
||||
// if we want to assert the exact values used during the call
|
||||
expect(spy).to.be.calledWith(2, 3)
|
||||
|
||||
// let's confirm "add" method was called with two numbers
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.number, Cypress.sinon.match.number)
|
||||
|
||||
// alternatively, provide the value to match
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(2), Cypress.sinon.match(3))
|
||||
|
||||
// match any value
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3)
|
||||
|
||||
// match any value from a list
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3)
|
||||
|
||||
/**
|
||||
* Returns true if the given number is event
|
||||
* @param {number} x
|
||||
*/
|
||||
const isEven = (x) => x % 2 === 0
|
||||
|
||||
// expect the value to pass a custom predicate function
|
||||
// the second argument to "sinon.match(predicate, message)" is
|
||||
// shown if the predicate does not pass and assertion fails
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, 'isEven'), 3)
|
||||
|
||||
/**
|
||||
* Returns a function that checks if a given number is larger than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isGreaterThan = (limit) => (x) => x > limit
|
||||
|
||||
/**
|
||||
* Returns a function that checks if a given number is less than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isLessThan = (limit) => (x) => x < limit
|
||||
|
||||
// you can combine several matchers using "and", "or"
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(2), '> 2').and(Cypress.sinon.match(isLessThan(4), '< 4')),
|
||||
)
|
||||
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(200), '> 200').or(Cypress.sinon.match(3)),
|
||||
)
|
||||
|
||||
// matchers can be used from BDD assertions
|
||||
cy.get('@add').should('have.been.calledWith',
|
||||
Cypress.sinon.match.number, Cypress.sinon.match(3))
|
||||
|
||||
// you can alias matchers for shorter test code
|
||||
const { match: M } = Cypress.sinon
|
||||
|
||||
cy.get('@add').should('have.been.calledWith', M.number, M(3))
|
||||
})
|
||||
})
|
||||
121
client/cypress/integration/2-advanced-examples/traversal.spec.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Traversal', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/traversal')
|
||||
})
|
||||
|
||||
it('.children() - get child DOM elements', () => {
|
||||
// https://on.cypress.io/children
|
||||
cy.get('.traversal-breadcrumb')
|
||||
.children('.active')
|
||||
.should('contain', 'Data')
|
||||
})
|
||||
|
||||
it('.closest() - get closest ancestor DOM element', () => {
|
||||
// https://on.cypress.io/closest
|
||||
cy.get('.traversal-badge')
|
||||
.closest('ul')
|
||||
.should('have.class', 'list-group')
|
||||
})
|
||||
|
||||
it('.eq() - get a DOM element at a specific index', () => {
|
||||
// https://on.cypress.io/eq
|
||||
cy.get('.traversal-list>li')
|
||||
.eq(1).should('contain', 'siamese')
|
||||
})
|
||||
|
||||
it('.filter() - get DOM elements that match the selector', () => {
|
||||
// https://on.cypress.io/filter
|
||||
cy.get('.traversal-nav>li')
|
||||
.filter('.active').should('contain', 'About')
|
||||
})
|
||||
|
||||
it('.find() - get descendant DOM elements of the selector', () => {
|
||||
// https://on.cypress.io/find
|
||||
cy.get('.traversal-pagination')
|
||||
.find('li').find('a')
|
||||
.should('have.length', 7)
|
||||
})
|
||||
|
||||
it('.first() - get first DOM element', () => {
|
||||
// https://on.cypress.io/first
|
||||
cy.get('.traversal-table td')
|
||||
.first().should('contain', '1')
|
||||
})
|
||||
|
||||
it('.last() - get last DOM element', () => {
|
||||
// https://on.cypress.io/last
|
||||
cy.get('.traversal-buttons .btn')
|
||||
.last().should('contain', 'Submit')
|
||||
})
|
||||
|
||||
it('.next() - get next sibling DOM element', () => {
|
||||
// https://on.cypress.io/next
|
||||
cy.get('.traversal-ul')
|
||||
.contains('apples').next().should('contain', 'oranges')
|
||||
})
|
||||
|
||||
it('.nextAll() - get all next sibling DOM elements', () => {
|
||||
// https://on.cypress.io/nextall
|
||||
cy.get('.traversal-next-all')
|
||||
.contains('oranges')
|
||||
.nextAll().should('have.length', 3)
|
||||
})
|
||||
|
||||
it('.nextUntil() - get next sibling DOM elements until next el', () => {
|
||||
// https://on.cypress.io/nextuntil
|
||||
cy.get('#veggies')
|
||||
.nextUntil('#nuts').should('have.length', 3)
|
||||
})
|
||||
|
||||
it('.not() - remove DOM elements from set of DOM elements', () => {
|
||||
// https://on.cypress.io/not
|
||||
cy.get('.traversal-disabled .btn')
|
||||
.not('[disabled]').should('not.contain', 'Disabled')
|
||||
})
|
||||
|
||||
it('.parent() - get parent DOM element from DOM elements', () => {
|
||||
// https://on.cypress.io/parent
|
||||
cy.get('.traversal-mark')
|
||||
.parent().should('contain', 'Morbi leo risus')
|
||||
})
|
||||
|
||||
it('.parents() - get parent DOM elements from DOM elements', () => {
|
||||
// https://on.cypress.io/parents
|
||||
cy.get('.traversal-cite')
|
||||
.parents().should('match', 'blockquote')
|
||||
})
|
||||
|
||||
it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {
|
||||
// https://on.cypress.io/parentsuntil
|
||||
cy.get('.clothes-nav')
|
||||
.find('.active')
|
||||
.parentsUntil('.clothes-nav')
|
||||
.should('have.length', 2)
|
||||
})
|
||||
|
||||
it('.prev() - get previous sibling DOM element', () => {
|
||||
// https://on.cypress.io/prev
|
||||
cy.get('.birds').find('.active')
|
||||
.prev().should('contain', 'Lorikeets')
|
||||
})
|
||||
|
||||
it('.prevAll() - get all previous sibling DOM elements', () => {
|
||||
// https://on.cypress.io/prevall
|
||||
cy.get('.fruits-list').find('.third')
|
||||
.prevAll().should('have.length', 2)
|
||||
})
|
||||
|
||||
it('.prevUntil() - get all previous sibling DOM elements until el', () => {
|
||||
// https://on.cypress.io/prevuntil
|
||||
cy.get('.foods-list').find('#nuts')
|
||||
.prevUntil('#veggies').should('have.length', 3)
|
||||
})
|
||||
|
||||
it('.siblings() - get all sibling DOM elements', () => {
|
||||
// https://on.cypress.io/siblings
|
||||
cy.get('.traversal-pills .active')
|
||||
.siblings().should('have.length', 2)
|
||||
})
|
||||
})
|
||||
110
client/cypress/integration/2-advanced-examples/utilities.spec.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Utilities', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/utilities')
|
||||
})
|
||||
|
||||
it('Cypress._ - call a lodash method', () => {
|
||||
// https://on.cypress.io/_
|
||||
cy.request('https://jsonplaceholder.cypress.io/users')
|
||||
.then((response) => {
|
||||
let ids = Cypress._.chain(response.body).map('id').take(3).value()
|
||||
|
||||
expect(ids).to.deep.eq([1, 2, 3])
|
||||
})
|
||||
})
|
||||
|
||||
it('Cypress.$ - call a jQuery method', () => {
|
||||
// https://on.cypress.io/$
|
||||
let $li = Cypress.$('.utility-jquery li:first')
|
||||
|
||||
cy.wrap($li)
|
||||
.should('not.have.class', 'active')
|
||||
.click()
|
||||
.should('have.class', 'active')
|
||||
})
|
||||
|
||||
it('Cypress.Blob - blob utilities and base64 string conversion', () => {
|
||||
// https://on.cypress.io/blob
|
||||
cy.get('.utility-blob').then(($div) => {
|
||||
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
|
||||
// get the dataUrl string for the javascript-logo
|
||||
return Cypress.Blob.imgSrcToDataURL('https://example.cypress.io/assets/img/javascript-logo.png', undefined, 'anonymous')
|
||||
.then((dataUrl) => {
|
||||
// create an <img> element and set its src to the dataUrl
|
||||
let img = Cypress.$('<img />', { src: dataUrl })
|
||||
|
||||
// need to explicitly return cy here since we are initially returning
|
||||
// the Cypress.Blob.imgSrcToDataURL promise to our test
|
||||
// append the image
|
||||
$div.append(img)
|
||||
|
||||
cy.get('.utility-blob img').click()
|
||||
.should('have.attr', 'src', dataUrl)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Cypress.minimatch - test out glob patterns against strings', () => {
|
||||
// https://on.cypress.io/minimatch
|
||||
let matching = Cypress.minimatch('/users/1/comments', '/users/*/comments', {
|
||||
matchBase: true,
|
||||
})
|
||||
|
||||
expect(matching, 'matching wildcard').to.be.true
|
||||
|
||||
matching = Cypress.minimatch('/users/1/comments/2', '/users/*/comments', {
|
||||
matchBase: true,
|
||||
})
|
||||
|
||||
expect(matching, 'comments').to.be.false
|
||||
|
||||
// ** matches against all downstream path segments
|
||||
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/**', {
|
||||
matchBase: true,
|
||||
})
|
||||
|
||||
expect(matching, 'comments').to.be.true
|
||||
|
||||
// whereas * matches only the next path segment
|
||||
|
||||
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/*', {
|
||||
matchBase: false,
|
||||
})
|
||||
|
||||
expect(matching, 'comments').to.be.false
|
||||
})
|
||||
|
||||
it('Cypress.Promise - instantiate a bluebird promise', () => {
|
||||
// https://on.cypress.io/promise
|
||||
let waited = false
|
||||
|
||||
/**
|
||||
* @return Bluebird<string>
|
||||
*/
|
||||
function waitOneSecond () {
|
||||
// return a promise that resolves after 1 second
|
||||
// @ts-ignore TS2351 (new Cypress.Promise)
|
||||
return new Cypress.Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
// set waited to true
|
||||
waited = true
|
||||
|
||||
// resolve with 'foo' string
|
||||
resolve('foo')
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
cy.then(() => {
|
||||
// return a promise to cy.then() that
|
||||
// is awaited until it resolves
|
||||
// @ts-ignore TS7006
|
||||
return waitOneSecond().then((str) => {
|
||||
expect(str).to.eq('foo')
|
||||
expect(waited).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,59 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Viewport', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/viewport')
|
||||
})
|
||||
|
||||
it('cy.viewport() - set the viewport size and dimension', () => {
|
||||
// https://on.cypress.io/viewport
|
||||
|
||||
cy.get('#navbar').should('be.visible')
|
||||
cy.viewport(320, 480)
|
||||
|
||||
// the navbar should have collapse since our screen is smaller
|
||||
cy.get('#navbar').should('not.be.visible')
|
||||
cy.get('.navbar-toggle').should('be.visible').click()
|
||||
cy.get('.nav').find('a').should('be.visible')
|
||||
|
||||
// lets see what our app looks like on a super large screen
|
||||
cy.viewport(2999, 2999)
|
||||
|
||||
// cy.viewport() accepts a set of preset sizes
|
||||
// to easily set the screen to a device's width and height
|
||||
|
||||
// We added a cy.wait() between each viewport change so you can see
|
||||
// the change otherwise it is a little too fast to see :)
|
||||
|
||||
cy.viewport('macbook-15')
|
||||
cy.wait(200)
|
||||
cy.viewport('macbook-13')
|
||||
cy.wait(200)
|
||||
cy.viewport('macbook-11')
|
||||
cy.wait(200)
|
||||
cy.viewport('ipad-2')
|
||||
cy.wait(200)
|
||||
cy.viewport('ipad-mini')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-6+')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-6')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-5')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-4')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-3')
|
||||
cy.wait(200)
|
||||
|
||||
// cy.viewport() accepts an orientation for all presets
|
||||
// the default orientation is 'portrait'
|
||||
cy.viewport('ipad-2', 'portrait')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-4', 'landscape')
|
||||
cy.wait(200)
|
||||
|
||||
// The viewport will be reset back to the default dimensions
|
||||
// in between tests (the default can be set in cypress.json)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Waiting', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/waiting')
|
||||
})
|
||||
// BE CAREFUL of adding unnecessary wait times.
|
||||
// https://on.cypress.io/best-practices#Unnecessary-Waiting
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
it('cy.wait() - wait for a specific amount of time', () => {
|
||||
cy.get('.wait-input1').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
cy.get('.wait-input2').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
cy.get('.wait-input3').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
it('cy.wait() - wait for a specific route', () => {
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
|
||||
// wait for GET comments/1
|
||||
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Window', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/window')
|
||||
})
|
||||
|
||||
it('cy.window() - get the global window object', () => {
|
||||
// https://on.cypress.io/window
|
||||
cy.window().should('have.property', 'top')
|
||||
})
|
||||
|
||||
it('cy.document() - get the document object', () => {
|
||||
// https://on.cypress.io/document
|
||||
cy.document().should('have.property', 'charset').and('eq', 'UTF-8')
|
||||
})
|
||||
|
||||
it('cy.title() - get the title', () => {
|
||||
// https://on.cypress.io/title
|
||||
cy.title().should('include', 'Kitchen Sink')
|
||||
})
|
||||
})
|
||||
22
client/cypress/plugins/index.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
27
client/cypress/support/commands.js
Normal file
@@ -0,0 +1,27 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
import "@testing-library/cypress/add-commands";
|
||||
20
client/cypress/support/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
8
client/cypress/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": "../node_modules",
|
||||
"types": ["cypress"]
|
||||
},
|
||||
"include": ["**/*.*"]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.44.1 (20200629.0846)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="43pt" height="43pt"
|
||||
viewBox="0.00 0.00 43.20 43.20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(21.6 21.6)">
|
||||
<title>G</title>
|
||||
<polygon fill="#111111" stroke="transparent" points="-21.6,21.6 -21.6,-21.6 21.6,-21.6 21.6,21.6 -21.6,21.6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 613 B |
42958
client/package-lock.json
generated
@@ -1,90 +1,101 @@
|
||||
{
|
||||
"name": "bodyshop",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.1",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:5000",
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.3.17",
|
||||
"@craco/craco": "^6.1.2",
|
||||
"@fingerprintjs/fingerprintjs": "^3.1.2",
|
||||
"@lourenci/react-kanban": "^2.1.0",
|
||||
"@sentry/react": "^6.3.6",
|
||||
"@sentry/tracing": "^6.3.6",
|
||||
"@stripe/react-stripe-js": "^1.4.0",
|
||||
"@stripe/stripe-js": "^1.14.0",
|
||||
"@tanem/react-nprogress": "^3.0.65",
|
||||
"antd": "^4.15.5",
|
||||
"@apollo/client": "^3.5.6",
|
||||
"@asseinfo/react-kanban": "^2.2.0",
|
||||
"@craco/craco": "^6.4.3",
|
||||
"@fingerprintjs/fingerprintjs": "^3.3.1",
|
||||
"@sentry/react": "^6.16.1",
|
||||
"@sentry/tracing": "^6.16.1",
|
||||
"@splitsoftware/splitio-react": "^1.3.0",
|
||||
"@stripe/react-stripe-js": "^1.6.0",
|
||||
"@stripe/stripe-js": "^1.22.0",
|
||||
"@tanem/react-nprogress": "^3.0.82",
|
||||
"antd": "^4.17.3",
|
||||
"apollo-link-logger": "^2.0.0",
|
||||
"axios": "^0.21.1",
|
||||
"craco-less": "^1.17.1",
|
||||
"dinero.js": "^1.8.1",
|
||||
"dotenv": "^9.0.2",
|
||||
"axios": "^0.24.0",
|
||||
"craco-less": "^1.20.0",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"firebase": "^8.6.0",
|
||||
"graphql": "^15.5.0",
|
||||
"i18next": "^20.2.2",
|
||||
"i18next-browser-languagedetector": "^6.1.1",
|
||||
"jsoneditor": "^9.4.1",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^9.6.1",
|
||||
"graphql": "^16.1.0",
|
||||
"i18next": "^21.6.0",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"jsoneditor": "^9.5.7",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.9.17",
|
||||
"logrocket": "^1.2.0",
|
||||
"libphonenumber-js": "^1.9.44",
|
||||
"logrocket": "^2.1.2",
|
||||
"markerjs2": "^2.17.2",
|
||||
"moment-business-days": "^1.2.0",
|
||||
"phone": "^2.4.21",
|
||||
"phone": "^3.1.10",
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"query-string": "^7.0.0",
|
||||
"react": "^17.0.1",
|
||||
"react-big-calendar": "^0.33.2",
|
||||
"query-string": "^7.0.1",
|
||||
"rc-queue-anim": "^2.0.0",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^17.0.2",
|
||||
"react-big-calendar": "^0.38.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-drag-listview": "^0.1.8",
|
||||
"react-grid-gallery": "^0.5.5",
|
||||
"react-i18next": "^11.8.15",
|
||||
"react-icons": "^4.2.0",
|
||||
"react-number-format": "^4.5.5",
|
||||
"react-redux": "^7.2.4",
|
||||
"react-resizable": "^3.0.1",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-i18next": "^11.15.1",
|
||||
"react-icons": "^4.3.1",
|
||||
"react-number-format": "^4.8.0",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-resizable": "^3.0.4",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.0.7",
|
||||
"redux": "^4.1.0",
|
||||
"recharts": "^2.1.8",
|
||||
"redux": "^4.1.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.1.3",
|
||||
"redux-state-sync": "^3.1.2",
|
||||
"reselect": "^4.0.0",
|
||||
"sass": "^1.32.13",
|
||||
"styled-components": "^5.3.0",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
"web-vitals": "^1.1.2",
|
||||
"workbox-background-sync": "^6.1.5",
|
||||
"workbox-broadcast-update": "^6.1.5",
|
||||
"workbox-cacheable-response": "^6.1.5",
|
||||
"workbox-core": "^6.1.5",
|
||||
"workbox-expiration": "^6.1.5",
|
||||
"workbox-google-analytics": "^6.1.5",
|
||||
"workbox-navigation-preload": "^6.1.5",
|
||||
"workbox-precaching": "^6.1.5",
|
||||
"workbox-range-requests": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5",
|
||||
"workbox-streams": "^6.1.5"
|
||||
"reselect": "^4.1.5",
|
||||
"sass": "^1.45.0",
|
||||
"socket.io-client": "^4.4.0",
|
||||
"styled-components": "^5.3.3",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"web-vitals": "^2.1.2",
|
||||
"workbox-background-sync": "^6.4.2",
|
||||
"workbox-broadcast-update": "^6.4.2",
|
||||
"workbox-cacheable-response": "^6.4.2",
|
||||
"workbox-core": "^6.4.2",
|
||||
"workbox-expiration": "^6.4.2",
|
||||
"workbox-google-analytics": "^6.4.2",
|
||||
"workbox-navigation-preload": "^6.4.2",
|
||||
"workbox-precaching": "^6.4.2",
|
||||
"workbox-range-requests": "^6.4.2",
|
||||
"workbox-routing": "^6.4.2",
|
||||
"workbox-strategies": "^6.4.2",
|
||||
"workbox-streams": "^6.4.2"
|
||||
},
|
||||
"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` react-scripts build",
|
||||
"test": "craco test",
|
||||
"build:test": "env-cmd -f .env.test yarn run build",
|
||||
"build-deploy:test": "yarn 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",
|
||||
"test": "cypress open",
|
||||
"eject": "react-scripts eject",
|
||||
"madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular ."
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
"react-app/jest",
|
||||
"plugin:cypress/recommended"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
@@ -100,6 +111,10 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sentry/webpack-plugin": "^1.18.3",
|
||||
"@testing-library/cypress": "^8.0.2",
|
||||
"cypress": "^9.1.1",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.2"
|
||||
}
|
||||
|
||||
13087
client/patches/peerjs+1.3.2.patch
Normal file
@@ -1,53 +1,56 @@
|
||||
importScripts("https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js");
|
||||
importScripts(
|
||||
"https://www.gstatic.com/firebasejs/7.14.2/firebase-messaging.js"
|
||||
);
|
||||
// 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");
|
||||
|
||||
firebase.initializeApp({
|
||||
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",
|
||||
});
|
||||
// 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({
|
||||
// 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",
|
||||
// });
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
|
||||
// Retrieve firebase messaging
|
||||
const messaging = firebase.messaging();
|
||||
|
||||
self.addEventListener("fetch", (fetch) => {
|
||||
//required for installation as a PWA. Can ignore for now.
|
||||
//console.log("fetch", fetch);
|
||||
});
|
||||
messaging.onBackgroundMessage(function (payload) {
|
||||
// Customize notification here
|
||||
const channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.postMessage(payload);
|
||||
|
||||
messaging.setBackgroundMessageHandler(function (payload) {
|
||||
return self.registration.showNotification(
|
||||
"[SW]" + payload.notification.title,
|
||||
payload.notification
|
||||
);
|
||||
});
|
||||
|
||||
//Handles the notification getting clicked.
|
||||
self.addEventListener("notificationclick", function (event) {
|
||||
console.log("SW notificationclick", event);
|
||||
// event.notification.close();
|
||||
if (event.action === "archive") {
|
||||
// Archive action was clicked
|
||||
archiveEmail();
|
||||
} else {
|
||||
// Main body of notification was clicked
|
||||
clients.openWindow("/inbox");
|
||||
}
|
||||
//self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
});
|
||||
|
||||
@@ -8,13 +8,61 @@
|
||||
<meta name="description" content="ImEX Online" />
|
||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<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>
|
||||
|
||||
<!-- <script
|
||||
data-jsd-embedded
|
||||
data-key="51adb36e-ee16-46b1-a4c6-4b6d5fcd8530"
|
||||
data-base-url="https://jsd-widget.atlassian.com"
|
||||
src="https://jsd-widget.atlassian.com/assets/embed.js"
|
||||
></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/
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
import { ApolloProvider } from "@apollo/client";
|
||||
import { SplitFactory, SplitSdk } from "@splitsoftware/splitio-react";
|
||||
import { ConfigProvider } from "antd";
|
||||
import enLocale from "antd/es/locale/en_US";
|
||||
import LogRocket from "logrocket";
|
||||
import moment from "moment";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import App from "./App";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
moment.locale("en-US");
|
||||
|
||||
|
||||
//tracker.start();
|
||||
if (process.env.NODE_ENV === "production") LogRocket.init("gvfvfw/bodyshopapp");
|
||||
|
||||
export const factory = SplitSdk({
|
||||
core: {
|
||||
authorizationKey: process.env.REACT_APP_SPLIT_API,
|
||||
key: "anon",
|
||||
},
|
||||
});
|
||||
|
||||
export default function AppContainer() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<ConfigProvider
|
||||
@@ -28,7 +41,9 @@ export default function AppContainer() {
|
||||
}}
|
||||
>
|
||||
<GlobalLoadingBar />
|
||||
<App />
|
||||
<SplitFactory factory={factory}>
|
||||
<App />
|
||||
</SplitFactory>
|
||||
</ConfigProvider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import { Button, Result } from "antd";
|
||||
import React, { lazy, Suspense, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Route, Switch } 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";
|
||||
//Component Imports
|
||||
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
|
||||
import AboutPage from "../pages/about/about.page";
|
||||
import DisclaimerPage from "../pages/disclaimer/disclaimer.page";
|
||||
import TechPageContainer from "../pages/tech/tech.page.container";
|
||||
import { setOnline } from "../redux/application/application.actions";
|
||||
import { selectOnline } from "../redux/application/application.selectors";
|
||||
import { checkUserSession } from "../redux/user/user.actions";
|
||||
import { selectCurrentUser } from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../utils/private-route";
|
||||
import "./App.styles.scss";
|
||||
|
||||
const LandingPage = lazy(() => import("../pages/landing/landing.page"));
|
||||
import LandingPage from "../pages/landing/landing.page";
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
);
|
||||
@@ -27,25 +31,58 @@ const MobilePaymentContainer = lazy(() =>
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
online: selectOnline,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
checkUserSession: () => dispatch(checkUserSession()),
|
||||
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
|
||||
});
|
||||
|
||||
export function App({ checkUserSession, currentUser }) {
|
||||
export function App({ checkUserSession, currentUser, online, setOnline }) {
|
||||
useEffect(() => {
|
||||
if (!navigator.onLine) {
|
||||
setOnline(false);
|
||||
}
|
||||
|
||||
checkUserSession();
|
||||
}, [checkUserSession]);
|
||||
}, [checkUserSession, setOnline]);
|
||||
|
||||
//const b = Grid.useBreakpoint();
|
||||
// console.log("Breakpoints:", b);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
window.addEventListener("offline", function (e) {
|
||||
setOnline(false);
|
||||
});
|
||||
|
||||
window.addEventListener("online", function (e) {
|
||||
setOnline(true);
|
||||
});
|
||||
|
||||
if (currentUser.authorized === null) {
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")} />;
|
||||
}
|
||||
|
||||
if (!online)
|
||||
return (
|
||||
<Result
|
||||
status="warning"
|
||||
title={t("general.labels.nointernet")}
|
||||
subTitle={t("general.labels.nointernet_sub")}
|
||||
extra={
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
{t("general.actions.refresh")}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Suspense fallback={<LoadingSpinner message="ImEX Online" />}>
|
||||
@@ -62,7 +99,7 @@ export function App({ checkUserSession, currentUser }) {
|
||||
<Route exact path="/csi/:surveyId" component={CsiPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/about" component={AboutPage} />
|
||||
<Route exact path="/disclaimer" component={DisclaimerPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route
|
||||
@@ -85,6 +122,13 @@ export function App({ checkUserSession, currentUser }) {
|
||||
component={TechPageContainer}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
path="/edit"
|
||||
component={DocumentEditorContainer}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</Suspense>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -118,3 +118,27 @@
|
||||
.production-list-min-height {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
#noticeable-widget {
|
||||
iframe {
|
||||
z-index: 2 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.react-kanban-column {
|
||||
background-color: #ddd !important;
|
||||
}
|
||||
|
||||
.production-list-table {
|
||||
td.ant-table-column-sort {
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.ReactGridGallery_tile-icon-bar {
|
||||
div {
|
||||
svg {
|
||||
fill: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
client/src/assets/C2QB_composite_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
24
client/src/assets/C2QB_transparent_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
client/src/assets/ImEX Online Logo - Dark.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
client/src/assets/ImEX Online Logo.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
client/src/assets/banner-logo.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
client/src/assets/banner1.jpeg
Normal file
|
After Width: | Height: | Size: 272 KiB |
BIN
client/src/assets/banner2.jpeg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
client/src/assets/banner3.jpeg
Normal file
|
After Width: | Height: | Size: 177 KiB |
5
client/src/assets/icons/technology.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" ?><svg style="enable-background:new 0 0 128 128;" version="1.1" viewBox="0 0 128 128" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:8;stroke-miterlimit:10;}
|
||||
.st1{display:none;}
|
||||
.st2{display:inline;opacity:0.25;fill:#F45EFD;}
|
||||
</style><g id="_x31_2_3D_Printing"/><g id="_x31_1_VR_Gear"/><g id="_x31_0_Virtual_reality"/><g id="_x39__Augmented_reality"/><g id="_x38__Teleport"/><g id="_x37__Glassess"/><g id="_x36__Folding_phone"/><g id="_x35__Drone"/><g id="_x34__Retina_scan"/><g id="_x33__Smartwatch"/><g id="_x32__Bionic_Arm"/><g id="_x31__Chip"><g><path d="M108,40c-5.2,0-9.6,3.3-11.3,8H84V32h-8V20h-8v12h-8V20h-8v12h-8v16H24v-8.7c4.7-1.7,8-6.1,8-11.3c0-6.6-5.4-12-12-12 S8,21.4,8,28c0,5.2,3.3,9.6,8,11.3V56h28v8H16v16.7c-4.7,1.7-8,6.1-8,11.3c0,6.6,5.4,12,12,12s12-5.4,12-12c0-5.2-3.3-9.6-8-11.3 V72h20v16h8v12h8V88h8v12h8V88h8V72h8v16.7c-4.7,1.7-8,6.1-8,11.3c0,6.6,5.4,12,12,12s12-5.4,12-12c0-5.2-3.3-9.6-8-11.3V64H84v-8 h12.7c1.7,4.7,6.1,8,11.3,8c6.6,0,12-5.4,12-12S114.6,40,108,40z M20,32c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S22.2,32,20,32z M20,96c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S22.2,96,20,96z M76,80H52V40h24V80z M96,96c2.2,0,4,1.8,4,4s-1.8,4-4,4s-4-1.8-4-4 S93.8,96,96,96z M108,56c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S110.2,56,108,56z"/><rect height="8" width="8" x="56" y="64"/></g></g><g class="st1" id="Guide"><path class="st2" d="M120,8v112H8V8H120 M128,0H0v128h128V0L128,0z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
4
client/src/assets/qbo/C2QB_green_btn_med_default.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_green_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
4
client/src/assets/qbo/C2QB_green_btn_short_default.svg
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
5
client/src/assets/qbo/C2QB_green_btn_short_hover.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
4
client/src/assets/qbo/C2QB_green_btn_tall_default.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
5
client/src/assets/qbo/C2QB_green_btn_tall_hover.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_transparent_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@@ -1,25 +1,9 @@
|
||||
import Axios from "axios";
|
||||
import React from "react";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
export default function Test() {
|
||||
const handleQbSignIn = async () => {
|
||||
const result = await Axios.post("/qbo/authorize", { userId: "1234" });
|
||||
console.log("handleQbSignIn -> result", result.data);
|
||||
// window.open(result.data, "_blank", "toolbar=0,location=0,menubar=0");
|
||||
|
||||
var parameters = "location=1,width=800,height=650";
|
||||
parameters +=
|
||||
",left=" +
|
||||
(window.screen.width - 800) / 2 +
|
||||
",top=" +
|
||||
(window.screen.height - 650) / 2;
|
||||
|
||||
// Launch Popup
|
||||
window.open(result.data, "connectPopup", parameters);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={handleQbSignIn}>Sign Into Qb.</button>
|
||||
<QboAuthorizeComponent />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,25 @@ import PayableExportAll from "../payable-export-all-button/payable-export-all-bu
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import queryString from "query-string";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountingPayablesTableComponent);
|
||||
|
||||
export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedBills, setSelectedBills] = useState([]);
|
||||
const [transInProgress, setTransInProgress] = useState(false);
|
||||
@@ -109,6 +126,17 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
<Checkbox disabled checked={record.is_credit_memo} />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
@@ -121,6 +149,7 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
billId={record.id}
|
||||
disabled={transInProgress || !!record.exported}
|
||||
loadingCallback={setTransInProgress}
|
||||
setSelectedBills={setSelectedBills}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
@@ -154,6 +183,9 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedBills}
|
||||
/>
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -5,11 +5,29 @@ import { Link } from "react-router-dom";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||
import PaymentExportButton from "../payment-export-button/payment-export-button.component";
|
||||
import { PaymentsExportAllButton } from "../payments-export-all-button/payments-export-all-button.component";
|
||||
import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
export default function AccountingPayablesTableComponent({
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountingPayablesTableComponent);
|
||||
|
||||
export function AccountingPayablesTableComponent({
|
||||
bodyshop,
|
||||
loading,
|
||||
payments,
|
||||
}) {
|
||||
@@ -41,19 +59,12 @@ export default function AccountingPayablesTableComponent({
|
||||
title: t("payments.fields.date"),
|
||||
dataIndex: "date",
|
||||
key: "date",
|
||||
sorter: (a, b) => alphaSort(a.date, b.date),
|
||||
sorter: (a, b) => dateSort(a.date, b.date),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
||||
render: (text, record) => <DateFormatter>{record.date}</DateFormatter>,
|
||||
},
|
||||
{
|
||||
title: t("payments.fields.date"),
|
||||
dataIndex: "date",
|
||||
key: "date",
|
||||
sorter: (a, b) => alphaSort(a.date, b.date),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
||||
},
|
||||
|
||||
{
|
||||
title: t("jobs.fields.owner"),
|
||||
dataIndex: "owner",
|
||||
@@ -61,7 +72,7 @@ export default function AccountingPayablesTableComponent({
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "ownr_ln" && state.sortedInfo.order,
|
||||
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
return record.job.owner ? (
|
||||
<Link to={"/manage/owners/" + record.job.owner.id}>
|
||||
@@ -115,7 +126,17 @@ export default function AccountingPayablesTableComponent({
|
||||
<DateTimeFormatter>{record.exportedat}</DateTimeFormatter>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
@@ -127,6 +148,7 @@ export default function AccountingPayablesTableComponent({
|
||||
paymentId={record.id}
|
||||
disabled={transInProgress || !!record.exportedat}
|
||||
loadingCallback={setTransInProgress}
|
||||
setSelectedPayments={setSelectedPayments}
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -159,6 +181,9 @@ export default function AccountingPayablesTableComponent({
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedPayments}
|
||||
/>
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -8,7 +8,26 @@ import { alphaSort } from "../../utils/sorters";
|
||||
import JobExportButton from "../jobs-close-export-button/jobs-close-export-button.component";
|
||||
import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-button.component";
|
||||
|
||||
export default function AccountingReceivablesTableComponent({ loading, jobs }) {
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountingReceivablesTableComponent);
|
||||
|
||||
export function AccountingReceivablesTableComponent({
|
||||
bodyshop,
|
||||
loading,
|
||||
jobs,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedJobs, setSelectedJobs] = useState([]);
|
||||
const [transInProgress, setTransInProgress] = useState(false);
|
||||
@@ -91,13 +110,6 @@ export default function AccountingReceivablesTableComponent({ loading, jobs }) {
|
||||
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
return record.clm_no ? (
|
||||
<span>{record.clm_no}</span>
|
||||
) : (
|
||||
t("general.labels.unknown")
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.clm_total"),
|
||||
@@ -107,24 +119,31 @@ export default function AccountingReceivablesTableComponent({ loading, jobs }) {
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
return record.clm_total ? (
|
||||
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
|
||||
) : (
|
||||
t("general.labels.unknown")
|
||||
);
|
||||
return <CurrencyFormatter>{record.clm_total}</CurrencyFormatter>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("exportlogs.labels.attempts"),
|
||||
dataIndex: "attempts",
|
||||
key: "attempts",
|
||||
|
||||
render: (text, record) => {
|
||||
const success = record.exportlogs.filter((e) => e.successful).length;
|
||||
const attempts = record.exportlogs.length;
|
||||
return `${success}/${attempts}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
sorter: (a, b) => a.clm_total - b.clm_total,
|
||||
|
||||
render: (text, record) => (
|
||||
<Space wrap>
|
||||
<JobExportButton
|
||||
jobId={record.id}
|
||||
disabled={!!record.date_exported}
|
||||
setSelectedJobs={setSelectedJobs}
|
||||
/>
|
||||
<Link to={`/manage/jobs/${record.id}/close`}>
|
||||
<Button>{t("jobs.labels.viewallocations")}</Button>
|
||||
@@ -169,12 +188,17 @@ export default function AccountingReceivablesTableComponent({ loading, jobs }) {
|
||||
<Card
|
||||
extra={
|
||||
<Space wrap>
|
||||
<JobsExportAllButton
|
||||
jobIds={selectedJobs}
|
||||
disabled={transInProgress || selectedJobs.length === 0}
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedJobs}
|
||||
/>
|
||||
{!bodyshop.cdk_dealerid && !bodyshop.pbs_serialnumber && (
|
||||
<JobsExportAllButton
|
||||
jobIds={selectedJobs}
|
||||
disabled={transInProgress || selectedJobs.length === 0}
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedJobs}
|
||||
/>
|
||||
)}
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input.Search
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -9,6 +9,7 @@ export default function AuditTrailListContainer({ recordId }) {
|
||||
const { loading, error, data } = useQuery(QUERY_AUDIT_TRAIL, {
|
||||
variables: { id: recordId },
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
|
||||
logImEXEvent("audittrail_view", { recordId });
|
||||
|
||||
@@ -26,6 +26,8 @@ import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-bu
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -33,6 +35,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setPartsOrderContext: (context) =>
|
||||
dispatch(setModalContext({ context: context, modal: "partsOrder" })),
|
||||
insertAuditTrail: ({ jobid, operation }) =>
|
||||
dispatch(insertAuditTrail({ jobid, operation })),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
@@ -40,7 +44,10 @@ export default connect(
|
||||
mapDispatchToProps
|
||||
)(BillDetailEditcontainer);
|
||||
|
||||
export function BillDetailEditcontainer({ setPartsOrderContext }) {
|
||||
export function BillDetailEditcontainer({
|
||||
setPartsOrderContext,
|
||||
insertAuditTrail,
|
||||
}) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@@ -70,6 +77,8 @@ export function BillDetailEditcontainer({ setPartsOrderContext }) {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_BILL_BY_PK, {
|
||||
variables: { billid: search.billid },
|
||||
skip: !!!search.billid,
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
|
||||
const handleSave = () => {
|
||||
@@ -134,6 +143,12 @@ export function BillDetailEditcontainer({ setPartsOrderContext }) {
|
||||
});
|
||||
await Promise.all(updates);
|
||||
|
||||
insertAuditTrail({
|
||||
jobid: bill.jobid,
|
||||
billid: search.billid,
|
||||
operation: AuditTrailMapping.billupdated(bill.invoice_number),
|
||||
});
|
||||
|
||||
await refetch();
|
||||
form.setFieldsValue(transformData(data));
|
||||
form.resetFields();
|
||||
|
||||
@@ -11,13 +11,17 @@ import {
|
||||
QUERY_JOB_LBR_ADJUSTMENTS,
|
||||
UPDATE_JOB,
|
||||
} from "../../graphql/jobs.queries";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||
import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import confirmDialog from "../../utils/asyncConfirm";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import BillFormContainer from "../bill-form/bill-form.container";
|
||||
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -27,6 +31,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
toggleModalVisible: () => dispatch(toggleModalVisible("billEnter")),
|
||||
insertAuditTrail: ({ jobid, operation }) =>
|
||||
dispatch(insertAuditTrail({ jobid, operation })),
|
||||
});
|
||||
|
||||
function BillEnterModalContainer({
|
||||
@@ -34,6 +40,7 @@ function BillEnterModalContainer({
|
||||
toggleModalVisible,
|
||||
bodyshop,
|
||||
currentUser,
|
||||
insertAuditTrail,
|
||||
}) {
|
||||
const [form] = Form.useForm();
|
||||
const { t } = useTranslation();
|
||||
@@ -43,7 +50,31 @@ function BillEnterModalContainer({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const client = useApolloClient();
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
};
|
||||
}, [billEnterModal, bodyshop]);
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
let totals = CalculateBillTotal(values);
|
||||
if (totals.discrepancy.getAmount() !== 0) {
|
||||
if (!(await confirmDialog(t("bills.labels.savewithdiscrepancy")))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
const { upload, location, ...remainingValues } = values;
|
||||
|
||||
@@ -81,8 +112,9 @@ function BillEnterModalContainer({
|
||||
},
|
||||
],
|
||||
},
|
||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID"],
|
||||
});
|
||||
console.log("adjustmentsToInsert", adjustmentsToInsert);
|
||||
|
||||
const adjKeys = Object.keys(adjustmentsToInsert);
|
||||
if (adjKeys.length > 0) {
|
||||
//Query the adjustments, merge, and update them.
|
||||
@@ -115,7 +147,12 @@ function BillEnterModalContainer({
|
||||
message: JSON.stringify(jobUpdate.errors),
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
insertAuditTrail({
|
||||
jobid: values.jobid,
|
||||
operation: AuditTrailMapping.jobmodifylbradj(),
|
||||
});
|
||||
}
|
||||
|
||||
if (!!r1.errors) {
|
||||
@@ -171,9 +208,15 @@ function BillEnterModalContainer({
|
||||
});
|
||||
if (billEnterModal.actions.refetch) billEnterModal.actions.refetch();
|
||||
|
||||
insertAuditTrail({
|
||||
jobid: values.jobid,
|
||||
billid: billId,
|
||||
operation: AuditTrailMapping.billposted(remainingValues.invoice_number),
|
||||
});
|
||||
|
||||
if (enterAgain) {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ billlines: [] });
|
||||
form.setFieldsValue({ ...form.getFieldsValue(), billlines: [] });
|
||||
} else {
|
||||
toggleModalVisible();
|
||||
}
|
||||
@@ -191,23 +234,6 @@ function BillEnterModalContainer({
|
||||
if (enterAgain) form.submit();
|
||||
}, [enterAgain, form]);
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
};
|
||||
}, [billEnterModal, bodyshop]);
|
||||
|
||||
useEffect(() => {
|
||||
if (billEnterModal.visible) {
|
||||
form.setFieldsValue(formValues);
|
||||
@@ -225,7 +251,10 @@ function BillEnterModalContainer({
|
||||
keyboard="false"
|
||||
onOk={() => form.submit()}
|
||||
onCancel={handleCancel}
|
||||
afterClose={() => form.resetFields()}
|
||||
afterClose={() => {
|
||||
form.resetFields();
|
||||
setLoading(false);
|
||||
}}
|
||||
footer={
|
||||
<Space>
|
||||
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import Icon, { UploadOutlined } from "@ant-design/icons";
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { MdOpenInNew } from "react-icons/md";
|
||||
import {
|
||||
Alert,
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
@@ -13,6 +15,7 @@ import {
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
@@ -41,6 +44,7 @@ export function BillFormComponent({
|
||||
loadLines,
|
||||
billEdit,
|
||||
disableInvNumber,
|
||||
job,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const client = useApolloClient();
|
||||
@@ -50,6 +54,10 @@ export function BillFormComponent({
|
||||
setDiscount(opt.discount);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (job) form.validateFields(["is_credit_memo"]);
|
||||
}, [job, form]);
|
||||
|
||||
useEffect(() => {
|
||||
if (form.getFieldValue("vendorid") && vendorAutoCompleteOptions) {
|
||||
const vendorId = form.getFieldValue("vendorid");
|
||||
@@ -89,7 +97,7 @@ export function BillFormComponent({
|
||||
<JobSearchSelect
|
||||
disabled={billEdit || disabled}
|
||||
convertedOnly
|
||||
// notExported={false}
|
||||
notExported={false}
|
||||
onBlur={() => {
|
||||
if (form.getFieldValue("jobid") !== null) {
|
||||
loadLines({ variables: { id: form.getFieldValue("jobid") } });
|
||||
@@ -106,6 +114,18 @@ export function BillFormComponent({
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
value &&
|
||||
!getFieldValue(["isinhouse"]) &&
|
||||
value === bodyshop.inhousevendorid
|
||||
) {
|
||||
return Promise.reject(t("bills.validation.manualinhouse"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<VendorSearchSelect
|
||||
@@ -115,6 +135,30 @@ export function BillFormComponent({
|
||||
/>
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
{job &&
|
||||
job.ious &&
|
||||
job.ious.length > 0 &&
|
||||
job.ious.map((iou) => (
|
||||
<Alert
|
||||
key={iou.id}
|
||||
type="warning"
|
||||
message={
|
||||
<Space>
|
||||
{t("bills.labels.iouexists")}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
to={`/manage/jobs/${iou.id}?tab=repairdata`}
|
||||
>
|
||||
<Space>
|
||||
{iou.ro_number}
|
||||
<Icon component={MdOpenInNew} />
|
||||
</Space>
|
||||
</Link>
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<LayoutFormRow>
|
||||
<Form.Item
|
||||
label={t("bills.fields.invoice_number")}
|
||||
@@ -175,6 +219,22 @@ export function BillFormComponent({
|
||||
label={t("bills.fields.is_credit_memo")}
|
||||
name="is_credit_memo"
|
||||
valuePropName="checked"
|
||||
rules={[
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
(job.status === bodyshop.md_ro_statuses.default_invoiced ||
|
||||
job.status === bodyshop.md_ro_statuses.default_exported ||
|
||||
job.status === bodyshop.md_ro_statuses.default_void) &&
|
||||
(value === false || !value)
|
||||
) {
|
||||
return Promise.reject(t("bills.labels.onlycmforinvoiced"));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
@@ -304,6 +364,7 @@ export function BillFormComponent({
|
||||
responsibilityCenters={responsibilityCenters}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
<Form.Item
|
||||
name="upload"
|
||||
label="Upload"
|
||||
|
||||
@@ -18,7 +18,10 @@ export function BillFormContainer({
|
||||
disabled,
|
||||
disableInvNumber,
|
||||
}) {
|
||||
const { data: VendorAutoCompleteData } = useQuery(SEARCH_VENDOR_AUTOCOMPLETE);
|
||||
const { data: VendorAutoCompleteData } = useQuery(
|
||||
SEARCH_VENDOR_AUTOCOMPLETE,
|
||||
{ fetchPolicy: "network-only", nextFetchPolicy: "network-only" }
|
||||
);
|
||||
|
||||
const [loadLines, { data: lineData }] = useLazyQuery(
|
||||
GET_JOB_LINES_TO_ENTER_BILL
|
||||
@@ -34,6 +37,7 @@ export function BillFormContainer({
|
||||
}
|
||||
loadLines={loadLines}
|
||||
lineData={lineData ? lineData.joblines : []}
|
||||
job={lineData ? lineData.jobs_by_pk : null}
|
||||
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
||||
disableInvNumber={disableInvNumber}
|
||||
/>
|
||||
|
||||
@@ -7,13 +7,14 @@ import {
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Table
|
||||
} 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 CiecaSelect from "../../utils/Ciecaselect";
|
||||
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
|
||||
@@ -72,9 +73,13 @@ export function BillEnterModalLinesComponent({
|
||||
quantity: opt.part_qty || 1,
|
||||
actual_price: opt.cost,
|
||||
cost_center: opt.part_type
|
||||
? responsibilityCenters.defaults.costs[
|
||||
opt.part_type
|
||||
] || null
|
||||
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
|
||||
? opt.part_type
|
||||
: responsibilityCenters.defaults &&
|
||||
(responsibilityCenters.defaults.costs[
|
||||
opt.part_type
|
||||
] ||
|
||||
null)
|
||||
: null,
|
||||
};
|
||||
}
|
||||
@@ -154,18 +159,7 @@ export function BillEnterModalLinesComponent({
|
||||
setFieldsValue({
|
||||
billlines: getFieldsValue("billlines").billlines.map(
|
||||
(item, idx) => {
|
||||
console.log("Checking", index, idx);
|
||||
if (idx === index) {
|
||||
console.log(
|
||||
"Found and setting.",
|
||||
!!item.actual_cost
|
||||
? item.actual_cost
|
||||
: Math.round(
|
||||
(parseFloat(e.target.value) * (1 - discount) +
|
||||
Number.EPSILON) *
|
||||
100
|
||||
) / 100
|
||||
);
|
||||
return {
|
||||
...item,
|
||||
actual_cost: !!item.actual_cost
|
||||
@@ -233,6 +227,7 @@ export function BillEnterModalLinesComponent({
|
||||
key: `${field.index}cost_center`,
|
||||
name: [field.name, "cost_center"],
|
||||
label: t("billlines.fields.cost_center"),
|
||||
valuePropName: "value",
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
@@ -242,10 +237,12 @@ export function BillEnterModalLinesComponent({
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
<Select style={{ minWidth: "3rem" }} disabled={disabled}>
|
||||
{responsibilityCenters.costs.map((item) => (
|
||||
<Select.Option key={item.name}>{item.name}</Select.Option>
|
||||
))}
|
||||
<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>
|
||||
),
|
||||
},
|
||||
@@ -500,9 +497,9 @@ const EditableCell = ({
|
||||
labelCol={{ span: 0 }}
|
||||
{...(formItemProps && formItemProps(record))}
|
||||
>
|
||||
{(formInput && formInput(record, record.key)) || children}
|
||||
{(formInput && formInput(record, record.name)) || children}
|
||||
</Form.Item>
|
||||
{additional && additional(record, record.key)}
|
||||
{additional && additional(record, record.name)}
|
||||
</Space>
|
||||
</td>
|
||||
);
|
||||
@@ -514,7 +511,7 @@ const EditableCell = ({
|
||||
name={dataIndex}
|
||||
{...(formItemProps && formItemProps(record))}
|
||||
>
|
||||
{(formInput && formInput(record, record.key)) || children}
|
||||
{(formInput && formInput(record, record.name)) || children}
|
||||
</Form.Item>
|
||||
</td>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import Dinero from "dinero.js";
|
||||
|
||||
export const CalculateBillTotal = (invoice) => {
|
||||
const {
|
||||
total,
|
||||
billlines,
|
||||
federal_tax_rate,
|
||||
local_tax_rate,
|
||||
state_tax_rate,
|
||||
} = invoice;
|
||||
const { total, billlines, federal_tax_rate, local_tax_rate, state_tax_rate } =
|
||||
invoice;
|
||||
|
||||
//TODO Determine why this recalculates so many times.
|
||||
let subtotal = Dinero({ amount: 0 });
|
||||
@@ -20,8 +15,7 @@ export const CalculateBillTotal = (invoice) => {
|
||||
billlines.forEach((i) => {
|
||||
if (!!i) {
|
||||
const itemTotal = Dinero({
|
||||
amount:
|
||||
Math.round(((i.actual_cost || 0) * 100 + Number.EPSILON) * 100) / 100,
|
||||
amount: Math.round((i.actual_cost || 0) * 100),
|
||||
}).multiply(i.quantity || 1);
|
||||
|
||||
subtotal = subtotal.add(itemTotal);
|
||||
|
||||
@@ -12,7 +12,22 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
|
||||
disabled={disabled}
|
||||
ref={ref}
|
||||
showSearch
|
||||
optionFilterProp="line_desc"
|
||||
// optionFilterProp="line_desc"
|
||||
filterOption={(inputValue, option) => {
|
||||
return (
|
||||
(option.line_desc &&
|
||||
option.line_desc
|
||||
.toLowerCase()
|
||||
.includes(inputValue.toLowerCase())) ||
|
||||
(option.oem_partno &&
|
||||
option.oem_partno
|
||||
.toLowerCase()
|
||||
.includes(inputValue.toLowerCase())) ||
|
||||
(option.act_price &&
|
||||
option.act_price.toString().startsWith(inputValue.toString()))
|
||||
);
|
||||
}}
|
||||
notFoundContent={"Removed."}
|
||||
{...restProps}
|
||||
>
|
||||
<Select.Option key={null} value={"noline"} cost={0} line_desc={""}>
|
||||
@@ -21,16 +36,22 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
|
||||
{options
|
||||
? options.map((item) => (
|
||||
<Option
|
||||
disabled={item.removed}
|
||||
key={item.id}
|
||||
value={item.id}
|
||||
cost={item.act_price ? item.act_price : 0}
|
||||
part_type={item.part_type}
|
||||
line_desc={item.line_desc}
|
||||
part_qty={item.part_qty}
|
||||
oem_partno={item.oem_partno}
|
||||
act_price={item.act_price}
|
||||
style={{
|
||||
...(item.removed ? { textDecoration: "line-through" } : {}),
|
||||
}}
|
||||
>
|
||||
{`${item.line_desc}${
|
||||
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||
}`}
|
||||
}${item.act_price ? ` - $${item.act_price}` : ``}`}
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
|
||||
@@ -47,7 +47,9 @@ export function BillMarkForReexportButton({ bodyshop, authLevel, bill }) {
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({ message: t("bills.successes.save") });
|
||||
notification["success"]({
|
||||
message: t("bills.successes.reexport"),
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("bills.errors.saving", {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { EyeFilled, SyncOutlined } from "@ant-design/icons";
|
||||
import { EditFilled, SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Card, Checkbox, Input, Space, Table } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||
@@ -14,6 +15,7 @@ import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//jobRO: selectJobReadOnly,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
@@ -26,6 +28,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
});
|
||||
|
||||
export function BillsListTableComponent({
|
||||
bodyshop,
|
||||
job,
|
||||
billsQuery,
|
||||
handleOnRowClick,
|
||||
@@ -47,12 +50,14 @@ export function BillsListTableComponent({
|
||||
<Space wrap>
|
||||
{showView && (
|
||||
<Button onClick={() => handleOnRowClick(record)}>
|
||||
<EyeFilled />
|
||||
<EditFilled />
|
||||
</Button>
|
||||
)}
|
||||
<BillDeleteButton bill={record} />
|
||||
<Button
|
||||
disabled={record.is_credit_memo}
|
||||
disabled={
|
||||
record.is_credit_memo || record.vendorid === bodyshop.inhousevendorid
|
||||
}
|
||||
onClick={() =>
|
||||
setPartsOrderContext({
|
||||
actions: {},
|
||||
|
||||
@@ -12,7 +12,10 @@ export default function BillsVendorsList() {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_ALL_VENDORS);
|
||||
const { loading, error, data } = useQuery(QUERY_ALL_VENDORS, {
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { HomeFilled } from "@ant-design/icons";
|
||||
import { Breadcrumb } from "antd";
|
||||
import { Breadcrumb, Row, Col } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBreadcrumbs } from "../../redux/application/application.selectors";
|
||||
import GlobalSearch from "../global-search/global-search.component";
|
||||
import "./breadcrumbs.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -13,24 +14,29 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
export function BreadCrumbs({ breadcrumbs }) {
|
||||
return (
|
||||
<div className="breadcrumb-container imex-flex-row">
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item>
|
||||
<Link to={`/manage`}>
|
||||
<HomeFilled />
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
{breadcrumbs.map((item) =>
|
||||
item.link ? (
|
||||
<Breadcrumb.Item key={item.label}>
|
||||
<Link to={item.link}>{item.label} </Link>
|
||||
</Breadcrumb.Item>
|
||||
) : (
|
||||
<Breadcrumb.Item key={item.label}>{item.label}</Breadcrumb.Item>
|
||||
)
|
||||
)}
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<Row className="breadcrumb-container">
|
||||
<Col xs={24} sm={24} md={16}>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item>
|
||||
<Link to={`/manage`}>
|
||||
<HomeFilled />
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
{breadcrumbs.map((item) =>
|
||||
item.link ? (
|
||||
<Breadcrumb.Item key={item.label}>
|
||||
<Link to={item.link}>{item.label} </Link>
|
||||
</Breadcrumb.Item>
|
||||
) : (
|
||||
<Breadcrumb.Item key={item.label}>{item.label}</Breadcrumb.Item>
|
||||
)
|
||||
)}
|
||||
</Breadcrumb>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={8}>
|
||||
<GlobalSearch />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(BreadCrumbs);
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { MessageOutlined } from "@ant-design/icons";
|
||||
import { Badge, Card } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { toggleChatVisible } from "../../redux/messaging/messaging.actions";
|
||||
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
|
||||
import ChatPopupComponent from '../chat-popup/chat-popup.component'
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
chatVisible: selectChatVisible,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
toggleChatVisible: () => dispatch(toggleChatVisible()),
|
||||
});
|
||||
|
||||
export function ChatAffixComponent({
|
||||
chatVisible,
|
||||
toggleChatVisible,
|
||||
conversationList,
|
||||
unreadCount,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Badge count={unreadCount}>
|
||||
<Card size='small'>
|
||||
{chatVisible ? (
|
||||
<ChatPopupComponent conversationList={conversationList} />
|
||||
) : (
|
||||
<div
|
||||
onClick={() => toggleChatVisible()}
|
||||
style={{ cursor: "pointer" }}>
|
||||
<MessageOutlined />
|
||||
<strong>{t("messaging.labels.messaging")}</strong>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatAffixComponent);
|
||||
@@ -1,16 +1,17 @@
|
||||
import { useSubscription } from "@apollo/client";
|
||||
import React from "react";
|
||||
import { CONVERSATION_LIST_SUBSCRIPTION } from "../../graphql/conversations.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import ChatAffixComponent from "./chat-affix.component";
|
||||
import { Affix } from "antd";
|
||||
import "./chat-affix.styles.scss";
|
||||
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { getToken, onMessage } from "@firebase/messaging";
|
||||
import { Button, notification, Space } from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { messaging, requestForToken } from "../../firebase/firebase.utils";
|
||||
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import FcmHandler from "../../utils/fcm-handler";
|
||||
import ChatPopupComponent from "../chat-popup/chat-popup.component";
|
||||
import "./chat-affix.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -18,35 +19,88 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||
const { loading, error, data } = useSubscription(
|
||||
CONVERSATION_LIST_SUBSCRIPTION,
|
||||
{
|
||||
skip: !bodyshop || (bodyshop && !bodyshop.messagingservicesid),
|
||||
}
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
const client = useApolloClient();
|
||||
useEffect(() => {
|
||||
if (!bodyshop || !bodyshop.messagingservicesid) return;
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
async function SubscribeToTopic() {
|
||||
try {
|
||||
const r = await axios.post("/notifications/subscribe", {
|
||||
fcm_tokens: await getToken(messaging, {
|
||||
vapidKey: process.env.REACT_APP_FIREBASE_PUBLIC_VAPID_KEY,
|
||||
}),
|
||||
type: "messaging",
|
||||
imexshopid: bodyshop.imexshopid,
|
||||
});
|
||||
console.log("FCM Topic Subscription", r.data);
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"Error attempting to subscribe to messaging topic: ",
|
||||
error
|
||||
);
|
||||
notification.open({
|
||||
type: "warning",
|
||||
message: t("general.errors.fcm"),
|
||||
btn: (
|
||||
<Space>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
await requestForToken();
|
||||
|
||||
SubscribeToTopic();
|
||||
}}
|
||||
>
|
||||
{t("general.actions.tryagain")}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
const win = window.open(
|
||||
"https://help.imex.online/en/article/enabling-notifications-o978xi/",
|
||||
"_blank"
|
||||
);
|
||||
win.focus();
|
||||
}}
|
||||
>
|
||||
{t("general.labels.help")}
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SubscribeToTopic();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [bodyshop]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleMessage(payload) {
|
||||
FcmHandler({
|
||||
client,
|
||||
payload: (payload && payload.data && payload.data.data) || payload.data,
|
||||
});
|
||||
}
|
||||
let stopMessageListenr, channel;
|
||||
try {
|
||||
stopMessageListenr = onMessage(messaging, handleMessage);
|
||||
channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.addEventListener("message", handleMessage);
|
||||
} catch (error) {
|
||||
console.log("Unable to set event listeners.");
|
||||
}
|
||||
return () => {
|
||||
stopMessageListenr && stopMessageListenr();
|
||||
channel && channel.removeEventListener("message", handleMessage);
|
||||
};
|
||||
}, [client]);
|
||||
|
||||
if (!bodyshop || !bodyshop.messagingservicesid) return <></>;
|
||||
|
||||
return (
|
||||
<Affix className={`chat-affix ${chatVisible ? "chat-affix-open" : ""}`}>
|
||||
<div>
|
||||
{bodyshop && bodyshop.messagingservicesid ? (
|
||||
<ChatAffixComponent
|
||||
conversationList={(data && data.conversations) || []}
|
||||
unreadCount={
|
||||
(data &&
|
||||
data.conversations.reduce((acc, val) => {
|
||||
return (acc = acc + val.messages_aggregate.aggregate.count);
|
||||
}, 0)) ||
|
||||
0
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</Affix>
|
||||
<div className={`chat-affix ${chatVisible ? "chat-affix-open" : ""}`}>
|
||||
{bodyshop && bodyshop.messagingservicesid ? <ChatPopupComponent /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(ChatAffixContainer);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
.chat-affix {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
left: 2vw;
|
||||
bottom: 2vh;
|
||||
z-index: 999;
|
||||
-webkit-box-shadow: 0px 0px 2px 0px rgba(69, 69, 69, 1);
|
||||
-moz-box-shadow: 0px 0px 2px 0px rgba(69, 69, 69, 1);
|
||||
box-shadow: 0px 0px 2px 0px rgba(69, 69, 69, 1);
|
||||
}
|
||||
|
||||
.chat-affix-open {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { Button } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries";
|
||||
|
||||
export default function ChatArchiveButton({ conversation }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const [updateConversation] = useMutation(TOGGLE_CONVERSATION_ARCHIVE);
|
||||
const handleToggleArchive = async () => {
|
||||
setLoading(true);
|
||||
|
||||
await updateConversation({
|
||||
variables: { id: conversation.id, archived: !conversation.archived },
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button onClick={handleToggleArchive} loading={loading} type="primary">
|
||||
{conversation.archived
|
||||
? t("messaging.labels.unarchive")
|
||||
: t("messaging.labels.archive")}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Badge, List, Tag, Tooltip } from "antd";
|
||||
import { AlertFilled } from "@ant-design/icons";
|
||||
import { Badge, List, Tag } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
||||
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||
import "./chat-conversation-list.styles.scss";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
@@ -23,8 +22,6 @@ export function ChatConversationListComponent({
|
||||
selectedConversation,
|
||||
setSelectedConversation,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="chat-list-container">
|
||||
<List
|
||||
@@ -32,6 +29,7 @@ export function ChatConversationListComponent({
|
||||
dataSource={conversationList}
|
||||
renderItem={(item) => (
|
||||
<List.Item
|
||||
key={item.id}
|
||||
onClick={() => setSelectedConversation(item.id)}
|
||||
className={`chat-list-item ${
|
||||
item.id === selectedConversation
|
||||
@@ -42,31 +40,26 @@ export function ChatConversationListComponent({
|
||||
{item.job_conversations.length > 0 ? (
|
||||
<div className="chat-name">
|
||||
{item.job_conversations.map((j, idx) => (
|
||||
<div key={idx} style={{ display: "flex" }}>
|
||||
{j.job.owner && !j.job.owner.allow_text_message && (
|
||||
<Tooltip title={t("messaging.labels.noallowtxt")}>
|
||||
<AlertFilled
|
||||
className="production-alert"
|
||||
style={{ marginRight: ".3rem", alignItems: "center" }}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<div>{`${j.job.ownr_fn || ""} ${j.job.ownr_ln || ""} ${
|
||||
j.job.ownr_co_nm || ""
|
||||
} `}</div>
|
||||
</div>
|
||||
<div key={idx}>{`${j.job.ownr_fn || ""} ${
|
||||
j.job.ownr_ln || ""
|
||||
} ${j.job.ownr_co_nm || ""} `}</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||
)}
|
||||
{item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx} className="ro-number-tag">
|
||||
{j.job.ro_number}
|
||||
</Tag>
|
||||
))
|
||||
: null}
|
||||
<div sryle={{ display: "inline-block" }}>
|
||||
<div>
|
||||
{item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx} className="ro-number-tag">
|
||||
{j.job.ro_number}
|
||||
</Tag>
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
||||
</div>
|
||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||
</List.Item>
|
||||
)}
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
import { Space } from "antd";
|
||||
import React from "react";
|
||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
|
||||
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
||||
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
||||
|
||||
export default function ChatConversationTitle({ conversation }) {
|
||||
return (
|
||||
<div>
|
||||
<div className="imex-flex-row">
|
||||
<ChatConversationTitleTags
|
||||
jobConversations={
|
||||
(conversation && conversation.job_conversations) || []
|
||||
}
|
||||
/>
|
||||
<ChatTagRoContainer conversation={conversation || []} />
|
||||
</div>
|
||||
<div className="imex-flex-row">
|
||||
<PhoneNumberFormatter>
|
||||
{conversation && conversation.phone_num}
|
||||
</PhoneNumberFormatter>
|
||||
</div>
|
||||
</div>
|
||||
<Space wrap>
|
||||
<PhoneNumberFormatter>
|
||||
{conversation && conversation.phone_num}
|
||||
</PhoneNumberFormatter>
|
||||
<ChatConversationTitleTags
|
||||
jobConversations={
|
||||
(conversation && conversation.job_conversations) || []
|
||||
}
|
||||
/>
|
||||
<ChatTagRoContainer conversation={conversation || []} />
|
||||
<ChatArchiveButton conversation={conversation} />
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import "./chat-conversation.styles.scss";
|
||||
export default function ChatConversationComponent({
|
||||
subState,
|
||||
conversation,
|
||||
messages,
|
||||
handleMarkConversationAsRead,
|
||||
}) {
|
||||
const [loading, error] = subState;
|
||||
@@ -16,8 +17,6 @@ export default function ChatConversationComponent({
|
||||
if (loading) return <LoadingSkeleton />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
const messages = (conversation && conversation.messages) || [];
|
||||
|
||||
return (
|
||||
<div
|
||||
className="chat-conversation"
|
||||
|
||||