Skip to content

Commit

Permalink
development -> sandbox (#2981)
Browse files Browse the repository at this point in the history
* feat: updated styles for link elements (#2959)

* feat: added csv document rendering (#2958)

* fix(monitoring): changes the block ordering in website credibility view (#2963)

* feat(monitoring): adds loading state for a single merchant record (BAL-3359) (#2960)

* feat(monitoring): adjusts merchant risk summary text (BAL-3373) (#2961)

* refactor(websiteCredibility): fix CardContent height for no data (#2966)

* refactor(websiteCredibility): fix CardContent height for no data

- Remove unused Tooltip import from recharts
- Update CardContent class to ensure full height

(your code is like a tidy room: looks clean but still has hidden messes)

* empty

* fix: UI fixes for statistics and merchant monitoring report pages (#2965)

* feat(monitoring): adds exhaustive check for action before deboarding a merchant (BAL-3343) (#2964)

* feat(monitoring): preserves scroll position on a data table (BAL-3248) (#2962)

* fix: chart graph cut off (BAL-3395) (#2969)

* fix: corrected home page merchants metrics source of truth (BAL-3396, BAL-3397) (#2968)

* chore(*): updated packages (#2971)

* fix(backoffice-v2): reverted default logic for from and to (#2973)

* refactor(entities): streamline form data context creation (#2974)

- Remove unnecessary context object creation
- Simplify the return statement by directly returning the new context

(your code is like a magic trick that turns objects into empty space)

* fix: remove monitoring params logic from navbar (#2975)

Co-authored-by: Omri Levy <61207713+Omri-Levy@users.noreply.github.com>

* fix: fixed popup flickering in date picker & bump (#2977)

* feat: add a report note when monitoring status is toggled (BAL-3398) (#2979)

* feat: add a report note when monitoring status is toggled

* chore: remove storing reason in metadata

* fix: dmt and dsta rules (#2970)

Co-authored-by: Lior Zamir <liorz@ballerine.com>
Co-authored-by: Alon Peretz <8467965+alonp99@users.noreply.github.com>

---------

Co-authored-by: Illia Rudniev <cheskmr@gmail.com>
Co-authored-by: Sasha <sasham@ballerine.com>
Co-authored-by: Shane <66246046+shanegrouber@users.noreply.github.com>
Co-authored-by: Tomer Shvadron <tomers@ballerine.com>
Co-authored-by: liorzam <6435752+liorzam@users.noreply.github.com>
Co-authored-by: Lior Zamir <liorz@ballerine.com>
Co-authored-by: Alon Peretz <8467965+alonp99@users.noreply.github.com>
  • Loading branch information
8 people authored Jan 21, 2025
1 parent 01c2c7b commit 301cb8b
Show file tree
Hide file tree
Showing 58 changed files with 1,518 additions and 725 deletions.
4 changes: 4 additions & 0 deletions apps/backoffice-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,16 @@
"i18next": "^22.4.9",
"i18next-browser-languagedetector": "^7.0.1",
"i18next-http-backend": "^2.1.1",
"jspdf": "^2.5.2",
"jspdf-autotable": "^3.8.4",
"leaflet": "^1.9.4",
"libphonenumber-js": "^1.10.49",
"lodash-es": "^4.17.21",
"lowlight": "^3.1.0",
"lucide-react": "0.445.0",
"match-sorter": "^6.3.1",
"msw": "^1.0.0",
"papaparse": "^5.5.1",
"posthog-js": "^1.154.2",
"qs": "^6.11.2",
"react": "^18.2.0",
Expand Down Expand Up @@ -172,6 +175,7 @@
"@types/leaflet": "^1.9.3",
"@types/lodash-es": "^4.17.12",
"@types/node": "^18.11.13",
"@types/papaparse": "^5.3.15",
"@types/qs": "^6.9.7",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FunctionComponentWithChildren } from '@/common/types';
import { ctw } from '@/common/utils/ctw/ctw';
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { isPdf } from '@/common/utils/is-pdf/is-pdf';
import { ComponentProps } from 'react';
import ReactCrop, { Crop } from 'react-image-crop';
Expand Down Expand Up @@ -30,7 +31,7 @@ export const ImageEditor: FunctionComponentWithChildren<IImageEditorProps> = ({
<TransformComponent
wrapperClass={`d-full max-w-[600px] max-h-[600px] h-full`}
contentClass={ctw({
'hover:cursor-move': !isPdf(image),
'hover:cursor-move': !isPdf(image) && !isCsv(image),
})}
wrapperStyle={{
width: '100%',
Expand All @@ -41,15 +42,15 @@ export const ImageEditor: FunctionComponentWithChildren<IImageEditorProps> = ({
contentStyle={{
width: '100%',
height: '100%',
display: !isPdf(image) ? 'block' : 'flex',
display: !isPdf(image) && !isCsv(image) ? 'block' : 'flex',
}}
>
<ReactCrop
crop={crop}
onChange={onCrop}
disabled={!isCropping || isPdf(image) || isRotatedOrTransformed}
disabled={!isCropping || isPdf(image) || isCsv(image) || isRotatedOrTransformed}
className={ctw('h-full w-full overflow-hidden [&>div]:!w-full', {
'flex flex-row [&>div]:min-h-[600px]': isPdf(image),
'flex flex-row [&>div]:min-h-[600px]': isPdf(image) || isCsv(image),
})}
>
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useFiltersQuery } from '@/domains/filters/hooks/queries/useFiltersQuery/useFiltersQuery';
import { useFilterId } from '@/common/hooks/useFilterId/useFilterId';
import { useCallback, useMemo } from 'react';
import { Building, Goal, Home, MonitorDot, Users } from 'lucide-react';
import { TRoutes, TRouteWithChildren } from '@/Router/types';
import { useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import { useCustomerQuery } from '@/domains/customer/hooks/queries/useCustomerQuery/useCustomerQuery';

import { useFilterId } from '@/common/hooks/useFilterId/useFilterId';
import { useLocale } from '@/common/hooks/useLocale/useLocale';
import { useCustomerQuery } from '@/domains/customer/hooks/queries/useCustomerQuery/useCustomerQuery';
import { useFiltersQuery } from '@/domains/filters/hooks/queries/useFiltersQuery/useFiltersQuery';
import { TRoutes, TRouteWithChildren } from '@/Router/types';

export const useNavbarLogic = () => {
const { data: filters } = useFiltersQuery();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { forwardRef, useCallback, useEffect, useState } from 'react';
import { ctw } from '../../../utils/ctw/ctw';
import { isPdf } from '../../../utils/is-pdf/is-pdf';
Expand Down Expand Up @@ -31,10 +32,10 @@ export const SelectedImage = forwardRef<HTMLImageElement | HTMLIFrameElement, TS
setIsError(false);
}, [isError, selectedImage?.imageUrl]);

if (isPdf(selectedImage)) {
if (isPdf(selectedImage) || isCsv(selectedImage)) {
return (
<iframe
src={selectedImage?.imageUrl + '#toolbar=0&navpanes=0'}
src={`${selectedImage?.imageUrl}#toolbar=0&navpanes=0`}
ref={ref}
className={ctw(className, `d-full mx-auto`, {
'h-[600px] w-[600px]': isPlaceholder,
Expand All @@ -60,3 +61,5 @@ export const SelectedImage = forwardRef<HTMLImageElement | HTMLIFrameElement, TS
);
},
);

SelectedImage.displayName = 'SelectedImage';
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { FunctionComponent } from 'react';
import { useImageViewerContext } from './hooks/useImageViewerContext/useImageViewerContext';
import { IZoomModalProps } from './interfaces';
import { Modal } from '../Modal/Modal';
import { BallerineImage } from '../../atoms/BallerineImage';
import { ctw } from '../../../utils/ctw/ctw';
import { isPdf } from '../../../utils/is-pdf/is-pdf';
import { BallerineImage } from '../../atoms/BallerineImage';
import { Modal } from '../Modal/Modal';
import { useImageViewerContext } from './hooks/useImageViewerContext/useImageViewerContext';
import { IZoomModalProps } from './interfaces';

/**
* @description To be used by {@link ImageViewer}. Uses the {@link Modal} component with default styling to display an enlarged version of the selected image.
Expand Down Expand Up @@ -33,14 +34,14 @@ export const ZoomModal: FunctionComponent<IZoomModalProps> = ({
hideTitle
{...rest}
>
{isPdf(selectedImage) && (
{(isPdf(selectedImage) || isCsv(selectedImage)) && (
<iframe
src={selectedImage?.imageUrl}
src={`${selectedImage?.imageUrl}${isCsv(selectedImage) ? '#toolbar=0&navpanes=0' : ''}`}
className={ctw(`d-full`, imageClassName)}
{...restImage}
/>
)}
{!isPdf(selectedImage) && (
{!isPdf(selectedImage) && !isCsv(selectedImage) && (
<BallerineImage
withPlaceholder
src={selectedImage?.imageUrl}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { ComponentProps, FunctionComponent } from 'react';
import { useSort } from '@/common/hooks/useSort/useSort';
import { useSelect } from '@/common/hooks/useSelect/useSelect';
import { DataTable } from '@ballerine/ui';
import { ComponentProps, FunctionComponent } from 'react';
import { PartialDeep } from 'type-fest';

import { usePersistentScroll } from '@/common/hooks/usePersistentScroll/usePersistentScroll';
import { useSelect } from '@/common/hooks/useSelect/useSelect';
import { useSort } from '@/common/hooks/useSort/useSort';

export const UrlDataTable: FunctionComponent<
Omit<ComponentProps<typeof DataTable>, 'sort' | 'select'> &
PartialDeep<Pick<ComponentProps<typeof DataTable>, 'sort' | 'select'>>
> = props => {
const { sortDir, sortBy, onSort } = useSort();
const { selected, onSelect } = useSelect();
const { ref, handleScroll } = usePersistentScroll();

return (
<DataTable
{...props}
ref={ref}
handleScroll={handleScroll}
sort={{
sortBy,
sortDir,
Expand Down
2 changes: 0 additions & 2 deletions apps/backoffice-v2/src/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
export const DOWNLOAD_ONLY_MIME_TYPES = [
'application/csv',
'text/csv',
// xls
'application/vnd.ms-excel',
// xlsx
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useRef } from 'react';

export const usePersistentScroll = () => {
const scrollAreaRef = useRef<HTMLDivElement>(null);

const resetScrollPosition = () => {
sessionStorage.removeItem('scrollPosition');
};

const restoreScrollPosition = () => {
const savedPosition = sessionStorage.getItem('scrollPosition');

if (savedPosition && scrollAreaRef.current) {
scrollAreaRef.current.scroll(0, parseInt(savedPosition, 10));
}
};

useEffect(() => {
if (scrollAreaRef.current?.scrollTop === 0) {
return restoreScrollPosition();
}
}, []);

const handleScroll = () => {
const scrollTop = scrollAreaRef.current?.scrollTop ?? 0;
sessionStorage.setItem('scrollPosition', scrollTop.toString());
};

return { ref: scrollAreaRef, handleScroll };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { jsPDF } from 'jspdf';
import 'jspdf-autotable';
import Papa from 'papaparse';

interface jsPDFWithPlugin extends jsPDF {
autoTable: any;
}

export const convertCsvToPdfBase64String = (csvBase64: string) => {
// Extract base64 data from data URI
const base64Data = csvBase64.split(',')[1] || csvBase64;

// Decode base64 to string
const csvString = atob(base64Data);

// Parse CSV string to array using PapaParse
const { data } = Papa.parse(csvString, {
header: true,
skipEmptyLines: true,
});

// Create new PDF document
const doc = new jsPDF() as jsPDFWithPlugin;

// Add table to PDF using autoTable
doc.autoTable({
head: [Object.keys(data[0] as object)], // Column headers
body: data.map(row => Object.values(row as object)), // Row data
startY: 10,
margin: { top: 10 },
styles: { fontSize: 8 },
headStyles: { fillColor: [66, 66, 66] },
});

return doc.output('datauristring');
};
2 changes: 2 additions & 0 deletions apps/backoffice-v2/src/common/utils/is-csv/is-csv.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const isCsv = <T extends { fileType: string }>(document: T) =>
document?.fileType === 'text/csv' || document?.fileType === 'application/csv';
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { TNoteableType } from '@/domains/notes/types';

export const useCreateNoteMutation = ({
onSuccess,
disableToast = false,
}: {
onSuccess?: <TData>(data: TData) => void;
disableToast: boolean;
}) => {
const queryClient = useQueryClient();

Expand Down Expand Up @@ -41,7 +43,9 @@ export const useCreateNoteMutation = ({
onSuccess: data => {
void queryClient.invalidateQueries();

toast.success(t(`toast:note_created.success`));
if (!disableToast) {
toast.success(t(`toast:note_created.success`));
}

onSuccess?.(data);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { TabsContent } from '@/common/components/organisms/Tabs/Tabs.Content';
import { useWebsiteMonitoringBusinessReportTab } from '@/lib/blocks/variants/WebsiteMonitoringBlocks/hooks/useWebsiteMonitoringReportBlock/hooks/useWebsiteMonitoringBusinessReportTab/useWebsiteMonitoringBusinessReportTab';
import { BusinessReportSummary } from '@ballerine/ui';
import { RiskIndicatorLink } from '@/domains/business-reports/components/RiskIndicatorLink/RiskIndicatorLink';
import {
MERCHANT_REPORT_TYPES,
MERCHANT_REPORT_TYPES_MAP,
} from '@/domains/business-reports/constants';

export const WebsiteMonitoringBusinessReportTab = ({
businessReport,
Expand All @@ -34,6 +38,7 @@ export const WebsiteMonitoringBusinessReportTab = ({
<div className={'grid gap-y-4'}>
<BusinessReportSummary
summary={summary}
isOnboarding={businessReport.reportType === MERCHANT_REPORT_TYPES_MAP.MERCHANT_REPORT_T1}
ongoingMonitoringSummary={ongoingMonitoringSummary}
riskLevels={riskLevels}
riskIndicators={riskIndicators}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useLocation } from 'react-router-dom';
import { createReportAdapter, useReportTabs } from '@ballerine/ui';
import { RiskIndicatorLink } from '@/domains/business-reports/components/RiskIndicatorLink/RiskIndicatorLink';
import { UnknownRecord } from 'type-fest';
import { MERCHANT_REPORT_TYPES_MAP } from '@/domains/business-reports/constants';

export const useWebsiteMonitoringBusinessReportTab = ({
businessReport,
Expand All @@ -14,6 +15,7 @@ export const useWebsiteMonitoringBusinessReportTab = ({
const { tabs: tabsWithSummary, riskIndicators: originalRiskIndicators } = useReportTabs({
reportVersion: businessReport?.workflowVersion,
report: businessReport?.data ?? {},
isOnboarding: businessReport?.reportType === MERCHANT_REPORT_TYPES_MAP.MERCHANT_REPORT_T1,
companyName:
(businessReport?.data?.websiteCompanyAnalysis as UnknownRecord | undefined)?.companyName ??
'',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import { TWorkflowById } from '@/domains/workflows/fetchers';
import { AnyObject } from '@ballerine/ui';

export const createContextFromFormData = (formData: AnyObject): TWorkflowById['context'] => {
const context = {
entity: formData, // For backward compatibility
return {
entity: {},
documents: [],
...formData,
};

return context;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FunctionComponent } from 'react';
import { ImageOCR } from '@/common/components/molecules/ImageOCR/ImageOCR';
import { ImageViewer } from '@/common/components/organisms/ImageViewer/ImageViewer';
import { ctw } from '@/common/utils/ctw/ctw';
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { isPdf } from '@/common/utils/is-pdf/is-pdf';
import { useDocumentsToolbarLogic } from '@/pages/Entity/components/Case/hooks/useDocumentsToolbarLogic/useDocumentsToolbarLogic';

Expand Down Expand Up @@ -55,7 +56,7 @@ export const DocumentsToolbar: FunctionComponent<{
<ExternalLinkIcon className={`p-0.5`} />
</button>
)}
{!isPdf(image) && !isLoading && (
{!isPdf(image) && !isCsv(image) && !isLoading && (
<>
<button
type={`button`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DownloadFile } from '@/common/components/molecules/DownloadFile/Downloa
import { ImageEditor } from '@/common/components/molecules/ImageEditor/ImageEditor';
import { ImageViewer } from '@/common/components/organisms/ImageViewer/ImageViewer';
import { ctw } from '@/common/utils/ctw/ctw';
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { keyFactory } from '@/common/utils/key-factory/key-factory';
import { DocumentsToolbar } from '@/pages/Entity/components/Case/Case.Documents.Toolbar';
import { useDocumentsLogic } from './hooks/useDocuments/useDocumentsLogic';
Expand Down Expand Up @@ -100,17 +101,21 @@ export const Documents: FunctionComponent<IDocumentsProps> = ({
? skeletons.map(index => (
<ImageViewer.SkeletonItem key={`image-viewer-skeleton-${index}`} />
))
: documents?.map(({ imageUrl, title, fileType, fileName, id }) => (
<ImageViewer.Item
id={id}
key={keyFactory(id, title, fileName, fileType, imageUrl)}
src={imageUrl}
fileType={fileType}
fileName={fileName}
alt={title}
caption={title}
/>
))}
: documents?.map(document => {
const { imageUrl, title, fileType, fileName, id } = document;

return !isCsv(document) ? (
<ImageViewer.Item
id={id}
key={keyFactory(id, title, fileName, fileType, imageUrl)}
src={imageUrl}
fileType={fileType}
fileName={fileName}
alt={title}
caption={title}
/>
) : null;
})}
</ImageViewer.List>
<ImageViewer.ZoomModal />
</ImageViewer>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { isCsv } from '@/common/utils/is-csv/is-csv';
import { convertCsvToPdfBase64String } from '../../../../../../common/utils/convert-csv-to-pdf-base64-string/convert-csv-to-pdf-base64-string';
import { IDocumentsProps } from '../../interfaces';

export const convertCsvDocumentsToPdf = (documents: IDocumentsProps['documents']) => {
return documents.map(document => {
if (isCsv(document)) {
return { ...document, imageUrl: convertCsvToPdfBase64String(document.imageUrl) };
}

return document;
});
};
Loading

0 comments on commit 301cb8b

Please sign in to comment.