kyd-shared-badge 0.2.10 → 0.2.12
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/package.json +1 -1
- package/src/SharedBadgeDisplay.tsx +18 -6
- package/src/components/AppendixTables.tsx +25 -9
- package/src/types.ts +6 -0
package/package.json
CHANGED
|
@@ -239,12 +239,24 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
239
239
|
<div className="space-y-8">
|
|
240
240
|
<div>
|
|
241
241
|
<h4 className={'text-xl font-bold mb-4'} style={{ color: 'var(--text-main)' }}>Sanctions & Watchlists</h4>
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
242
|
+
{(() => {
|
|
243
|
+
const ofacProvided = screening_sources.ofac_screen?.sources || [];
|
|
244
|
+
const lists = [...(screening_sources.ofac_lists || []), ...ofacProvided];
|
|
245
|
+
const seen: { [k: string]: boolean } = {};
|
|
246
|
+
const dedup: string[] = [];
|
|
247
|
+
for (let i = 0; i < lists.length; i++) {
|
|
248
|
+
const val = lists[i];
|
|
249
|
+
if (!seen[val]) { seen[val] = true; dedup.push(val); }
|
|
250
|
+
}
|
|
251
|
+
return (
|
|
252
|
+
<AppendixTables
|
|
253
|
+
type="sanctions"
|
|
254
|
+
sources={dedup}
|
|
255
|
+
searchedAt={updatedAt}
|
|
256
|
+
developerName={developerName || 'this developer'}
|
|
257
|
+
/>
|
|
258
|
+
);
|
|
259
|
+
})()}
|
|
248
260
|
</div>
|
|
249
261
|
<div>
|
|
250
262
|
<h4 className={'text-xl font-bold mb-4'} style={{ color: 'var(--text-main)' }}>Country-specific Entity Affiliations</h4>
|
|
@@ -6,6 +6,7 @@ import { DomainCSVRow } from '../types';
|
|
|
6
6
|
interface SanctionSource {
|
|
7
7
|
issuingEntity: string;
|
|
8
8
|
listName: string;
|
|
9
|
+
matched?: boolean;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
interface DomainSource {
|
|
@@ -25,7 +26,7 @@ interface AppendixTableProps {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionSource, searchedAt: string, developerName: string }) => (
|
|
28
|
-
<tr className={'transition-colors hover:bg-black/5'}>
|
|
29
|
+
<tr className={'transition-colors hover:bg-black/5'} style={source.matched ? { backgroundColor: 'rgba(236,102,98,0.08)' } : undefined}>
|
|
29
30
|
<td className={'px-4 py-4 whitespace-nowrap text-sm font-medium'} style={{ color: 'var(--text-main)' }}>
|
|
30
31
|
{source.issuingEntity}
|
|
31
32
|
</td>
|
|
@@ -36,12 +37,20 @@ const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionS
|
|
|
36
37
|
{searchedAt}
|
|
37
38
|
</td>
|
|
38
39
|
<td className={'px-4 py-4 whitespace-nowrap text-sm'} style={{ color: 'var(--text-secondary)' }}>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
{source.matched ? (
|
|
41
|
+
<span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'rgba(236,102,98,0.2)', color: 'var(--text-main)' }}>
|
|
42
|
+
Match
|
|
43
|
+
</span>
|
|
44
|
+
) : (
|
|
45
|
+
<span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' }}>
|
|
46
|
+
Not Found
|
|
47
|
+
</span>
|
|
48
|
+
)}
|
|
42
49
|
</td>
|
|
43
50
|
<td className={'px-4 py-4 text-sm whitespace-normal'} style={{ color: 'var(--text-secondary)' }}>
|
|
44
|
-
|
|
51
|
+
{source.matched
|
|
52
|
+
? (<span>Exact or strong match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)
|
|
53
|
+
: (<span>No exact match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)}
|
|
45
54
|
</td>
|
|
46
55
|
</tr>
|
|
47
56
|
);
|
|
@@ -77,9 +86,12 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
|
|
|
77
86
|
: ["Country", "Entity Type", "Entity/Domain", "Searched On", "Value", "Findings"];
|
|
78
87
|
|
|
79
88
|
const parsedSources = type === 'sanctions'
|
|
80
|
-
? (sources as
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
? (sources as any[]).map((src: any) => {
|
|
90
|
+
if (typeof src === 'string') {
|
|
91
|
+
const parts = src.split(':');
|
|
92
|
+
return { issuingEntity: parts[0].trim(), listName: parts.slice(1).join(':').trim(), matched: false } as SanctionSource;
|
|
93
|
+
}
|
|
94
|
+
return src as SanctionSource;
|
|
83
95
|
})
|
|
84
96
|
: (sources as DomainCSVRow[]).map(s => ({
|
|
85
97
|
country: s.Country,
|
|
@@ -88,7 +100,11 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
|
|
|
88
100
|
url: s.URL,
|
|
89
101
|
}));
|
|
90
102
|
|
|
91
|
-
const
|
|
103
|
+
const sortedParsedSources = (type === 'sanctions')
|
|
104
|
+
? (parsedSources as SanctionSource[]).slice().sort((a, b) => (b.matched === true ? 1 : 0) - (a.matched === true ? 1 : 0))
|
|
105
|
+
: parsedSources;
|
|
106
|
+
|
|
107
|
+
const visibleParsedSources = sortedParsedSources.slice(0, visibleCount);
|
|
92
108
|
|
|
93
109
|
const handleLoadMore = () => {
|
|
94
110
|
setVisibleCount(currentCount => currentCount + PAGE_SIZE);
|
package/src/types.ts
CHANGED
|
@@ -156,6 +156,12 @@ export interface AssessmentResult {
|
|
|
156
156
|
risk_profile_domains: DomainCSVRow[];
|
|
157
157
|
additional_watchlists?: string[];
|
|
158
158
|
ip_risk_analysis?: IpRiskAnalysis;
|
|
159
|
+
ofac_screen?: {
|
|
160
|
+
checked?: boolean;
|
|
161
|
+
sources?: string[];
|
|
162
|
+
matches?: any[];
|
|
163
|
+
};
|
|
164
|
+
sanctions_sources_detailed?: { issuingEntity: string; listName: string; matched?: boolean }[];
|
|
159
165
|
};
|
|
160
166
|
optOutScreening?: boolean;
|
|
161
167
|
clientMetadata?: ClientMetadata;
|