@redacto.io/dpdpa-report-sdk-js 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dpdpa-report.d.mts +44 -5
- package/dist/dpdpa-report.d.ts +44 -5
- package/dist/dpdpa-report.global.js +287 -2
- package/dist/dpdpa-report.global.js.map +1 -1
- package/dist/dpdpa-report.js +532 -141
- package/dist/dpdpa-report.mjs +532 -141
- package/package.json +1 -1
package/dist/dpdpa-report.js
CHANGED
|
@@ -35,7 +35,7 @@ var PATHS = {
|
|
|
35
35
|
status: "/webhook/dpdpa/status"
|
|
36
36
|
};
|
|
37
37
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
38
|
-
var DEFAULT_POLL_TIMEOUT_MS =
|
|
38
|
+
var DEFAULT_POLL_TIMEOUT_MS = 9e4;
|
|
39
39
|
var MAX_CONSECUTIVE_ERRORS = 3;
|
|
40
40
|
var REQUEST_TIMEOUT_MS = 15e3;
|
|
41
41
|
var STORAGE_KEY = "redacto_dpdpa_lead";
|
|
@@ -737,6 +737,291 @@ function buildCss(brand) {
|
|
|
737
737
|
from { transform: rotate(0deg); }
|
|
738
738
|
to { transform: rotate(360deg); }
|
|
739
739
|
}
|
|
740
|
+
|
|
741
|
+
/* Quick insights view */
|
|
742
|
+
|
|
743
|
+
.dpdpa-card-wide {
|
|
744
|
+
min-height: 0;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.dpdpa-qi {
|
|
748
|
+
display: flex;
|
|
749
|
+
flex-direction: column;
|
|
750
|
+
gap: 18px;
|
|
751
|
+
flex: 1;
|
|
752
|
+
animation: dpdpa-fade-in 0.35s ease-out both;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.dpdpa-qi-header {
|
|
756
|
+
display: flex;
|
|
757
|
+
flex-direction: column;
|
|
758
|
+
gap: 12px;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
.dpdpa-qi-title {
|
|
762
|
+
margin: 0;
|
|
763
|
+
font-size: 18px;
|
|
764
|
+
font-weight: 700;
|
|
765
|
+
color: ${brand.text};
|
|
766
|
+
line-height: 1.3;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.dpdpa-qi-subtitle {
|
|
770
|
+
margin: 0;
|
|
771
|
+
font-size: 14px;
|
|
772
|
+
color: ${brand.text};
|
|
773
|
+
opacity: 0.85;
|
|
774
|
+
line-height: 1.55;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.dpdpa-applicability {
|
|
778
|
+
display: flex;
|
|
779
|
+
flex-direction: column;
|
|
780
|
+
gap: 4px;
|
|
781
|
+
padding: 12px 14px;
|
|
782
|
+
border-radius: ${brand.borderRadius};
|
|
783
|
+
border: 1px solid ${brand.border};
|
|
784
|
+
background: #ffffff;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
.dpdpa-applicability-level {
|
|
788
|
+
font-size: 11px;
|
|
789
|
+
font-weight: 700;
|
|
790
|
+
letter-spacing: 0.6px;
|
|
791
|
+
text-transform: uppercase;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.dpdpa-applicability-reason {
|
|
795
|
+
font-size: 13px;
|
|
796
|
+
color: ${brand.text};
|
|
797
|
+
opacity: 0.85;
|
|
798
|
+
line-height: 1.45;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.dpdpa-badge-strong { border-color: ${brand.primary}66; background: ${brand.primary}10; }
|
|
802
|
+
.dpdpa-badge-strong .dpdpa-applicability-level { color: ${brand.primary}; }
|
|
803
|
+
|
|
804
|
+
.dpdpa-badge-warn { border-color: #f59e0b66; background: #f59e0b14; }
|
|
805
|
+
.dpdpa-badge-warn .dpdpa-applicability-level { color: #b45309; }
|
|
806
|
+
|
|
807
|
+
.dpdpa-badge-soft { border-color: #94a3b866; background: #94a3b814; }
|
|
808
|
+
.dpdpa-badge-soft .dpdpa-applicability-level { color: #475569; }
|
|
809
|
+
|
|
810
|
+
.dpdpa-badge-mute { border-color: ${brand.border}; background: ${brand.background}; }
|
|
811
|
+
.dpdpa-badge-mute .dpdpa-applicability-level { color: ${brand.text}; opacity: 0.7; }
|
|
812
|
+
|
|
813
|
+
.dpdpa-badge-neutral { border-color: ${brand.border}; background: ${brand.background}; }
|
|
814
|
+
.dpdpa-badge-neutral .dpdpa-applicability-level { color: ${brand.text}; }
|
|
815
|
+
|
|
816
|
+
.dpdpa-confidence-row {
|
|
817
|
+
display: flex;
|
|
818
|
+
align-items: center;
|
|
819
|
+
gap: 8px;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.dpdpa-meta-label {
|
|
823
|
+
font-size: 11px;
|
|
824
|
+
font-weight: 700;
|
|
825
|
+
letter-spacing: 0.5px;
|
|
826
|
+
text-transform: uppercase;
|
|
827
|
+
color: ${brand.text};
|
|
828
|
+
opacity: 0.6;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.dpdpa-meta-value {
|
|
832
|
+
font-size: 13px;
|
|
833
|
+
color: ${brand.text};
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.dpdpa-chip {
|
|
837
|
+
display: inline-flex;
|
|
838
|
+
align-items: center;
|
|
839
|
+
padding: 3px 8px;
|
|
840
|
+
font-size: 11px;
|
|
841
|
+
font-weight: 600;
|
|
842
|
+
color: ${brand.text};
|
|
843
|
+
background: ${brand.background};
|
|
844
|
+
border: 1px solid ${brand.border};
|
|
845
|
+
border-radius: 999px;
|
|
846
|
+
white-space: nowrap;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.dpdpa-chip-ref {
|
|
850
|
+
background: ${brand.primary}12;
|
|
851
|
+
border-color: ${brand.primary}33;
|
|
852
|
+
color: ${brand.primary};
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
.dpdpa-chip-data {
|
|
856
|
+
background: #ecfeff;
|
|
857
|
+
border-color: #67e8f933;
|
|
858
|
+
color: #0e7490;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.dpdpa-chip-touchpoint {
|
|
862
|
+
background: #f5f3ff;
|
|
863
|
+
border-color: #c4b5fd33;
|
|
864
|
+
color: #5b21b6;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
.dpdpa-chip-row {
|
|
868
|
+
display: flex;
|
|
869
|
+
flex-wrap: wrap;
|
|
870
|
+
gap: 6px;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
.dpdpa-callout {
|
|
874
|
+
padding: 12px 14px;
|
|
875
|
+
background: ${brand.primary}08;
|
|
876
|
+
border: 1px solid ${brand.primary}22;
|
|
877
|
+
border-radius: ${brand.borderRadius};
|
|
878
|
+
display: flex;
|
|
879
|
+
flex-direction: column;
|
|
880
|
+
gap: 4px;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.dpdpa-callout-title {
|
|
884
|
+
font-size: 12px;
|
|
885
|
+
font-weight: 700;
|
|
886
|
+
letter-spacing: 0.3px;
|
|
887
|
+
text-transform: uppercase;
|
|
888
|
+
color: ${brand.primary};
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.dpdpa-callout-message {
|
|
892
|
+
margin: 0;
|
|
893
|
+
font-size: 13px;
|
|
894
|
+
color: ${brand.text};
|
|
895
|
+
line-height: 1.5;
|
|
896
|
+
opacity: 0.85;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.dpdpa-section {
|
|
900
|
+
display: flex;
|
|
901
|
+
flex-direction: column;
|
|
902
|
+
gap: 10px;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.dpdpa-section-title {
|
|
906
|
+
margin: 0;
|
|
907
|
+
font-size: 13px;
|
|
908
|
+
font-weight: 700;
|
|
909
|
+
color: ${brand.text};
|
|
910
|
+
letter-spacing: 0.2px;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.dpdpa-area-list {
|
|
914
|
+
display: flex;
|
|
915
|
+
flex-direction: column;
|
|
916
|
+
gap: 10px;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.dpdpa-area-card {
|
|
920
|
+
padding: 12px 14px;
|
|
921
|
+
background: #ffffff;
|
|
922
|
+
border: 1px solid ${brand.border};
|
|
923
|
+
border-radius: ${brand.borderRadius};
|
|
924
|
+
display: flex;
|
|
925
|
+
flex-direction: column;
|
|
926
|
+
gap: 8px;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.dpdpa-area-heading {
|
|
930
|
+
display: flex;
|
|
931
|
+
align-items: center;
|
|
932
|
+
justify-content: space-between;
|
|
933
|
+
gap: 10px;
|
|
934
|
+
flex-wrap: wrap;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
.dpdpa-area-name {
|
|
938
|
+
margin: 0;
|
|
939
|
+
font-size: 14px;
|
|
940
|
+
font-weight: 700;
|
|
941
|
+
color: ${brand.text};
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
.dpdpa-product-hint {
|
|
945
|
+
font-size: 11px;
|
|
946
|
+
font-weight: 600;
|
|
947
|
+
color: ${brand.primary};
|
|
948
|
+
background: ${brand.primary}12;
|
|
949
|
+
padding: 3px 8px;
|
|
950
|
+
border-radius: 999px;
|
|
951
|
+
white-space: nowrap;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.dpdpa-area-why {
|
|
955
|
+
margin: 0;
|
|
956
|
+
font-size: 13px;
|
|
957
|
+
color: ${brand.text};
|
|
958
|
+
opacity: 0.8;
|
|
959
|
+
line-height: 1.5;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
.dpdpa-cu-profile {
|
|
963
|
+
margin: 0;
|
|
964
|
+
font-size: 13px;
|
|
965
|
+
color: ${brand.text};
|
|
966
|
+
opacity: 0.85;
|
|
967
|
+
line-height: 1.5;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.dpdpa-cu-meta {
|
|
971
|
+
display: flex;
|
|
972
|
+
align-items: center;
|
|
973
|
+
gap: 8px;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.dpdpa-email-banner {
|
|
977
|
+
display: flex;
|
|
978
|
+
align-items: flex-start;
|
|
979
|
+
gap: 12px;
|
|
980
|
+
padding: 14px 16px;
|
|
981
|
+
background: linear-gradient(135deg, ${brand.primary}10, ${brand.accent}10);
|
|
982
|
+
border: 1px solid ${brand.primary}33;
|
|
983
|
+
border-radius: ${brand.borderRadius};
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.dpdpa-email-icon {
|
|
987
|
+
flex: none;
|
|
988
|
+
display: inline-flex;
|
|
989
|
+
align-items: center;
|
|
990
|
+
justify-content: center;
|
|
991
|
+
width: 32px;
|
|
992
|
+
height: 32px;
|
|
993
|
+
border-radius: 50%;
|
|
994
|
+
background: ${brand.primary};
|
|
995
|
+
color: ${brand.primaryText};
|
|
996
|
+
margin-top: 2px;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.dpdpa-email-text {
|
|
1000
|
+
display: flex;
|
|
1001
|
+
flex-direction: column;
|
|
1002
|
+
gap: 2px;
|
|
1003
|
+
min-width: 0;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.dpdpa-email-headline {
|
|
1007
|
+
font-size: 14px;
|
|
1008
|
+
font-weight: 700;
|
|
1009
|
+
color: ${brand.text};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.dpdpa-email-sub {
|
|
1013
|
+
margin: 0;
|
|
1014
|
+
font-size: 13px;
|
|
1015
|
+
color: ${brand.text};
|
|
1016
|
+
opacity: 0.8;
|
|
1017
|
+
line-height: 1.5;
|
|
1018
|
+
word-break: break-word;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
@keyframes dpdpa-fade-in {
|
|
1022
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
1023
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1024
|
+
}
|
|
740
1025
|
`;
|
|
741
1026
|
}
|
|
742
1027
|
function injectFormStyles(root, brand) {
|
|
@@ -974,7 +1259,7 @@ function renderIdle(brand, fields, errors, generalErrorText, handlers) {
|
|
|
974
1259
|
el(
|
|
975
1260
|
"p",
|
|
976
1261
|
{ className: "dpdpa-subheading" },
|
|
977
|
-
"We'll
|
|
1262
|
+
"We'll preview your DPDPA exposure here and email you the full report."
|
|
978
1263
|
),
|
|
979
1264
|
generalError,
|
|
980
1265
|
nameRow.row,
|
|
@@ -1034,42 +1319,12 @@ function animatedDots() {
|
|
|
1034
1319
|
el("span")
|
|
1035
1320
|
);
|
|
1036
1321
|
}
|
|
1037
|
-
function stepCheck(brand) {
|
|
1038
|
-
return el(
|
|
1039
|
-
"div",
|
|
1040
|
-
{
|
|
1041
|
-
className: "dpdpa-step-icon dpdpa-step-icon-done",
|
|
1042
|
-
style: { backgroundColor: brand.successColor }
|
|
1043
|
-
},
|
|
1044
|
-
svg(
|
|
1045
|
-
"svg",
|
|
1046
|
-
{ width: 12, height: 12, viewBox: "0 0 24 24", fill: "none" },
|
|
1047
|
-
svg("path", {
|
|
1048
|
-
d: "M5 12l5 5L20 7",
|
|
1049
|
-
stroke: "#ffffff",
|
|
1050
|
-
"stroke-width": 3,
|
|
1051
|
-
"stroke-linecap": "round",
|
|
1052
|
-
"stroke-linejoin": "round"
|
|
1053
|
-
})
|
|
1054
|
-
)
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
1322
|
function stepPulse(brand) {
|
|
1058
1323
|
return el("div", {
|
|
1059
1324
|
className: "dpdpa-step-icon dpdpa-step-icon-active",
|
|
1060
1325
|
style: { backgroundColor: brand.primary }
|
|
1061
1326
|
});
|
|
1062
1327
|
}
|
|
1063
|
-
var STEP_ORDER = {
|
|
1064
|
-
pending: 0,
|
|
1065
|
-
researching: 0,
|
|
1066
|
-
analysis_complete: 2
|
|
1067
|
-
};
|
|
1068
|
-
var STEPS = [
|
|
1069
|
-
{ label: (company) => `Researching ${company}` },
|
|
1070
|
-
{ label: () => "Analysing DPDPA compliance" },
|
|
1071
|
-
{ label: () => "Generating your report" }
|
|
1072
|
-
];
|
|
1073
1328
|
function renderPolling(brand, opts) {
|
|
1074
1329
|
const pct = Math.min(100, Math.round(opts.elapsedMs / opts.pollTimeoutMs * 100));
|
|
1075
1330
|
const progressFill = el("div", {
|
|
@@ -1081,92 +1336,191 @@ function renderPolling(brand, opts) {
|
|
|
1081
1336
|
{
|
|
1082
1337
|
className: "dpdpa-progress",
|
|
1083
1338
|
role: "progressbar",
|
|
1084
|
-
"aria-label": "
|
|
1339
|
+
"aria-label": "Quick insights progress",
|
|
1085
1340
|
"aria-valuemin": "0",
|
|
1086
1341
|
"aria-valuemax": "100",
|
|
1087
1342
|
"aria-valuenow": String(pct)
|
|
1088
1343
|
},
|
|
1089
1344
|
progressFill
|
|
1090
1345
|
);
|
|
1091
|
-
const
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
"
|
|
1098
|
-
{
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
el(
|
|
1103
|
-
"span",
|
|
1104
|
-
{
|
|
1105
|
-
className: isActive ? "dpdpa-step-label dpdpa-shimmer" : "dpdpa-step-label"
|
|
1106
|
-
},
|
|
1107
|
-
step.label(opts.companyName)
|
|
1108
|
-
)
|
|
1109
|
-
);
|
|
1110
|
-
if (isActive) row.appendChild(animatedDots());
|
|
1111
|
-
stepsList.appendChild(row);
|
|
1112
|
-
});
|
|
1346
|
+
const stepRow = el(
|
|
1347
|
+
"div",
|
|
1348
|
+
{ className: "dpdpa-step dpdpa-step-active" },
|
|
1349
|
+
stepPulse(brand),
|
|
1350
|
+
el(
|
|
1351
|
+
"span",
|
|
1352
|
+
{ className: "dpdpa-step-label dpdpa-shimmer" },
|
|
1353
|
+
`Scanning ${opts.companyName}'s privacy footprint`
|
|
1354
|
+
),
|
|
1355
|
+
animatedDots()
|
|
1356
|
+
);
|
|
1113
1357
|
const body = el(
|
|
1114
1358
|
"div",
|
|
1115
1359
|
{ className: "dpdpa-polling" },
|
|
1116
|
-
|
|
1360
|
+
el("div", { className: "dpdpa-steps" }, stepRow),
|
|
1117
1361
|
el(
|
|
1118
1362
|
"p",
|
|
1119
1363
|
{ className: "dpdpa-polling-sub" },
|
|
1120
|
-
"
|
|
1364
|
+
"Generating your preliminary DPDPA scan. This usually takes 10\u201320 seconds."
|
|
1121
1365
|
),
|
|
1122
1366
|
progressBar
|
|
1123
1367
|
);
|
|
1124
1368
|
return el("div", { className: "dpdpa-card" }, header(brand), body, footer(brand));
|
|
1125
1369
|
}
|
|
1126
|
-
function
|
|
1370
|
+
function chip(text, variant) {
|
|
1371
|
+
return el(
|
|
1372
|
+
"span",
|
|
1373
|
+
{ className: `dpdpa-chip${variant ? ` dpdpa-chip-${variant}` : ""}` },
|
|
1374
|
+
text
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
function applicabilityBadge(level, reason) {
|
|
1378
|
+
const upper = (level || "").toUpperCase();
|
|
1379
|
+
let cls = "dpdpa-badge-neutral";
|
|
1380
|
+
if (upper.includes("VERY_LIKELY")) cls = "dpdpa-badge-strong";
|
|
1381
|
+
else if (upper === "LIKELY") cls = "dpdpa-badge-warn";
|
|
1382
|
+
else if (upper === "POSSIBLY") cls = "dpdpa-badge-soft";
|
|
1383
|
+
else if (upper === "UNLIKELY") cls = "dpdpa-badge-mute";
|
|
1127
1384
|
return el(
|
|
1128
1385
|
"div",
|
|
1129
|
-
{
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
},
|
|
1133
|
-
svg(
|
|
1134
|
-
"svg",
|
|
1135
|
-
{
|
|
1136
|
-
width: 28,
|
|
1137
|
-
height: 28,
|
|
1138
|
-
viewBox: "0 0 24 24",
|
|
1139
|
-
fill: "none"
|
|
1140
|
-
},
|
|
1141
|
-
svg("path", {
|
|
1142
|
-
d: "M5 12l5 5L20 7",
|
|
1143
|
-
stroke: "#ffffff",
|
|
1144
|
-
"stroke-width": 3,
|
|
1145
|
-
"stroke-linecap": "round",
|
|
1146
|
-
"stroke-linejoin": "round"
|
|
1147
|
-
})
|
|
1148
|
-
)
|
|
1386
|
+
{ className: `dpdpa-applicability ${cls}` },
|
|
1387
|
+
el("span", { className: "dpdpa-applicability-level" }, level.replace(/_/g, " ")),
|
|
1388
|
+
el("span", { className: "dpdpa-applicability-reason" }, reason)
|
|
1149
1389
|
);
|
|
1150
1390
|
}
|
|
1151
|
-
function
|
|
1152
|
-
|
|
1153
|
-
if (!s) return false;
|
|
1154
|
-
if (/^https?:\/\//i.test(s)) return true;
|
|
1155
|
-
if (/^\/[^/]/.test(s) || s.startsWith("./") || s.startsWith("../"))
|
|
1156
|
-
return true;
|
|
1157
|
-
return false;
|
|
1391
|
+
function sectionTitle(text) {
|
|
1392
|
+
return el("h4", { className: "dpdpa-section-title" }, text);
|
|
1158
1393
|
}
|
|
1159
|
-
function
|
|
1160
|
-
const
|
|
1161
|
-
|
|
1162
|
-
"
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1394
|
+
function areaCard(area) {
|
|
1395
|
+
const refs = el(
|
|
1396
|
+
"div",
|
|
1397
|
+
{ className: "dpdpa-chip-row" },
|
|
1398
|
+
...area.dpdpa_references.map((r) => chip(r, "ref"))
|
|
1399
|
+
);
|
|
1400
|
+
const hint = area.redacto_product_hint ? el(
|
|
1401
|
+
"span",
|
|
1402
|
+
{ className: "dpdpa-product-hint" },
|
|
1403
|
+
`Redacto ${area.redacto_product_hint}`
|
|
1404
|
+
) : null;
|
|
1405
|
+
const heading = el(
|
|
1406
|
+
"div",
|
|
1407
|
+
{ className: "dpdpa-area-heading" },
|
|
1408
|
+
el("h5", { className: "dpdpa-area-name" }, area.area),
|
|
1409
|
+
...hint ? [hint] : []
|
|
1410
|
+
);
|
|
1411
|
+
return el(
|
|
1412
|
+
"div",
|
|
1413
|
+
{ className: "dpdpa-area-card" },
|
|
1414
|
+
heading,
|
|
1415
|
+
refs,
|
|
1416
|
+
el("p", { className: "dpdpa-area-why" }, area.why_this_is_being_checked)
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
function emailIcon() {
|
|
1420
|
+
return svg(
|
|
1421
|
+
"svg",
|
|
1422
|
+
{ width: 18, height: 18, viewBox: "0 0 24 24", fill: "none" },
|
|
1423
|
+
svg("path", {
|
|
1424
|
+
d: "M4 6h16v12H4z",
|
|
1425
|
+
stroke: "currentColor",
|
|
1426
|
+
"stroke-width": 2,
|
|
1427
|
+
"stroke-linejoin": "round"
|
|
1428
|
+
}),
|
|
1429
|
+
svg("path", {
|
|
1430
|
+
d: "M4 7l8 6 8-6",
|
|
1431
|
+
stroke: "currentColor",
|
|
1432
|
+
"stroke-width": 2,
|
|
1433
|
+
"stroke-linecap": "round",
|
|
1434
|
+
"stroke-linejoin": "round"
|
|
1435
|
+
})
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
function renderQuickInsights(brand, opts) {
|
|
1439
|
+
const ins = opts.insights;
|
|
1440
|
+
const title = el(
|
|
1441
|
+
"h3",
|
|
1442
|
+
{ className: "dpdpa-qi-title" },
|
|
1443
|
+
`Preliminary DPDPA scan for ${opts.companyName}`
|
|
1444
|
+
);
|
|
1445
|
+
const subtitle = el(
|
|
1446
|
+
"p",
|
|
1447
|
+
{ className: "dpdpa-qi-subtitle" },
|
|
1448
|
+
ins.summary
|
|
1449
|
+
);
|
|
1450
|
+
const confidence = el(
|
|
1451
|
+
"div",
|
|
1452
|
+
{ className: "dpdpa-confidence-row" },
|
|
1453
|
+
el("span", { className: "dpdpa-meta-label" }, "Confidence"),
|
|
1454
|
+
chip(ins.confidence)
|
|
1455
|
+
);
|
|
1456
|
+
const applicability = applicabilityBadge(
|
|
1457
|
+
ins.dpdpa_applicability_signal.level,
|
|
1458
|
+
ins.dpdpa_applicability_signal.reason
|
|
1459
|
+
);
|
|
1460
|
+
const eduNote = el(
|
|
1461
|
+
"div",
|
|
1462
|
+
{ className: "dpdpa-callout" },
|
|
1463
|
+
el("div", { className: "dpdpa-callout-title" }, ins.educational_note.title),
|
|
1464
|
+
el("p", { className: "dpdpa-callout-message" }, ins.educational_note.message)
|
|
1465
|
+
);
|
|
1466
|
+
const areasSection = el(
|
|
1467
|
+
"section",
|
|
1468
|
+
{ className: "dpdpa-section" },
|
|
1469
|
+
sectionTitle("Areas under review"),
|
|
1470
|
+
el(
|
|
1471
|
+
"div",
|
|
1472
|
+
{ className: "dpdpa-area-list" },
|
|
1473
|
+
...ins.areas_under_review.map((a) => areaCard(a))
|
|
1474
|
+
)
|
|
1475
|
+
);
|
|
1476
|
+
const cu = ins.company_understanding;
|
|
1477
|
+
const companySection = el(
|
|
1478
|
+
"section",
|
|
1479
|
+
{ className: "dpdpa-section" },
|
|
1480
|
+
sectionTitle("Company understanding"),
|
|
1481
|
+
el("p", { className: "dpdpa-cu-profile" }, cu.business_profile),
|
|
1482
|
+
el(
|
|
1483
|
+
"div",
|
|
1484
|
+
{ className: "dpdpa-cu-meta" },
|
|
1485
|
+
el("span", { className: "dpdpa-meta-label" }, "Likely users"),
|
|
1486
|
+
el("span", { className: "dpdpa-meta-value" }, cu.likely_user_relationship)
|
|
1487
|
+
),
|
|
1488
|
+
el(
|
|
1489
|
+
"div",
|
|
1490
|
+
{ className: "dpdpa-chip-row" },
|
|
1491
|
+
...cu.likely_digital_touchpoints.map((t) => chip(t, "touchpoint"))
|
|
1492
|
+
)
|
|
1493
|
+
);
|
|
1494
|
+
const dataSection = el(
|
|
1495
|
+
"section",
|
|
1496
|
+
{ className: "dpdpa-section" },
|
|
1497
|
+
sectionTitle("Data likely to validate"),
|
|
1498
|
+
el(
|
|
1499
|
+
"div",
|
|
1500
|
+
{ className: "dpdpa-chip-row" },
|
|
1501
|
+
...ins.likely_data_to_validate.map((d) => chip(d, "data"))
|
|
1502
|
+
)
|
|
1503
|
+
);
|
|
1504
|
+
const emailBanner = el(
|
|
1505
|
+
"div",
|
|
1506
|
+
{ className: "dpdpa-email-banner" },
|
|
1507
|
+
el("span", { className: "dpdpa-email-icon" }, emailIcon()),
|
|
1508
|
+
el(
|
|
1509
|
+
"div",
|
|
1510
|
+
{ className: "dpdpa-email-text" },
|
|
1511
|
+
el(
|
|
1512
|
+
"strong",
|
|
1513
|
+
{ className: "dpdpa-email-headline" },
|
|
1514
|
+
"Your full DPDPA report is on its way."
|
|
1515
|
+
),
|
|
1516
|
+
el(
|
|
1517
|
+
"p",
|
|
1518
|
+
{ className: "dpdpa-email-sub" },
|
|
1519
|
+
`We'll email it to `,
|
|
1520
|
+
el("strong", null, opts.email),
|
|
1521
|
+
` once compliance validation finishes.`
|
|
1522
|
+
)
|
|
1523
|
+
)
|
|
1170
1524
|
);
|
|
1171
1525
|
const resetLink = el(
|
|
1172
1526
|
"a",
|
|
@@ -1178,26 +1532,33 @@ function renderComplete(brand, opts) {
|
|
|
1178
1532
|
opts.onReset();
|
|
1179
1533
|
}
|
|
1180
1534
|
},
|
|
1181
|
-
"
|
|
1535
|
+
"Run another scan"
|
|
1182
1536
|
);
|
|
1183
1537
|
const body = el(
|
|
1184
1538
|
"div",
|
|
1185
|
-
{ className: "dpdpa-
|
|
1186
|
-
checkIcon(brand),
|
|
1187
|
-
el(
|
|
1188
|
-
"h3",
|
|
1189
|
-
{ className: "dpdpa-success-title" },
|
|
1190
|
-
`Your DPDPA report for ${opts.companyName} is ready`
|
|
1191
|
-
),
|
|
1539
|
+
{ className: "dpdpa-qi" },
|
|
1192
1540
|
el(
|
|
1193
|
-
"
|
|
1194
|
-
{ className: "dpdpa-
|
|
1195
|
-
|
|
1541
|
+
"div",
|
|
1542
|
+
{ className: "dpdpa-qi-header" },
|
|
1543
|
+
title,
|
|
1544
|
+
applicability
|
|
1196
1545
|
),
|
|
1197
|
-
|
|
1546
|
+
subtitle,
|
|
1547
|
+
confidence,
|
|
1548
|
+
eduNote,
|
|
1549
|
+
areasSection,
|
|
1550
|
+
companySection,
|
|
1551
|
+
dataSection,
|
|
1552
|
+
emailBanner,
|
|
1198
1553
|
resetLink
|
|
1199
1554
|
);
|
|
1200
|
-
return el(
|
|
1555
|
+
return el(
|
|
1556
|
+
"div",
|
|
1557
|
+
{ className: "dpdpa-card dpdpa-card-wide" },
|
|
1558
|
+
header(brand),
|
|
1559
|
+
body,
|
|
1560
|
+
footer(brand)
|
|
1561
|
+
);
|
|
1201
1562
|
}
|
|
1202
1563
|
function renderError(brand, opts) {
|
|
1203
1564
|
const retryBtn = el(
|
|
@@ -1236,7 +1597,6 @@ var FormController = class {
|
|
|
1236
1597
|
this.pollHiddenSince = null;
|
|
1237
1598
|
this.pollHiddenTotalMs = 0;
|
|
1238
1599
|
this.pollResumePending = false;
|
|
1239
|
-
this.lastSubStatus = null;
|
|
1240
1600
|
this.consecutiveErrors = 0;
|
|
1241
1601
|
this.destroyed = false;
|
|
1242
1602
|
this.unsubscribe = null;
|
|
@@ -1249,7 +1609,7 @@ var FormController = class {
|
|
|
1249
1609
|
subStatus: "pending",
|
|
1250
1610
|
elapsedMs: 0,
|
|
1251
1611
|
jobId: null,
|
|
1252
|
-
|
|
1612
|
+
quickInsights: null,
|
|
1253
1613
|
errors: {},
|
|
1254
1614
|
generalError: null,
|
|
1255
1615
|
errorMessage: "",
|
|
@@ -1335,10 +1695,11 @@ var FormController = class {
|
|
|
1335
1695
|
pollTimeoutMs: this.getPollTimeout()
|
|
1336
1696
|
});
|
|
1337
1697
|
break;
|
|
1338
|
-
case "
|
|
1339
|
-
node =
|
|
1698
|
+
case "quick_insights":
|
|
1699
|
+
node = renderQuickInsights(this.brand, {
|
|
1340
1700
|
companyName: this.fields.company_name,
|
|
1341
|
-
|
|
1701
|
+
email: this.fields.email,
|
|
1702
|
+
insights: s.quickInsights,
|
|
1342
1703
|
onReset: () => this.resetToIdle()
|
|
1343
1704
|
});
|
|
1344
1705
|
break;
|
|
@@ -1346,7 +1707,7 @@ var FormController = class {
|
|
|
1346
1707
|
node = renderError(this.brand, {
|
|
1347
1708
|
message: s.errorMessage,
|
|
1348
1709
|
retryable: s.retryable,
|
|
1349
|
-
onRetry: () => this.
|
|
1710
|
+
onRetry: () => this.retry(),
|
|
1350
1711
|
onBack: () => {
|
|
1351
1712
|
var _a;
|
|
1352
1713
|
return this.backToIdle((_a = s.generalError) != null ? _a : s.errorMessage);
|
|
@@ -1446,7 +1807,8 @@ var FormController = class {
|
|
|
1446
1807
|
baseUrl: this.getBaseUrl(),
|
|
1447
1808
|
body: {
|
|
1448
1809
|
company_name: lead.company_name,
|
|
1449
|
-
company_domain: lead.company_domain
|
|
1810
|
+
company_domain: lead.company_domain,
|
|
1811
|
+
requested_by: lead.email
|
|
1450
1812
|
}
|
|
1451
1813
|
});
|
|
1452
1814
|
if (this.destroyed) return;
|
|
@@ -1479,7 +1841,6 @@ var FormController = class {
|
|
|
1479
1841
|
this.pollStartedAt = Date.now();
|
|
1480
1842
|
this.pollHiddenSince = null;
|
|
1481
1843
|
this.pollHiddenTotalMs = 0;
|
|
1482
|
-
this.lastSubStatus = null;
|
|
1483
1844
|
this.consecutiveErrors = 0;
|
|
1484
1845
|
this.store.setState({
|
|
1485
1846
|
phase: "polling",
|
|
@@ -1501,18 +1862,19 @@ var FormController = class {
|
|
|
1501
1862
|
this.pollTimer = setTimeout(() => this.pollTick(), interval);
|
|
1502
1863
|
}
|
|
1503
1864
|
getActiveElapsed() {
|
|
1504
|
-
|
|
1865
|
+
const hiddenInFlight = this.pollHiddenSince !== null ? Date.now() - this.pollHiddenSince : 0;
|
|
1866
|
+
return Date.now() - this.pollStartedAt - this.pollHiddenTotalMs - hiddenInFlight;
|
|
1505
1867
|
}
|
|
1506
1868
|
async pollTick() {
|
|
1507
|
-
var _a, _b
|
|
1869
|
+
var _a, _b;
|
|
1508
1870
|
if (this.destroyed) return;
|
|
1509
1871
|
const jobId = this.store.getState().jobId;
|
|
1510
1872
|
if (!jobId) return;
|
|
1511
1873
|
const activeElapsed = this.getActiveElapsed();
|
|
1512
1874
|
if (activeElapsed >= this.getPollTimeout()) {
|
|
1513
1875
|
this.showError(
|
|
1514
|
-
"
|
|
1515
|
-
|
|
1876
|
+
"Quick insights are taking longer than expected. Please try again.",
|
|
1877
|
+
true
|
|
1516
1878
|
);
|
|
1517
1879
|
this.emitError("Polling timed out", "timeout");
|
|
1518
1880
|
return;
|
|
@@ -1522,33 +1884,47 @@ var FormController = class {
|
|
|
1522
1884
|
if (this.destroyed) return;
|
|
1523
1885
|
this.consecutiveErrors = 0;
|
|
1524
1886
|
if ("status" in res && res.status === "error") {
|
|
1525
|
-
|
|
1526
|
-
this.
|
|
1887
|
+
const errShape = res;
|
|
1888
|
+
this.showError(errShape.message || "Report generation failed.", true);
|
|
1889
|
+
this.emitError(errShape.message || "Job errored", "poll");
|
|
1527
1890
|
return;
|
|
1528
1891
|
}
|
|
1529
|
-
|
|
1892
|
+
const inProgress = res;
|
|
1893
|
+
if (inProgress.quick_insights_status === "complete") {
|
|
1894
|
+
const insights = inProgress.quick_insights;
|
|
1895
|
+
if (!insights) {
|
|
1896
|
+
this.showError(
|
|
1897
|
+
"Quick insights are marked complete but the payload is missing. Please try again.",
|
|
1898
|
+
true
|
|
1899
|
+
);
|
|
1900
|
+
this.emitError(
|
|
1901
|
+
"Quick insights complete without payload",
|
|
1902
|
+
"poll"
|
|
1903
|
+
);
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1530
1906
|
const acceptedLead = this.makeLead(jobId);
|
|
1531
1907
|
saveLead(acceptedLead);
|
|
1532
1908
|
this.store.setState({
|
|
1533
|
-
phase: "
|
|
1534
|
-
|
|
1909
|
+
phase: "quick_insights",
|
|
1910
|
+
quickInsights: insights
|
|
1535
1911
|
});
|
|
1536
1912
|
try {
|
|
1537
|
-
(_b = (_a = this.options).
|
|
1913
|
+
(_b = (_a = this.options).onQuickInsightsReady) == null ? void 0 : _b.call(_a, insights, acceptedLead);
|
|
1538
1914
|
} catch (err) {
|
|
1539
|
-
console.error("
|
|
1915
|
+
console.error("onQuickInsightsReady handler threw:", err);
|
|
1540
1916
|
}
|
|
1541
1917
|
return;
|
|
1542
1918
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
}
|
|
1919
|
+
if (inProgress.quick_insights_status === "error") {
|
|
1920
|
+
this.showError(
|
|
1921
|
+
"We couldn't generate quick insights. Please try again.",
|
|
1922
|
+
true
|
|
1923
|
+
);
|
|
1924
|
+
this.emitError("Quick insights errored", "poll");
|
|
1925
|
+
return;
|
|
1551
1926
|
}
|
|
1927
|
+
const sub = (inProgress.status === "complete" ? "analysis_complete" : inProgress.status) || "pending";
|
|
1552
1928
|
this.store.setState({
|
|
1553
1929
|
phase: "polling",
|
|
1554
1930
|
subStatus: sub,
|
|
@@ -1582,8 +1958,13 @@ var FormController = class {
|
|
|
1582
1958
|
handleVisibilityChange() {
|
|
1583
1959
|
if (this.destroyed) return;
|
|
1584
1960
|
if (document.hidden) {
|
|
1585
|
-
if (this.store.getState().phase === "polling"
|
|
1586
|
-
this.pollHiddenSince = Date.now();
|
|
1961
|
+
if (this.store.getState().phase === "polling") {
|
|
1962
|
+
if (this.pollHiddenSince === null) this.pollHiddenSince = Date.now();
|
|
1963
|
+
if (this.pollTimer) {
|
|
1964
|
+
clearTimeout(this.pollTimer);
|
|
1965
|
+
this.pollTimer = null;
|
|
1966
|
+
}
|
|
1967
|
+
this.pollResumePending = true;
|
|
1587
1968
|
}
|
|
1588
1969
|
return;
|
|
1589
1970
|
}
|
|
@@ -1603,15 +1984,25 @@ var FormController = class {
|
|
|
1603
1984
|
retryable
|
|
1604
1985
|
});
|
|
1605
1986
|
}
|
|
1987
|
+
// Resume polling on the existing job_id when we already have one;
|
|
1988
|
+
// otherwise re-POST. Prevents duplicate email delivery when a transient
|
|
1989
|
+
// poll/timeout error is retried.
|
|
1990
|
+
retry() {
|
|
1991
|
+
const jobId = this.store.getState().jobId;
|
|
1992
|
+
if (jobId) {
|
|
1993
|
+
this.startPolling(jobId);
|
|
1994
|
+
} else {
|
|
1995
|
+
this.submit();
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1606
1998
|
resetToIdle() {
|
|
1607
1999
|
this.fields = { ...EMPTY_FIELDS };
|
|
1608
|
-
this.lastSubStatus = null;
|
|
1609
2000
|
this.store.setState({
|
|
1610
2001
|
phase: "idle",
|
|
1611
2002
|
errors: {},
|
|
1612
2003
|
generalError: null,
|
|
1613
2004
|
errorMessage: "",
|
|
1614
|
-
|
|
2005
|
+
quickInsights: null,
|
|
1615
2006
|
jobId: null,
|
|
1616
2007
|
subStatus: "pending",
|
|
1617
2008
|
elapsedMs: 0
|
|
@@ -1653,7 +2044,7 @@ var FormController = class {
|
|
|
1653
2044
|
};
|
|
1654
2045
|
|
|
1655
2046
|
// src/index.ts
|
|
1656
|
-
var version = "0.
|
|
2047
|
+
var version = "0.3.0";
|
|
1657
2048
|
var activeController = null;
|
|
1658
2049
|
function init(options) {
|
|
1659
2050
|
destroy();
|