@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.mjs
CHANGED
|
@@ -5,7 +5,7 @@ var PATHS = {
|
|
|
5
5
|
status: "/webhook/dpdpa/status"
|
|
6
6
|
};
|
|
7
7
|
var DEFAULT_POLL_INTERVAL_MS = 3e3;
|
|
8
|
-
var DEFAULT_POLL_TIMEOUT_MS =
|
|
8
|
+
var DEFAULT_POLL_TIMEOUT_MS = 9e4;
|
|
9
9
|
var MAX_CONSECUTIVE_ERRORS = 3;
|
|
10
10
|
var REQUEST_TIMEOUT_MS = 15e3;
|
|
11
11
|
var STORAGE_KEY = "redacto_dpdpa_lead";
|
|
@@ -707,6 +707,291 @@ function buildCss(brand) {
|
|
|
707
707
|
from { transform: rotate(0deg); }
|
|
708
708
|
to { transform: rotate(360deg); }
|
|
709
709
|
}
|
|
710
|
+
|
|
711
|
+
/* Quick insights view */
|
|
712
|
+
|
|
713
|
+
.dpdpa-card-wide {
|
|
714
|
+
min-height: 0;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.dpdpa-qi {
|
|
718
|
+
display: flex;
|
|
719
|
+
flex-direction: column;
|
|
720
|
+
gap: 18px;
|
|
721
|
+
flex: 1;
|
|
722
|
+
animation: dpdpa-fade-in 0.35s ease-out both;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.dpdpa-qi-header {
|
|
726
|
+
display: flex;
|
|
727
|
+
flex-direction: column;
|
|
728
|
+
gap: 12px;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
.dpdpa-qi-title {
|
|
732
|
+
margin: 0;
|
|
733
|
+
font-size: 18px;
|
|
734
|
+
font-weight: 700;
|
|
735
|
+
color: ${brand.text};
|
|
736
|
+
line-height: 1.3;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.dpdpa-qi-subtitle {
|
|
740
|
+
margin: 0;
|
|
741
|
+
font-size: 14px;
|
|
742
|
+
color: ${brand.text};
|
|
743
|
+
opacity: 0.85;
|
|
744
|
+
line-height: 1.55;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.dpdpa-applicability {
|
|
748
|
+
display: flex;
|
|
749
|
+
flex-direction: column;
|
|
750
|
+
gap: 4px;
|
|
751
|
+
padding: 12px 14px;
|
|
752
|
+
border-radius: ${brand.borderRadius};
|
|
753
|
+
border: 1px solid ${brand.border};
|
|
754
|
+
background: #ffffff;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.dpdpa-applicability-level {
|
|
758
|
+
font-size: 11px;
|
|
759
|
+
font-weight: 700;
|
|
760
|
+
letter-spacing: 0.6px;
|
|
761
|
+
text-transform: uppercase;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
.dpdpa-applicability-reason {
|
|
765
|
+
font-size: 13px;
|
|
766
|
+
color: ${brand.text};
|
|
767
|
+
opacity: 0.85;
|
|
768
|
+
line-height: 1.45;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
.dpdpa-badge-strong { border-color: ${brand.primary}66; background: ${brand.primary}10; }
|
|
772
|
+
.dpdpa-badge-strong .dpdpa-applicability-level { color: ${brand.primary}; }
|
|
773
|
+
|
|
774
|
+
.dpdpa-badge-warn { border-color: #f59e0b66; background: #f59e0b14; }
|
|
775
|
+
.dpdpa-badge-warn .dpdpa-applicability-level { color: #b45309; }
|
|
776
|
+
|
|
777
|
+
.dpdpa-badge-soft { border-color: #94a3b866; background: #94a3b814; }
|
|
778
|
+
.dpdpa-badge-soft .dpdpa-applicability-level { color: #475569; }
|
|
779
|
+
|
|
780
|
+
.dpdpa-badge-mute { border-color: ${brand.border}; background: ${brand.background}; }
|
|
781
|
+
.dpdpa-badge-mute .dpdpa-applicability-level { color: ${brand.text}; opacity: 0.7; }
|
|
782
|
+
|
|
783
|
+
.dpdpa-badge-neutral { border-color: ${brand.border}; background: ${brand.background}; }
|
|
784
|
+
.dpdpa-badge-neutral .dpdpa-applicability-level { color: ${brand.text}; }
|
|
785
|
+
|
|
786
|
+
.dpdpa-confidence-row {
|
|
787
|
+
display: flex;
|
|
788
|
+
align-items: center;
|
|
789
|
+
gap: 8px;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.dpdpa-meta-label {
|
|
793
|
+
font-size: 11px;
|
|
794
|
+
font-weight: 700;
|
|
795
|
+
letter-spacing: 0.5px;
|
|
796
|
+
text-transform: uppercase;
|
|
797
|
+
color: ${brand.text};
|
|
798
|
+
opacity: 0.6;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.dpdpa-meta-value {
|
|
802
|
+
font-size: 13px;
|
|
803
|
+
color: ${brand.text};
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
.dpdpa-chip {
|
|
807
|
+
display: inline-flex;
|
|
808
|
+
align-items: center;
|
|
809
|
+
padding: 3px 8px;
|
|
810
|
+
font-size: 11px;
|
|
811
|
+
font-weight: 600;
|
|
812
|
+
color: ${brand.text};
|
|
813
|
+
background: ${brand.background};
|
|
814
|
+
border: 1px solid ${brand.border};
|
|
815
|
+
border-radius: 999px;
|
|
816
|
+
white-space: nowrap;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
.dpdpa-chip-ref {
|
|
820
|
+
background: ${brand.primary}12;
|
|
821
|
+
border-color: ${brand.primary}33;
|
|
822
|
+
color: ${brand.primary};
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.dpdpa-chip-data {
|
|
826
|
+
background: #ecfeff;
|
|
827
|
+
border-color: #67e8f933;
|
|
828
|
+
color: #0e7490;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.dpdpa-chip-touchpoint {
|
|
832
|
+
background: #f5f3ff;
|
|
833
|
+
border-color: #c4b5fd33;
|
|
834
|
+
color: #5b21b6;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.dpdpa-chip-row {
|
|
838
|
+
display: flex;
|
|
839
|
+
flex-wrap: wrap;
|
|
840
|
+
gap: 6px;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.dpdpa-callout {
|
|
844
|
+
padding: 12px 14px;
|
|
845
|
+
background: ${brand.primary}08;
|
|
846
|
+
border: 1px solid ${brand.primary}22;
|
|
847
|
+
border-radius: ${brand.borderRadius};
|
|
848
|
+
display: flex;
|
|
849
|
+
flex-direction: column;
|
|
850
|
+
gap: 4px;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.dpdpa-callout-title {
|
|
854
|
+
font-size: 12px;
|
|
855
|
+
font-weight: 700;
|
|
856
|
+
letter-spacing: 0.3px;
|
|
857
|
+
text-transform: uppercase;
|
|
858
|
+
color: ${brand.primary};
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.dpdpa-callout-message {
|
|
862
|
+
margin: 0;
|
|
863
|
+
font-size: 13px;
|
|
864
|
+
color: ${brand.text};
|
|
865
|
+
line-height: 1.5;
|
|
866
|
+
opacity: 0.85;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.dpdpa-section {
|
|
870
|
+
display: flex;
|
|
871
|
+
flex-direction: column;
|
|
872
|
+
gap: 10px;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
.dpdpa-section-title {
|
|
876
|
+
margin: 0;
|
|
877
|
+
font-size: 13px;
|
|
878
|
+
font-weight: 700;
|
|
879
|
+
color: ${brand.text};
|
|
880
|
+
letter-spacing: 0.2px;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.dpdpa-area-list {
|
|
884
|
+
display: flex;
|
|
885
|
+
flex-direction: column;
|
|
886
|
+
gap: 10px;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.dpdpa-area-card {
|
|
890
|
+
padding: 12px 14px;
|
|
891
|
+
background: #ffffff;
|
|
892
|
+
border: 1px solid ${brand.border};
|
|
893
|
+
border-radius: ${brand.borderRadius};
|
|
894
|
+
display: flex;
|
|
895
|
+
flex-direction: column;
|
|
896
|
+
gap: 8px;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.dpdpa-area-heading {
|
|
900
|
+
display: flex;
|
|
901
|
+
align-items: center;
|
|
902
|
+
justify-content: space-between;
|
|
903
|
+
gap: 10px;
|
|
904
|
+
flex-wrap: wrap;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
.dpdpa-area-name {
|
|
908
|
+
margin: 0;
|
|
909
|
+
font-size: 14px;
|
|
910
|
+
font-weight: 700;
|
|
911
|
+
color: ${brand.text};
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.dpdpa-product-hint {
|
|
915
|
+
font-size: 11px;
|
|
916
|
+
font-weight: 600;
|
|
917
|
+
color: ${brand.primary};
|
|
918
|
+
background: ${brand.primary}12;
|
|
919
|
+
padding: 3px 8px;
|
|
920
|
+
border-radius: 999px;
|
|
921
|
+
white-space: nowrap;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.dpdpa-area-why {
|
|
925
|
+
margin: 0;
|
|
926
|
+
font-size: 13px;
|
|
927
|
+
color: ${brand.text};
|
|
928
|
+
opacity: 0.8;
|
|
929
|
+
line-height: 1.5;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.dpdpa-cu-profile {
|
|
933
|
+
margin: 0;
|
|
934
|
+
font-size: 13px;
|
|
935
|
+
color: ${brand.text};
|
|
936
|
+
opacity: 0.85;
|
|
937
|
+
line-height: 1.5;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.dpdpa-cu-meta {
|
|
941
|
+
display: flex;
|
|
942
|
+
align-items: center;
|
|
943
|
+
gap: 8px;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
.dpdpa-email-banner {
|
|
947
|
+
display: flex;
|
|
948
|
+
align-items: flex-start;
|
|
949
|
+
gap: 12px;
|
|
950
|
+
padding: 14px 16px;
|
|
951
|
+
background: linear-gradient(135deg, ${brand.primary}10, ${brand.accent}10);
|
|
952
|
+
border: 1px solid ${brand.primary}33;
|
|
953
|
+
border-radius: ${brand.borderRadius};
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.dpdpa-email-icon {
|
|
957
|
+
flex: none;
|
|
958
|
+
display: inline-flex;
|
|
959
|
+
align-items: center;
|
|
960
|
+
justify-content: center;
|
|
961
|
+
width: 32px;
|
|
962
|
+
height: 32px;
|
|
963
|
+
border-radius: 50%;
|
|
964
|
+
background: ${brand.primary};
|
|
965
|
+
color: ${brand.primaryText};
|
|
966
|
+
margin-top: 2px;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.dpdpa-email-text {
|
|
970
|
+
display: flex;
|
|
971
|
+
flex-direction: column;
|
|
972
|
+
gap: 2px;
|
|
973
|
+
min-width: 0;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.dpdpa-email-headline {
|
|
977
|
+
font-size: 14px;
|
|
978
|
+
font-weight: 700;
|
|
979
|
+
color: ${brand.text};
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.dpdpa-email-sub {
|
|
983
|
+
margin: 0;
|
|
984
|
+
font-size: 13px;
|
|
985
|
+
color: ${brand.text};
|
|
986
|
+
opacity: 0.8;
|
|
987
|
+
line-height: 1.5;
|
|
988
|
+
word-break: break-word;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
@keyframes dpdpa-fade-in {
|
|
992
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
993
|
+
to { opacity: 1; transform: translateY(0); }
|
|
994
|
+
}
|
|
710
995
|
`;
|
|
711
996
|
}
|
|
712
997
|
function injectFormStyles(root, brand) {
|
|
@@ -944,7 +1229,7 @@ function renderIdle(brand, fields, errors, generalErrorText, handlers) {
|
|
|
944
1229
|
el(
|
|
945
1230
|
"p",
|
|
946
1231
|
{ className: "dpdpa-subheading" },
|
|
947
|
-
"We'll
|
|
1232
|
+
"We'll preview your DPDPA exposure here and email you the full report."
|
|
948
1233
|
),
|
|
949
1234
|
generalError,
|
|
950
1235
|
nameRow.row,
|
|
@@ -1004,42 +1289,12 @@ function animatedDots() {
|
|
|
1004
1289
|
el("span")
|
|
1005
1290
|
);
|
|
1006
1291
|
}
|
|
1007
|
-
function stepCheck(brand) {
|
|
1008
|
-
return el(
|
|
1009
|
-
"div",
|
|
1010
|
-
{
|
|
1011
|
-
className: "dpdpa-step-icon dpdpa-step-icon-done",
|
|
1012
|
-
style: { backgroundColor: brand.successColor }
|
|
1013
|
-
},
|
|
1014
|
-
svg(
|
|
1015
|
-
"svg",
|
|
1016
|
-
{ width: 12, height: 12, viewBox: "0 0 24 24", fill: "none" },
|
|
1017
|
-
svg("path", {
|
|
1018
|
-
d: "M5 12l5 5L20 7",
|
|
1019
|
-
stroke: "#ffffff",
|
|
1020
|
-
"stroke-width": 3,
|
|
1021
|
-
"stroke-linecap": "round",
|
|
1022
|
-
"stroke-linejoin": "round"
|
|
1023
|
-
})
|
|
1024
|
-
)
|
|
1025
|
-
);
|
|
1026
|
-
}
|
|
1027
1292
|
function stepPulse(brand) {
|
|
1028
1293
|
return el("div", {
|
|
1029
1294
|
className: "dpdpa-step-icon dpdpa-step-icon-active",
|
|
1030
1295
|
style: { backgroundColor: brand.primary }
|
|
1031
1296
|
});
|
|
1032
1297
|
}
|
|
1033
|
-
var STEP_ORDER = {
|
|
1034
|
-
pending: 0,
|
|
1035
|
-
researching: 0,
|
|
1036
|
-
analysis_complete: 2
|
|
1037
|
-
};
|
|
1038
|
-
var STEPS = [
|
|
1039
|
-
{ label: (company) => `Researching ${company}` },
|
|
1040
|
-
{ label: () => "Analysing DPDPA compliance" },
|
|
1041
|
-
{ label: () => "Generating your report" }
|
|
1042
|
-
];
|
|
1043
1298
|
function renderPolling(brand, opts) {
|
|
1044
1299
|
const pct = Math.min(100, Math.round(opts.elapsedMs / opts.pollTimeoutMs * 100));
|
|
1045
1300
|
const progressFill = el("div", {
|
|
@@ -1051,92 +1306,191 @@ function renderPolling(brand, opts) {
|
|
|
1051
1306
|
{
|
|
1052
1307
|
className: "dpdpa-progress",
|
|
1053
1308
|
role: "progressbar",
|
|
1054
|
-
"aria-label": "
|
|
1309
|
+
"aria-label": "Quick insights progress",
|
|
1055
1310
|
"aria-valuemin": "0",
|
|
1056
1311
|
"aria-valuemax": "100",
|
|
1057
1312
|
"aria-valuenow": String(pct)
|
|
1058
1313
|
},
|
|
1059
1314
|
progressFill
|
|
1060
1315
|
);
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
"
|
|
1068
|
-
{
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
el(
|
|
1073
|
-
"span",
|
|
1074
|
-
{
|
|
1075
|
-
className: isActive ? "dpdpa-step-label dpdpa-shimmer" : "dpdpa-step-label"
|
|
1076
|
-
},
|
|
1077
|
-
step.label(opts.companyName)
|
|
1078
|
-
)
|
|
1079
|
-
);
|
|
1080
|
-
if (isActive) row.appendChild(animatedDots());
|
|
1081
|
-
stepsList.appendChild(row);
|
|
1082
|
-
});
|
|
1316
|
+
const stepRow = el(
|
|
1317
|
+
"div",
|
|
1318
|
+
{ className: "dpdpa-step dpdpa-step-active" },
|
|
1319
|
+
stepPulse(brand),
|
|
1320
|
+
el(
|
|
1321
|
+
"span",
|
|
1322
|
+
{ className: "dpdpa-step-label dpdpa-shimmer" },
|
|
1323
|
+
`Scanning ${opts.companyName}'s privacy footprint`
|
|
1324
|
+
),
|
|
1325
|
+
animatedDots()
|
|
1326
|
+
);
|
|
1083
1327
|
const body = el(
|
|
1084
1328
|
"div",
|
|
1085
1329
|
{ className: "dpdpa-polling" },
|
|
1086
|
-
|
|
1330
|
+
el("div", { className: "dpdpa-steps" }, stepRow),
|
|
1087
1331
|
el(
|
|
1088
1332
|
"p",
|
|
1089
1333
|
{ className: "dpdpa-polling-sub" },
|
|
1090
|
-
"
|
|
1334
|
+
"Generating your preliminary DPDPA scan. This usually takes 10\u201320 seconds."
|
|
1091
1335
|
),
|
|
1092
1336
|
progressBar
|
|
1093
1337
|
);
|
|
1094
1338
|
return el("div", { className: "dpdpa-card" }, header(brand), body, footer(brand));
|
|
1095
1339
|
}
|
|
1096
|
-
function
|
|
1340
|
+
function chip(text, variant) {
|
|
1341
|
+
return el(
|
|
1342
|
+
"span",
|
|
1343
|
+
{ className: `dpdpa-chip${variant ? ` dpdpa-chip-${variant}` : ""}` },
|
|
1344
|
+
text
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
function applicabilityBadge(level, reason) {
|
|
1348
|
+
const upper = (level || "").toUpperCase();
|
|
1349
|
+
let cls = "dpdpa-badge-neutral";
|
|
1350
|
+
if (upper.includes("VERY_LIKELY")) cls = "dpdpa-badge-strong";
|
|
1351
|
+
else if (upper === "LIKELY") cls = "dpdpa-badge-warn";
|
|
1352
|
+
else if (upper === "POSSIBLY") cls = "dpdpa-badge-soft";
|
|
1353
|
+
else if (upper === "UNLIKELY") cls = "dpdpa-badge-mute";
|
|
1097
1354
|
return el(
|
|
1098
1355
|
"div",
|
|
1099
|
-
{
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
},
|
|
1103
|
-
svg(
|
|
1104
|
-
"svg",
|
|
1105
|
-
{
|
|
1106
|
-
width: 28,
|
|
1107
|
-
height: 28,
|
|
1108
|
-
viewBox: "0 0 24 24",
|
|
1109
|
-
fill: "none"
|
|
1110
|
-
},
|
|
1111
|
-
svg("path", {
|
|
1112
|
-
d: "M5 12l5 5L20 7",
|
|
1113
|
-
stroke: "#ffffff",
|
|
1114
|
-
"stroke-width": 3,
|
|
1115
|
-
"stroke-linecap": "round",
|
|
1116
|
-
"stroke-linejoin": "round"
|
|
1117
|
-
})
|
|
1118
|
-
)
|
|
1356
|
+
{ className: `dpdpa-applicability ${cls}` },
|
|
1357
|
+
el("span", { className: "dpdpa-applicability-level" }, level.replace(/_/g, " ")),
|
|
1358
|
+
el("span", { className: "dpdpa-applicability-reason" }, reason)
|
|
1119
1359
|
);
|
|
1120
1360
|
}
|
|
1121
|
-
function
|
|
1122
|
-
|
|
1123
|
-
if (!s) return false;
|
|
1124
|
-
if (/^https?:\/\//i.test(s)) return true;
|
|
1125
|
-
if (/^\/[^/]/.test(s) || s.startsWith("./") || s.startsWith("../"))
|
|
1126
|
-
return true;
|
|
1127
|
-
return false;
|
|
1361
|
+
function sectionTitle(text) {
|
|
1362
|
+
return el("h4", { className: "dpdpa-section-title" }, text);
|
|
1128
1363
|
}
|
|
1129
|
-
function
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1132
|
-
"
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1364
|
+
function areaCard(area) {
|
|
1365
|
+
const refs = el(
|
|
1366
|
+
"div",
|
|
1367
|
+
{ className: "dpdpa-chip-row" },
|
|
1368
|
+
...area.dpdpa_references.map((r) => chip(r, "ref"))
|
|
1369
|
+
);
|
|
1370
|
+
const hint = area.redacto_product_hint ? el(
|
|
1371
|
+
"span",
|
|
1372
|
+
{ className: "dpdpa-product-hint" },
|
|
1373
|
+
`Redacto ${area.redacto_product_hint}`
|
|
1374
|
+
) : null;
|
|
1375
|
+
const heading = el(
|
|
1376
|
+
"div",
|
|
1377
|
+
{ className: "dpdpa-area-heading" },
|
|
1378
|
+
el("h5", { className: "dpdpa-area-name" }, area.area),
|
|
1379
|
+
...hint ? [hint] : []
|
|
1380
|
+
);
|
|
1381
|
+
return el(
|
|
1382
|
+
"div",
|
|
1383
|
+
{ className: "dpdpa-area-card" },
|
|
1384
|
+
heading,
|
|
1385
|
+
refs,
|
|
1386
|
+
el("p", { className: "dpdpa-area-why" }, area.why_this_is_being_checked)
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
function emailIcon() {
|
|
1390
|
+
return svg(
|
|
1391
|
+
"svg",
|
|
1392
|
+
{ width: 18, height: 18, viewBox: "0 0 24 24", fill: "none" },
|
|
1393
|
+
svg("path", {
|
|
1394
|
+
d: "M4 6h16v12H4z",
|
|
1395
|
+
stroke: "currentColor",
|
|
1396
|
+
"stroke-width": 2,
|
|
1397
|
+
"stroke-linejoin": "round"
|
|
1398
|
+
}),
|
|
1399
|
+
svg("path", {
|
|
1400
|
+
d: "M4 7l8 6 8-6",
|
|
1401
|
+
stroke: "currentColor",
|
|
1402
|
+
"stroke-width": 2,
|
|
1403
|
+
"stroke-linecap": "round",
|
|
1404
|
+
"stroke-linejoin": "round"
|
|
1405
|
+
})
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1408
|
+
function renderQuickInsights(brand, opts) {
|
|
1409
|
+
const ins = opts.insights;
|
|
1410
|
+
const title = el(
|
|
1411
|
+
"h3",
|
|
1412
|
+
{ className: "dpdpa-qi-title" },
|
|
1413
|
+
`Preliminary DPDPA scan for ${opts.companyName}`
|
|
1414
|
+
);
|
|
1415
|
+
const subtitle = el(
|
|
1416
|
+
"p",
|
|
1417
|
+
{ className: "dpdpa-qi-subtitle" },
|
|
1418
|
+
ins.summary
|
|
1419
|
+
);
|
|
1420
|
+
const confidence = el(
|
|
1421
|
+
"div",
|
|
1422
|
+
{ className: "dpdpa-confidence-row" },
|
|
1423
|
+
el("span", { className: "dpdpa-meta-label" }, "Confidence"),
|
|
1424
|
+
chip(ins.confidence)
|
|
1425
|
+
);
|
|
1426
|
+
const applicability = applicabilityBadge(
|
|
1427
|
+
ins.dpdpa_applicability_signal.level,
|
|
1428
|
+
ins.dpdpa_applicability_signal.reason
|
|
1429
|
+
);
|
|
1430
|
+
const eduNote = el(
|
|
1431
|
+
"div",
|
|
1432
|
+
{ className: "dpdpa-callout" },
|
|
1433
|
+
el("div", { className: "dpdpa-callout-title" }, ins.educational_note.title),
|
|
1434
|
+
el("p", { className: "dpdpa-callout-message" }, ins.educational_note.message)
|
|
1435
|
+
);
|
|
1436
|
+
const areasSection = el(
|
|
1437
|
+
"section",
|
|
1438
|
+
{ className: "dpdpa-section" },
|
|
1439
|
+
sectionTitle("Areas under review"),
|
|
1440
|
+
el(
|
|
1441
|
+
"div",
|
|
1442
|
+
{ className: "dpdpa-area-list" },
|
|
1443
|
+
...ins.areas_under_review.map((a) => areaCard(a))
|
|
1444
|
+
)
|
|
1445
|
+
);
|
|
1446
|
+
const cu = ins.company_understanding;
|
|
1447
|
+
const companySection = el(
|
|
1448
|
+
"section",
|
|
1449
|
+
{ className: "dpdpa-section" },
|
|
1450
|
+
sectionTitle("Company understanding"),
|
|
1451
|
+
el("p", { className: "dpdpa-cu-profile" }, cu.business_profile),
|
|
1452
|
+
el(
|
|
1453
|
+
"div",
|
|
1454
|
+
{ className: "dpdpa-cu-meta" },
|
|
1455
|
+
el("span", { className: "dpdpa-meta-label" }, "Likely users"),
|
|
1456
|
+
el("span", { className: "dpdpa-meta-value" }, cu.likely_user_relationship)
|
|
1457
|
+
),
|
|
1458
|
+
el(
|
|
1459
|
+
"div",
|
|
1460
|
+
{ className: "dpdpa-chip-row" },
|
|
1461
|
+
...cu.likely_digital_touchpoints.map((t) => chip(t, "touchpoint"))
|
|
1462
|
+
)
|
|
1463
|
+
);
|
|
1464
|
+
const dataSection = el(
|
|
1465
|
+
"section",
|
|
1466
|
+
{ className: "dpdpa-section" },
|
|
1467
|
+
sectionTitle("Data likely to validate"),
|
|
1468
|
+
el(
|
|
1469
|
+
"div",
|
|
1470
|
+
{ className: "dpdpa-chip-row" },
|
|
1471
|
+
...ins.likely_data_to_validate.map((d) => chip(d, "data"))
|
|
1472
|
+
)
|
|
1473
|
+
);
|
|
1474
|
+
const emailBanner = el(
|
|
1475
|
+
"div",
|
|
1476
|
+
{ className: "dpdpa-email-banner" },
|
|
1477
|
+
el("span", { className: "dpdpa-email-icon" }, emailIcon()),
|
|
1478
|
+
el(
|
|
1479
|
+
"div",
|
|
1480
|
+
{ className: "dpdpa-email-text" },
|
|
1481
|
+
el(
|
|
1482
|
+
"strong",
|
|
1483
|
+
{ className: "dpdpa-email-headline" },
|
|
1484
|
+
"Your full DPDPA report is on its way."
|
|
1485
|
+
),
|
|
1486
|
+
el(
|
|
1487
|
+
"p",
|
|
1488
|
+
{ className: "dpdpa-email-sub" },
|
|
1489
|
+
`We'll email it to `,
|
|
1490
|
+
el("strong", null, opts.email),
|
|
1491
|
+
` once compliance validation finishes.`
|
|
1492
|
+
)
|
|
1493
|
+
)
|
|
1140
1494
|
);
|
|
1141
1495
|
const resetLink = el(
|
|
1142
1496
|
"a",
|
|
@@ -1148,26 +1502,33 @@ function renderComplete(brand, opts) {
|
|
|
1148
1502
|
opts.onReset();
|
|
1149
1503
|
}
|
|
1150
1504
|
},
|
|
1151
|
-
"
|
|
1505
|
+
"Run another scan"
|
|
1152
1506
|
);
|
|
1153
1507
|
const body = el(
|
|
1154
1508
|
"div",
|
|
1155
|
-
{ className: "dpdpa-
|
|
1156
|
-
checkIcon(brand),
|
|
1157
|
-
el(
|
|
1158
|
-
"h3",
|
|
1159
|
-
{ className: "dpdpa-success-title" },
|
|
1160
|
-
`Your DPDPA report for ${opts.companyName} is ready`
|
|
1161
|
-
),
|
|
1509
|
+
{ className: "dpdpa-qi" },
|
|
1162
1510
|
el(
|
|
1163
|
-
"
|
|
1164
|
-
{ className: "dpdpa-
|
|
1165
|
-
|
|
1511
|
+
"div",
|
|
1512
|
+
{ className: "dpdpa-qi-header" },
|
|
1513
|
+
title,
|
|
1514
|
+
applicability
|
|
1166
1515
|
),
|
|
1167
|
-
|
|
1516
|
+
subtitle,
|
|
1517
|
+
confidence,
|
|
1518
|
+
eduNote,
|
|
1519
|
+
areasSection,
|
|
1520
|
+
companySection,
|
|
1521
|
+
dataSection,
|
|
1522
|
+
emailBanner,
|
|
1168
1523
|
resetLink
|
|
1169
1524
|
);
|
|
1170
|
-
return el(
|
|
1525
|
+
return el(
|
|
1526
|
+
"div",
|
|
1527
|
+
{ className: "dpdpa-card dpdpa-card-wide" },
|
|
1528
|
+
header(brand),
|
|
1529
|
+
body,
|
|
1530
|
+
footer(brand)
|
|
1531
|
+
);
|
|
1171
1532
|
}
|
|
1172
1533
|
function renderError(brand, opts) {
|
|
1173
1534
|
const retryBtn = el(
|
|
@@ -1206,7 +1567,6 @@ var FormController = class {
|
|
|
1206
1567
|
this.pollHiddenSince = null;
|
|
1207
1568
|
this.pollHiddenTotalMs = 0;
|
|
1208
1569
|
this.pollResumePending = false;
|
|
1209
|
-
this.lastSubStatus = null;
|
|
1210
1570
|
this.consecutiveErrors = 0;
|
|
1211
1571
|
this.destroyed = false;
|
|
1212
1572
|
this.unsubscribe = null;
|
|
@@ -1219,7 +1579,7 @@ var FormController = class {
|
|
|
1219
1579
|
subStatus: "pending",
|
|
1220
1580
|
elapsedMs: 0,
|
|
1221
1581
|
jobId: null,
|
|
1222
|
-
|
|
1582
|
+
quickInsights: null,
|
|
1223
1583
|
errors: {},
|
|
1224
1584
|
generalError: null,
|
|
1225
1585
|
errorMessage: "",
|
|
@@ -1305,10 +1665,11 @@ var FormController = class {
|
|
|
1305
1665
|
pollTimeoutMs: this.getPollTimeout()
|
|
1306
1666
|
});
|
|
1307
1667
|
break;
|
|
1308
|
-
case "
|
|
1309
|
-
node =
|
|
1668
|
+
case "quick_insights":
|
|
1669
|
+
node = renderQuickInsights(this.brand, {
|
|
1310
1670
|
companyName: this.fields.company_name,
|
|
1311
|
-
|
|
1671
|
+
email: this.fields.email,
|
|
1672
|
+
insights: s.quickInsights,
|
|
1312
1673
|
onReset: () => this.resetToIdle()
|
|
1313
1674
|
});
|
|
1314
1675
|
break;
|
|
@@ -1316,7 +1677,7 @@ var FormController = class {
|
|
|
1316
1677
|
node = renderError(this.brand, {
|
|
1317
1678
|
message: s.errorMessage,
|
|
1318
1679
|
retryable: s.retryable,
|
|
1319
|
-
onRetry: () => this.
|
|
1680
|
+
onRetry: () => this.retry(),
|
|
1320
1681
|
onBack: () => {
|
|
1321
1682
|
var _a;
|
|
1322
1683
|
return this.backToIdle((_a = s.generalError) != null ? _a : s.errorMessage);
|
|
@@ -1416,7 +1777,8 @@ var FormController = class {
|
|
|
1416
1777
|
baseUrl: this.getBaseUrl(),
|
|
1417
1778
|
body: {
|
|
1418
1779
|
company_name: lead.company_name,
|
|
1419
|
-
company_domain: lead.company_domain
|
|
1780
|
+
company_domain: lead.company_domain,
|
|
1781
|
+
requested_by: lead.email
|
|
1420
1782
|
}
|
|
1421
1783
|
});
|
|
1422
1784
|
if (this.destroyed) return;
|
|
@@ -1449,7 +1811,6 @@ var FormController = class {
|
|
|
1449
1811
|
this.pollStartedAt = Date.now();
|
|
1450
1812
|
this.pollHiddenSince = null;
|
|
1451
1813
|
this.pollHiddenTotalMs = 0;
|
|
1452
|
-
this.lastSubStatus = null;
|
|
1453
1814
|
this.consecutiveErrors = 0;
|
|
1454
1815
|
this.store.setState({
|
|
1455
1816
|
phase: "polling",
|
|
@@ -1471,18 +1832,19 @@ var FormController = class {
|
|
|
1471
1832
|
this.pollTimer = setTimeout(() => this.pollTick(), interval);
|
|
1472
1833
|
}
|
|
1473
1834
|
getActiveElapsed() {
|
|
1474
|
-
|
|
1835
|
+
const hiddenInFlight = this.pollHiddenSince !== null ? Date.now() - this.pollHiddenSince : 0;
|
|
1836
|
+
return Date.now() - this.pollStartedAt - this.pollHiddenTotalMs - hiddenInFlight;
|
|
1475
1837
|
}
|
|
1476
1838
|
async pollTick() {
|
|
1477
|
-
var _a, _b
|
|
1839
|
+
var _a, _b;
|
|
1478
1840
|
if (this.destroyed) return;
|
|
1479
1841
|
const jobId = this.store.getState().jobId;
|
|
1480
1842
|
if (!jobId) return;
|
|
1481
1843
|
const activeElapsed = this.getActiveElapsed();
|
|
1482
1844
|
if (activeElapsed >= this.getPollTimeout()) {
|
|
1483
1845
|
this.showError(
|
|
1484
|
-
"
|
|
1485
|
-
|
|
1846
|
+
"Quick insights are taking longer than expected. Please try again.",
|
|
1847
|
+
true
|
|
1486
1848
|
);
|
|
1487
1849
|
this.emitError("Polling timed out", "timeout");
|
|
1488
1850
|
return;
|
|
@@ -1492,33 +1854,47 @@ var FormController = class {
|
|
|
1492
1854
|
if (this.destroyed) return;
|
|
1493
1855
|
this.consecutiveErrors = 0;
|
|
1494
1856
|
if ("status" in res && res.status === "error") {
|
|
1495
|
-
|
|
1496
|
-
this.
|
|
1857
|
+
const errShape = res;
|
|
1858
|
+
this.showError(errShape.message || "Report generation failed.", true);
|
|
1859
|
+
this.emitError(errShape.message || "Job errored", "poll");
|
|
1497
1860
|
return;
|
|
1498
1861
|
}
|
|
1499
|
-
|
|
1862
|
+
const inProgress = res;
|
|
1863
|
+
if (inProgress.quick_insights_status === "complete") {
|
|
1864
|
+
const insights = inProgress.quick_insights;
|
|
1865
|
+
if (!insights) {
|
|
1866
|
+
this.showError(
|
|
1867
|
+
"Quick insights are marked complete but the payload is missing. Please try again.",
|
|
1868
|
+
true
|
|
1869
|
+
);
|
|
1870
|
+
this.emitError(
|
|
1871
|
+
"Quick insights complete without payload",
|
|
1872
|
+
"poll"
|
|
1873
|
+
);
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1500
1876
|
const acceptedLead = this.makeLead(jobId);
|
|
1501
1877
|
saveLead(acceptedLead);
|
|
1502
1878
|
this.store.setState({
|
|
1503
|
-
phase: "
|
|
1504
|
-
|
|
1879
|
+
phase: "quick_insights",
|
|
1880
|
+
quickInsights: insights
|
|
1505
1881
|
});
|
|
1506
1882
|
try {
|
|
1507
|
-
(_b = (_a = this.options).
|
|
1883
|
+
(_b = (_a = this.options).onQuickInsightsReady) == null ? void 0 : _b.call(_a, insights, acceptedLead);
|
|
1508
1884
|
} catch (err) {
|
|
1509
|
-
console.error("
|
|
1885
|
+
console.error("onQuickInsightsReady handler threw:", err);
|
|
1510
1886
|
}
|
|
1511
1887
|
return;
|
|
1512
1888
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
}
|
|
1889
|
+
if (inProgress.quick_insights_status === "error") {
|
|
1890
|
+
this.showError(
|
|
1891
|
+
"We couldn't generate quick insights. Please try again.",
|
|
1892
|
+
true
|
|
1893
|
+
);
|
|
1894
|
+
this.emitError("Quick insights errored", "poll");
|
|
1895
|
+
return;
|
|
1521
1896
|
}
|
|
1897
|
+
const sub = (inProgress.status === "complete" ? "analysis_complete" : inProgress.status) || "pending";
|
|
1522
1898
|
this.store.setState({
|
|
1523
1899
|
phase: "polling",
|
|
1524
1900
|
subStatus: sub,
|
|
@@ -1552,8 +1928,13 @@ var FormController = class {
|
|
|
1552
1928
|
handleVisibilityChange() {
|
|
1553
1929
|
if (this.destroyed) return;
|
|
1554
1930
|
if (document.hidden) {
|
|
1555
|
-
if (this.store.getState().phase === "polling"
|
|
1556
|
-
this.pollHiddenSince = Date.now();
|
|
1931
|
+
if (this.store.getState().phase === "polling") {
|
|
1932
|
+
if (this.pollHiddenSince === null) this.pollHiddenSince = Date.now();
|
|
1933
|
+
if (this.pollTimer) {
|
|
1934
|
+
clearTimeout(this.pollTimer);
|
|
1935
|
+
this.pollTimer = null;
|
|
1936
|
+
}
|
|
1937
|
+
this.pollResumePending = true;
|
|
1557
1938
|
}
|
|
1558
1939
|
return;
|
|
1559
1940
|
}
|
|
@@ -1573,15 +1954,25 @@ var FormController = class {
|
|
|
1573
1954
|
retryable
|
|
1574
1955
|
});
|
|
1575
1956
|
}
|
|
1957
|
+
// Resume polling on the existing job_id when we already have one;
|
|
1958
|
+
// otherwise re-POST. Prevents duplicate email delivery when a transient
|
|
1959
|
+
// poll/timeout error is retried.
|
|
1960
|
+
retry() {
|
|
1961
|
+
const jobId = this.store.getState().jobId;
|
|
1962
|
+
if (jobId) {
|
|
1963
|
+
this.startPolling(jobId);
|
|
1964
|
+
} else {
|
|
1965
|
+
this.submit();
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1576
1968
|
resetToIdle() {
|
|
1577
1969
|
this.fields = { ...EMPTY_FIELDS };
|
|
1578
|
-
this.lastSubStatus = null;
|
|
1579
1970
|
this.store.setState({
|
|
1580
1971
|
phase: "idle",
|
|
1581
1972
|
errors: {},
|
|
1582
1973
|
generalError: null,
|
|
1583
1974
|
errorMessage: "",
|
|
1584
|
-
|
|
1975
|
+
quickInsights: null,
|
|
1585
1976
|
jobId: null,
|
|
1586
1977
|
subStatus: "pending",
|
|
1587
1978
|
elapsedMs: 0
|
|
@@ -1623,7 +2014,7 @@ var FormController = class {
|
|
|
1623
2014
|
};
|
|
1624
2015
|
|
|
1625
2016
|
// src/index.ts
|
|
1626
|
-
var version = "0.
|
|
2017
|
+
var version = "0.3.0";
|
|
1627
2018
|
var activeController = null;
|
|
1628
2019
|
function init(options) {
|
|
1629
2020
|
destroy();
|