diff --git a/packages/app-builder/src/components/Sanctions/EntityProperties.tsx b/packages/app-builder/src/components/Sanctions/EntityProperties.tsx new file mode 100644 index 000000000..5799af5c9 --- /dev/null +++ b/packages/app-builder/src/components/Sanctions/EntityProperties.tsx @@ -0,0 +1,100 @@ +import { + createPropertyTransformer, + getSanctionEntityProperties, + type PropertyForSchema, + type SanctionCheckEntityProperty, +} from '@app-builder/constants/sanction-check-entity'; +import { type OpenSanctionEntity } from '@app-builder/models/sanction-check'; +import { useFormatLanguage } from '@app-builder/utils/format'; +import { Fragment, type ReactNode, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { sanctionsI18n } from './sanctions-i18n'; + +export function EntityProperties({ + entity, + forcedProperties, + showUnavailable = false, + before, + after, +}: { + entity: T; + forcedProperties?: PropertyForSchema[]; + showUnavailable?: boolean; + before?: ReactNode; + after?: ReactNode; +}) { + const [displayAll, setDisplayAll] = useState< + Partial> + >({}); + + const displayProperties = forcedProperties ?? getSanctionEntityProperties(entity.schema); + const { t, i18n } = useTranslation(sanctionsI18n); + const language = useFormatLanguage(); + const entityPropertyList = displayProperties + .map((property) => { + const items = entity.properties[property] ?? []; + const itemsToDisplay = displayAll[property] ? items : items.slice(0, 5); + return { + property, + values: itemsToDisplay, + restItemsCount: Math.max(0, items.length - itemsToDisplay.length), + }; + }) + .filter((prop) => (showUnavailable ? true : prop.values.length > 0)); + + const TransformProperty = useMemo( + () => + createPropertyTransformer({ + language: i18n.language, + formatLanguage: language, + }), + [i18n.language, language], + ); + + const handleShowMore = (prop: string) => { + setDisplayAll((prev) => ({ ...prev, [prop]: true })); + }; + + return ( +
+ {before} + {entityPropertyList.map(({ property, values, restItemsCount }) => { + return ( + + {t(`sanctions:entity.property.${property}`)} + + {values.length > 0 ? ( + <> + {values.map((v, i) => ( + + + {i === values.length - 1 ? null : ·} + + ))} + {restItemsCount > 0 ? ( + <> + · + + + ) : null} + + ) : ( + not available + )} + + + ); + })} + {after} +
+ ); +} diff --git a/packages/app-builder/src/components/Sanctions/MatchCard.tsx b/packages/app-builder/src/components/Sanctions/MatchCard.tsx index 7b5f39a62..4cdd35eae 100644 --- a/packages/app-builder/src/components/Sanctions/MatchCard.tsx +++ b/packages/app-builder/src/components/Sanctions/MatchCard.tsx @@ -1,5 +1,6 @@ import { type SanctionCheckMatch } from '@app-builder/models/sanction-check'; import { SanctionCheckReviewModal } from '@app-builder/routes/ressources+/cases+/review-sanction-match'; +import { EnrichMatchButton } from '@app-builder/routes/ressources+/sanction-check+/enrich-match.$matchId'; import { useOrganizationUsers } from '@app-builder/services/organization/organization-users'; import { getFullName } from '@app-builder/services/user'; import { formatDateTime, useFormatLanguage } from '@app-builder/utils/format'; @@ -34,7 +35,7 @@ export const MatchCard = ({ match, readonly, unreviewable, defaultOpen }: MatchC
-
+
+ {!match.enriched ? ( +
+ +
+ ) : null}
{unreviewable ? ( diff --git a/packages/app-builder/src/components/Sanctions/MatchDetails.tsx b/packages/app-builder/src/components/Sanctions/MatchDetails.tsx index fd2f708cd..3c5d657a9 100644 --- a/packages/app-builder/src/components/Sanctions/MatchDetails.tsx +++ b/packages/app-builder/src/components/Sanctions/MatchDetails.tsx @@ -1,83 +1,83 @@ +import { type PropertyForSchema } from '@app-builder/constants/sanction-check-entity'; import { - createPropertyTransformer, - getSanctionEntityProperties, - type SanctionCheckEntityProperty, -} from '@app-builder/constants/sanction-check-entity'; -import { type SanctionCheckMatch } from '@app-builder/models/sanction-check'; -import { useFormatLanguage } from '@app-builder/utils/format'; -import { Fragment, useMemo, useState } from 'react'; + type SanctionCheckMatch, + type SanctionCheckSanctionEntity, +} from '@app-builder/models/sanction-check'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { ModalV2 } from 'ui-design-system'; +import { Icon } from 'ui-icons'; +import { EntityProperties } from './EntityProperties'; import { sanctionsI18n } from './sanctions-i18n'; export type MatchDetailsProps = { entity: SanctionCheckMatch['payload']; }; -export function MatchDetails({ entity }: MatchDetailsProps) { - const { t, i18n } = useTranslation(sanctionsI18n); - const language = useFormatLanguage(); - const [displayAll, setDisplayAll] = useState< - Partial> - >({}); +const sanctionProps = [ + 'country', + 'authority', + 'authorityId', + 'startDate', + 'endDate', + 'listingDate', + 'program', + 'programId', + 'programUrl', + 'summary', + 'reason', + 'sourceUrl', +] satisfies PropertyForSchema<'Sanction'>[]; - const TransformProperty = useMemo( - () => - createPropertyTransformer({ - language: i18n.language, - formatLanguage: language, - }), - [i18n.language, language], +export function MatchDetails({ entity }: MatchDetailsProps) { + const { t } = useTranslation(sanctionsI18n); + const [selectedSanction, setSelectedSanction] = useState( + null, ); - const displayProperties = getSanctionEntityProperties(entity.schema); - const entityPropertyList = displayProperties - .map((property) => { - const items = entity.properties[property] ?? []; - const itemsToDisplay = displayAll[property] ? items : items.slice(0, 5); - return { - property, - values: itemsToDisplay, - restItemsCount: Math.max(0, items.length - itemsToDisplay.length), - }; - }) - .filter((prop) => prop.values.length > 0); - - const handleShowMore = (prop: string) => { - setDisplayAll((prev) => ({ ...prev, [prop]: true })); - }; - return ( -
- {entityPropertyList.map(({ property, values, restItemsCount }) => { - return ( - - {t(`sanctions:entity.property.${property}`)} - - {values.map((v, i) => ( - - - {i === values.length - 1 ? null : ·} - - ))} - {restItemsCount > 0 ? ( - <> - · - - - ) : null} - - - ); - })} + {sanction.properties['authority']} + +
+ ))} +
+ + setSelectedSanction(null)} + size="large" + className="max-h-[80vh]" + > + {t('sanctions:sanction_detail.title')} +
+ {selectedSanction ? ( + + ) : null} +
+
+ + ) : null + } + />
); } diff --git a/packages/app-builder/src/constants/sanction-check-entity.tsx b/packages/app-builder/src/constants/sanction-check-entity.tsx index 8c2a4c06c..7dbc6a07d 100644 --- a/packages/app-builder/src/constants/sanction-check-entity.tsx +++ b/packages/app-builder/src/constants/sanction-check-entity.tsx @@ -1,13 +1,13 @@ import { ExternalLink } from '@app-builder/components/ExternalLink'; -import { type SanctionCheckEntitySchema } from '@app-builder/models/sanction-check'; +import { type OpenSanctionEntitySchema } from '@app-builder/models/sanction-check'; export type PropertyDataType = 'string' | 'country' | 'url' | 'date' | 'wikidataId'; export type PropertyForSchema< - Schema extends SanctionCheckEntitySchema, + Schema extends OpenSanctionEntitySchema, _R = never, > = (typeof schemaInheritence)[Schema] extends null ? _R | (typeof schemaProperties)[Schema][number] - : (typeof schemaInheritence)[Schema] extends infer P extends SanctionCheckEntitySchema + : (typeof schemaInheritence)[Schema] extends infer P extends OpenSanctionEntitySchema ? PropertyForSchema : never; @@ -88,7 +88,21 @@ export const schemaProperties = { Vehicle: ['registrationNumber'] as const, Airplane: [] as const, Vessel: [] as const, -} satisfies Record; + Sanction: [ + 'country', + 'authority', + 'authorityId', + 'program', + 'startDate', + 'endDate', + 'listingDate', + 'sourceUrl', + 'reason', + 'summary', + 'programId', + 'programUrl', + ] as const, +} satisfies Record; export type SanctionCheckEntityProperty = (typeof schemaProperties)[keyof typeof schemaProperties][number]; @@ -102,7 +116,8 @@ const schemaInheritence = { Vehicle: 'Thing', Vessel: 'Vehicle', Airplane: 'Vehicle', -} satisfies Record; + Sanction: null, +} satisfies Record; const propertyMetadata = { address: { type: 'string' }, @@ -170,10 +185,18 @@ const propertyMetadata = { website: { type: 'url' }, weight: { type: 'string' }, wikidataId: { type: 'wikidataId' }, + authority: { type: 'string' }, + authorityId: { type: 'string' }, + startDate: { type: 'date' }, + endDate: { type: 'date' }, + programId: { type: 'string' }, + programUrl: { type: 'url' }, + reason: { type: 'string' }, + listingDate: { type: 'date' }, } satisfies Record; -export function getSanctionEntityProperties(schema: SanctionCheckEntitySchema) { - let currentSchema: SanctionCheckEntitySchema | null = schema; +export function getSanctionEntityProperties(schema: OpenSanctionEntitySchema) { + let currentSchema: OpenSanctionEntitySchema | null = schema; const properties: SanctionCheckEntityProperty[] = []; do { diff --git a/packages/app-builder/src/locales/ar/sanctions.json b/packages/app-builder/src/locales/ar/sanctions.json index fb50086f6..36b358564 100644 --- a/packages/app-builder/src/locales/ar/sanctions.json +++ b/packages/app-builder/src/locales/ar/sanctions.json @@ -117,5 +117,18 @@ "error_label_one": "التحقق من العقوبة خطأ للسبب التالي", "error_label_others": "فحص العقوبة خطأ للأسباب التالية", "match.not_reviewable": "غير قابل للمراجعة", - "refine_modal.search_input_label": "يغطي البحث الحقول التالية:" + "refine_modal.search_input_label": "يغطي البحث الحقول التالية:", + "entity.property.authority": "سلطة", + "entity.property.authorityId": "المعرف الصادر عن السلطة", + "entity.property.endDate": "تاريخ الانتهاء", + "entity.property.listingDate": "تاريخ الإدراج", + "entity.property.programId": "معرف البرنامج", + "entity.property.programUrl": "برنامج URL", + "entity.property.reason": "سبب", + "entity.property.startDate": "تاريخ البدء", + "enrich_button": "إثراء", + "entity.property.sanctions": "العقوبات", + "sanction_detail.title": "تفاصيل العقوبات", + "error.match_already_enriched": "تطابق المخصب بالفعل", + "success.match_enriched": "تطابق المباراة بنجاح" } diff --git a/packages/app-builder/src/locales/en/sanctions.json b/packages/app-builder/src/locales/en/sanctions.json index 654a73c97..6b8eeecc6 100644 --- a/packages/app-builder/src/locales/en/sanctions.json +++ b/packages/app-builder/src/locales/en/sanctions.json @@ -109,6 +109,15 @@ "entity.property.hairColor": "Hair color", "entity.property.appearance": "Appearance", "entity.property.political": "Political association", + "entity.property.sanctions": "Sanctions", + "entity.property.programId": "Program ID", + "entity.property.programUrl": "Program URL", + "entity.property.authority": "Authority", + "entity.property.authorityId": "Authority-issued Identifier", + "entity.property.startDate": "Start date", + "entity.property.endDate": "End date", + "entity.property.listingDate": "Listing date", + "entity.property.reason": "Reason", "entity.schema.airplane": "Airplane", "entity.schema.company": "Company", "entity.schema.person": "Person", @@ -117,5 +126,9 @@ "entity.schema.legalentity": "Legal Entity", "entity.schema.vehicle": "Vehicle", "entity.schema.vessel": "Vessel", - "refine_modal.schema.legalentity": "Legal Entity" + "refine_modal.schema.legalentity": "Legal Entity", + "sanction_detail.title": "Sanction details", + "enrich_button": "Enrich", + "success.match_enriched": "Match successfully enriched", + "error.match_already_enriched": "Match already enriched" } diff --git a/packages/app-builder/src/locales/fr/sanctions.json b/packages/app-builder/src/locales/fr/sanctions.json index 3e77a3f32..506118aab 100644 --- a/packages/app-builder/src/locales/fr/sanctions.json +++ b/packages/app-builder/src/locales/fr/sanctions.json @@ -80,7 +80,7 @@ "refine_modal.apply_search": "Appliquer les modifications", "refine_modal.back_search": "Retour à la recherche", "refine_modal.refine_callout": "En appliquant cette recherche, le filtrage des sanction sera mis à jour pour afficher uniquement la correspondance possible visible ci-dessus.", - "refine_modal.result_label": "Matchs possibles avec votre recherche:", + "refine_modal.result_label": "Correspondances possibles avec votre recherche:", "refine_modal.schema.company": "Entreprise", "refine_modal.schema.legalentity": "Entité légale", "refine_modal.schema.thing": "Je ne sais pas", @@ -102,7 +102,7 @@ "review_modal.title": "Modifier l'état de la correspondance", "review_modal.confirmation": "Confirmation", "review_modal.whitelist_label": "Ne plus alerter si ce profil est associé à:", - "callout.needs_review": "{{toreview}} / {{totalmatches}} à examiner", + "callout.needs_review": "{{toReview}}/{{totalMatches}} à examiner", "entity.schema.vehicle": "Véhicule", "refine_modal.no_match_callout": "En appliquant cette recherche, le filtrage de sanction sera défini comme suit: ", "refine_modal.no_match_label": "Aucune correspondance possible n'a été trouvée avec votre recherche.", @@ -117,5 +117,18 @@ "error_label_one": "Le filtrage de sanction est erronée pour la raison suivante", "error_label_others": "Le filtrage de sanction est erronée pour les raisons suivantes", "match.not_reviewable": "Non révisable", - "refine_modal.search_input_label": "La recherche couvre les champs suivants:" + "refine_modal.search_input_label": "La recherche couvre les champs suivants:", + "entity.property.authority": "Autorité", + "entity.property.authorityId": "Identifiant émis par l'autorité", + "entity.property.endDate": "Date de fin", + "entity.property.listingDate": "Date d'inscription", + "entity.property.programId": "ID du programme", + "entity.property.programUrl": "URL du programme", + "entity.property.reason": "Raison", + "entity.property.startDate": "Date de début", + "enrich_button": "Enrichir", + "entity.property.sanctions": "Sanctions", + "sanction_detail.title": "Détails de sanction", + "error.match_already_enriched": "Correspondance déjà enrichie", + "success.match_enriched": "Correspondance enrichie avec succès" } diff --git a/packages/app-builder/src/models/sanction-check.ts b/packages/app-builder/src/models/sanction-check.ts index b404906b1..7ea6dae0f 100644 --- a/packages/app-builder/src/models/sanction-check.ts +++ b/packages/app-builder/src/models/sanction-check.ts @@ -8,7 +8,7 @@ import { } from 'marble-api'; import * as R from 'remeda'; -const entitySchemas = [ +const matchEntitySchemas = [ 'Thing', 'LegalEntity', 'Person', @@ -18,22 +18,53 @@ const entitySchemas = [ 'Airplane', 'Vessel', ] as const; +const sanctionEntitySchemas = ['Sanction'] as const; +export const openSanctionEntitySchemas = [...matchEntitySchemas, ...sanctionEntitySchemas] as const; export type SanctionCheckStatus = 'in_review' | 'confirmed_hit' | 'no_hit' | 'error'; export type SanctionCheckMatchStatus = 'pending' | 'confirmed_hit' | 'no_hit' | 'skipped'; -export type SanctionCheckEntitySchema = (typeof entitySchemas)[number]; +export type OpenSanctionEntitySchema = (typeof openSanctionEntitySchemas)[number]; + +export type OpenSanctionEntity = { + id: string; + schema: OpenSanctionEntitySchema; + properties: Record; +}; + +export type SanctionCheckSanctionEntity = { + id: string; + schema: 'Sanction'; + properties: Record; +}; + +export type SanctionCheckMatchEntitySchema = Extract< + OpenSanctionEntitySchema, + | 'Thing' + | 'LegalEntity' + | 'Person' + | 'Organization' + | 'Company' + | 'Vehicle' + | 'Airplane' + | 'Vessel' +>; export type SanctionCheckMatchPayload = { id: string; match: boolean; score: number; - schema: SanctionCheckEntitySchema; + schema: SanctionCheckMatchEntitySchema; caption: string; - properties: Record; + properties: { + sanctions?: SanctionCheckSanctionEntity[]; + } & Record; }; -function isKnownEntitySchema(schema: string): schema is SanctionCheckEntitySchema { - return (entitySchemas as ReadonlyArray).includes(schema); +function isKnownEntitySchema( + schema: string, + schemaList: readonly K[], +): schema is K { + return (schemaList as ReadonlyArray).includes(schema); } export function adapatSanctionCheckMatchPayload( @@ -41,7 +72,7 @@ export function adapatSanctionCheckMatchPayload( ): SanctionCheckMatchPayload { return { ...dto, - schema: isKnownEntitySchema(dto.schema) ? dto.schema : 'Thing', + schema: isKnownEntitySchema(dto.schema, matchEntitySchemas) ? dto.schema : 'Thing', }; } @@ -50,6 +81,7 @@ export type SanctionCheckMatch = { entityId: string; queryIds: string[]; status: SanctionCheckMatchStatus; + enriched: boolean; // datasets: unknown[]; uniqueCounterpartyIdentifier?: string; payload: SanctionCheckMatchPayload; @@ -67,6 +99,7 @@ export function adaptSanctionCheckMatch(dto: SanctionCheckMatchDto): SanctionChe entityId: dto.entity_id, queryIds: dto.query_ids, status: dto.status, + enriched: dto.enriched, payload: adapatSanctionCheckMatchPayload(dto.payload), uniqueCounterpartyIdentifier: dto.unique_counterparty_identifier, comments: R.map(dto.comments, (comment) => ({ @@ -79,7 +112,7 @@ export function adaptSanctionCheckMatch(dto: SanctionCheckMatchDto): SanctionChe } export type SanctionCheckQuery = { - schema: SanctionCheckEntitySchema; + schema: OpenSanctionEntitySchema; properties: { [key: string]: string[]; }; @@ -96,7 +129,7 @@ export type SanctionCheckRequest = { function adaptQueries(dto: SanctionCheckRequestDto['search_input']['queries']) { return R.mapValues(dto, (value) => { return { - schema: isKnownEntitySchema(value.schema) ? value.schema : 'Thing', + schema: isKnownEntitySchema(value.schema, matchEntitySchemas) ? value.schema : 'Thing', properties: value.properties, }; }); diff --git a/packages/app-builder/src/repositories/SanctionCheckRepository.ts b/packages/app-builder/src/repositories/SanctionCheckRepository.ts index 7e3b137ac..1fa4e0ac9 100644 --- a/packages/app-builder/src/repositories/SanctionCheckRepository.ts +++ b/packages/app-builder/src/repositories/SanctionCheckRepository.ts @@ -4,8 +4,8 @@ import { adapatSanctionCheckMatchPayload, adaptSanctionCheck, adaptSanctionCheckMatch, + type OpenSanctionEntitySchema, type SanctionCheck, - type SanctionCheckEntitySchema, type SanctionCheckFile, type SanctionCheckMatch, type SanctionCheckMatchPayload, @@ -31,15 +31,16 @@ export interface SanctionCheckRepository { }): Promise; searchSanctionCheckMatches(args: { decisionId: string; - entityType: SanctionCheckEntitySchema; + entityType: OpenSanctionEntitySchema; fields: Record; }): Promise; refineSanctionCheck(args: { decisionId: string; - entityType: SanctionCheckEntitySchema; + entityType: OpenSanctionEntitySchema; fields: Record; }): Promise; listSanctionCheckFiles(args: { sanctionCheckId: string }): Promise; + enrichMatch(args: { matchId: string }): Promise; } export function makeGetSanctionCheckRepository() { @@ -89,5 +90,8 @@ export function makeGetSanctionCheckRepository() { adapatSanctionCheckFile, ); }, + enrichMatch: async ({ matchId }) => { + return adaptSanctionCheckMatch(await marbleCoreApiClient.enrichSanctionCheckMatch(matchId)); + }, }); } diff --git a/packages/app-builder/src/routes/_builder+/scenarios+/$scenarioId+/i+/$iterationId+/sanction.tsx b/packages/app-builder/src/routes/_builder+/scenarios+/$scenarioId+/i+/$iterationId+/sanction.tsx index b1673876f..ef55c710e 100644 --- a/packages/app-builder/src/routes/_builder+/scenarios+/$scenarioId+/i+/$iterationId+/sanction.tsx +++ b/packages/app-builder/src/routes/_builder+/scenarios+/$scenarioId+/i+/$iterationId+/sanction.tsx @@ -24,7 +24,7 @@ import { useEditorMode } from '@app-builder/services/editor'; import { OptionsProvider } from '@app-builder/services/editor/options'; import { serverServices } from '@app-builder/services/init.server'; import { getRoute } from '@app-builder/utils/routes'; -import { fromParams, fromUUID, useParam } from '@app-builder/utils/short-uuid'; +import { fromParams, fromUUID, toUUID, useParam } from '@app-builder/utils/short-uuid'; import * as Ariakit from '@ariakit/react'; import { type ActionFunctionArgs, json, type LoaderFunctionArgs } from '@remix-run/node'; import { useFetcher, useLoaderData } from '@remix-run/react'; @@ -275,6 +275,7 @@ export default function SanctionDetail() { + {toUUID('pQ323VAW6WpSSrfJL7QU5r')}
{ diff --git a/packages/app-builder/src/routes/ressources+/sanction-check+/enrich-match.$matchId.tsx b/packages/app-builder/src/routes/ressources+/sanction-check+/enrich-match.$matchId.tsx new file mode 100644 index 000000000..d102e0afa --- /dev/null +++ b/packages/app-builder/src/routes/ressources+/sanction-check+/enrich-match.$matchId.tsx @@ -0,0 +1,87 @@ +import { setToastMessage } from '@app-builder/components/MarbleToaster'; +import { sanctionsI18n } from '@app-builder/components/Sanctions/sanctions-i18n'; +import { isStatusConflictHttpError } from '@app-builder/models'; +import { serverServices } from '@app-builder/services/init.server'; +import { useCallbackRef } from '@app-builder/utils/hooks'; +import { getRoute } from '@app-builder/utils/routes'; +import { fromParams, fromUUID } from '@app-builder/utils/short-uuid'; +import { type ActionFunctionArgs } from '@remix-run/node'; +import { useFetcher } from '@remix-run/react'; +import { useTranslation } from 'react-i18next'; +import { Button } from 'ui-design-system'; +import { Icon } from 'ui-icons'; + +export async function action({ request, params }: ActionFunctionArgs) { + const { + authService, + i18nextService: { getFixedT }, + toastSessionService: { getSession, commitSession }, + } = serverServices; + const { sanctionCheck } = await authService.isAuthenticated(request, { + failureRedirect: getRoute('/sign-in'), + }); + const matchId = fromParams(params, 'matchId'); + + const session = await getSession(request); + const t = await getFixedT(request, ['common', 'sanctions']); + + try { + const match = await sanctionCheck.enrichMatch({ matchId }); + + setToastMessage(session, { + type: 'success', + message: t('sanctions:success.match_enriched'), + }); + + return Response.json( + { + match, + }, + { + headers: { 'Set-Cookie': await commitSession(session) }, + }, + ); + } catch (error) { + let message: string; + if (isStatusConflictHttpError(error)) { + message = t('sanctions:error.match_already_enriched'); + } else { + message = t('common:errors.unknown'); + } + + setToastMessage(session, { + type: 'error', + message, + }); + + return Response.json( + { match: null }, + { + headers: { 'Set-Cookie': await commitSession(session) }, + }, + ); + } +} + +export function EnrichMatchButton({ matchId }: { matchId: string }) { + const { t } = useTranslation(sanctionsI18n); + const fetcher = useFetcher(); + const handleButtonClick = useCallbackRef(() => { + fetcher.submit( + {}, + { + method: 'POST', + action: getRoute('/ressources/sanction-check/enrich-match/:matchId', { + matchId: fromUUID(matchId), + }), + }, + ); + }); + + return ( + + ); +} diff --git a/packages/app-builder/src/utils/routes/routes.ts b/packages/app-builder/src/utils/routes/routes.ts index 156cdfaa3..ad2f6b67f 100644 --- a/packages/app-builder/src/utils/routes/routes.ts +++ b/packages/app-builder/src/utils/routes/routes.ts @@ -494,6 +494,11 @@ export const routes = [ "path": "ressources/rule-snoozes/read/:ruleSnoozeId", "file": "routes/ressources+/rule-snoozes+/read.$ruleSnoozeId.tsx" }, + { + "id": "routes/ressources+/sanction-check+/enrich-match.$matchId", + "path": "ressources/sanction-check/enrich-match/:matchId", + "file": "routes/ressources+/sanction-check+/enrich-match.$matchId.tsx" + }, { "id": "routes/ressources+/sanction-check+/refine", "path": "ressources/sanction-check/refine", @@ -594,11 +599,6 @@ export const routes = [ "path": "ressources/settings/api-keys/delete", "file": "routes/ressources+/settings+/api-keys+/delete.tsx" }, - { - "id": "routes/ressources+/settings+/edit-org-default-timezone", - "path": "ressources/settings/edit-org-default-timezone", - "file": "routes/ressources+/settings+/edit-org-default-timezone.tsx" - }, { "id": "routes/ressources+/settings+/inboxes+/create", "path": "ressources/settings/inboxes/create", diff --git a/packages/app-builder/src/utils/routes/types.ts b/packages/app-builder/src/utils/routes/types.ts index 6dedf6832..f73c57f42 100644 --- a/packages/app-builder/src/utils/routes/types.ts +++ b/packages/app-builder/src/utils/routes/types.ts @@ -78,6 +78,7 @@ export type RoutePath = | '/ressources/lists/value_delete' | '/ressources/locales' | '/ressources/rule-snoozes/read/:ruleSnoozeId' + | '/ressources/sanction-check/enrich-match/:matchId' | '/ressources/sanction-check/refine' | '/ressources/sanction-check/search' | '/ressources/scenarios/:scenarioId/:iterationId/activate' @@ -98,7 +99,6 @@ export type RoutePath = | '/ressources/scenarios/update' | '/ressources/settings/api-keys/create' | '/ressources/settings/api-keys/delete' - | '/ressources/settings/edit-org-default-timezone' | '/ressources/settings/inboxes/create' | '/ressources/settings/inboxes/delete' | '/ressources/settings/inboxes/inbox-users/create' @@ -222,6 +222,7 @@ export type RouteID = | 'routes/ressources+/lists+/value_delete' | 'routes/ressources+/locales' | 'routes/ressources+/rule-snoozes+/read.$ruleSnoozeId' + | 'routes/ressources+/sanction-check+/enrich-match.$matchId' | 'routes/ressources+/sanction-check+/refine' | 'routes/ressources+/sanction-check+/search' | 'routes/ressources+/scenarios+/$scenarioId+/$iterationId+/activate' @@ -242,7 +243,6 @@ export type RouteID = | 'routes/ressources+/scenarios+/update' | 'routes/ressources+/settings+/api-keys+/create' | 'routes/ressources+/settings+/api-keys+/delete' - | 'routes/ressources+/settings+/edit-org-default-timezone' | 'routes/ressources+/settings+/inboxes+/create' | 'routes/ressources+/settings+/inboxes+/delete' | 'routes/ressources+/settings+/inboxes+/inbox-users.create' diff --git a/packages/app-builder/vite.config.ts b/packages/app-builder/vite.config.ts index cfec48dc9..d0d75cdf3 100644 --- a/packages/app-builder/vite.config.ts +++ b/packages/app-builder/vite.config.ts @@ -1,13 +1,10 @@ import { vitePlugin as remix } from '@remix-run/dev'; -import { installGlobals } from '@remix-run/node'; import { sentryVitePlugin } from '@sentry/vite-plugin'; import { remixDevTools } from 'remix-development-tools'; import { flatRoutes } from 'remix-flat-routes'; import { defineConfig, type PluginOption } from 'vite'; import viteTsConfigPaths from 'vite-tsconfig-paths'; -installGlobals(); - const isSentryConfigured = !!process.env['SENTRY_AUTH_TOKEN']; const appDirectory = 'src'; diff --git a/packages/marble-api/openapis/marblecore-api/_schemas.yml b/packages/marble-api/openapis/marblecore-api/_schemas.yml index b9e3e448d..008f71ec5 100644 --- a/packages/marble-api/openapis/marblecore-api/_schemas.yml +++ b/packages/marble-api/openapis/marblecore-api/_schemas.yml @@ -190,6 +190,8 @@ SanctionCheckErrorDto: $ref: sanction-checks.yml#/components/schemas/SanctionCheckErrorDto SanctionCheckFileDto: $ref: sanction-checks.yml#/components/schemas/SanctionCheckFileDto +SanctionCheckSanctionEntityDto: + $ref: sanction-checks.yml#/components/schemas/SanctionCheckSanctionEntityDto SanctionCheckMatchPayloadDto: $ref: sanction-checks.yml#/components/schemas/SanctionCheckMatchPayloadDto SanctionCheckMatchDto: diff --git a/packages/marble-api/openapis/marblecore-api/sanction-checks.yml b/packages/marble-api/openapis/marblecore-api/sanction-checks.yml index a63e0b1ce..fc24d1a49 100644 --- a/packages/marble-api/openapis/marblecore-api/sanction-checks.yml +++ b/packages/marble-api/openapis/marblecore-api/sanction-checks.yml @@ -338,6 +338,25 @@ components: created_at: type: string format: date-time + SanctionCheckSanctionEntityDto: + type: object + required: + - id + - schema + - properties + properties: + id: + type: string + schema: + type: string + enum: ['Sanction'] + properties: + type: object + additionalProperties: + type: array + items: + type: string + SanctionCheckMatchPayloadDto: type: object required: @@ -359,11 +378,18 @@ components: caption: type: string properties: - type: object - additionalProperties: - type: array - items: - type: string + allOf: + - type: object + properties: + sanctions: + type: array + items: + $ref: '#/components/schemas/SanctionCheckSanctionEntityDto' + - type: object + additionalProperties: + type: array + items: + type: string SanctionCheckMatchDto: type: object required: diff --git a/packages/marble-api/src/generated/marblecore-api.ts b/packages/marble-api/src/generated/marblecore-api.ts index 72bb9b37e..56c93d9ce 100644 --- a/packages/marble-api/src/generated/marblecore-api.ts +++ b/packages/marble-api/src/generated/marblecore-api.ts @@ -492,6 +492,13 @@ export type SanctionCheckRequestDto = { }; }; }; +export type SanctionCheckSanctionEntityDto = { + id: string; + schema: "Sanction"; + properties: { + [key: string]: string[]; + }; +}; export type SanctionCheckMatchPayloadDto = { id: string; match: boolean; @@ -499,6 +506,8 @@ export type SanctionCheckMatchPayloadDto = { schema: SanctionCheckEntityDto; caption: string; properties: { + sanctions?: SanctionCheckSanctionEntityDto[]; + } & { [key: string]: string[]; }; };