Skip to content

Commit 8d918a5

Browse files
fixed fileselection issue
1 parent 737cd25 commit 8d918a5

File tree

10 files changed

+127
-56
lines changed

10 files changed

+127
-56
lines changed

frontend/src/components/ChatBot/Chatbot.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
SpeakerXMarkIconOutline,
88
} from '@neo4j-ndl/react/icons';
99
import ChatBotAvatar from '../../assets/images/chatbot-ai.png';
10-
import { ChatbotProps, UserCredentials, chunk } from '../../types';
10+
import { ChatbotProps, CustomFile, UserCredentials, chunk } from '../../types';
1111
import { useCredentials } from '../../context/UserCredentials';
1212
import { chatBotAPI } from '../../services/QnaAPI';
1313
import { v4 as uuidv4 } from 'uuid';
@@ -25,7 +25,7 @@ const Chatbot: React.FC<ChatbotProps> = (props) => {
2525
const [inputMessage, setInputMessage] = useState('');
2626
const [loading, setLoading] = useState<boolean>(isLoading);
2727
const { userCredentials } = useCredentials();
28-
const { model, chatMode, selectedRows } = useFileContext();
28+
const { model, chatMode, selectedRows, filesData } = useFileContext();
2929
const messagesEndRef = useRef<HTMLDivElement>(null);
3030
const [sessionId, setSessionId] = useState<string>(sessionStorage.getItem('session_id') ?? '');
3131
const [showInfoModal, setShowInfoModal] = useState<boolean>(false);
@@ -43,8 +43,17 @@ const Chatbot: React.FC<ChatbotProps> = (props) => {
4343
setListMessages((msgs) => msgs.map((msg) => ({ ...msg, speaking: false })));
4444
},
4545
});
46-
47-
const selectedFileNames = selectedRows.map((str) => JSON.parse(str).name);
46+
let selectedFileNames: CustomFile[] = [];
47+
selectedRows.forEach((id) => {
48+
console.log(id);
49+
filesData.forEach((f) => {
50+
console.log(f.id, id);
51+
if (f.id === id) {
52+
selectedFileNames.push(f);
53+
}
54+
});
55+
});
56+
console.log({ selectedFileNames });
4857

4958
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
5059
setInputMessage(e.target.value);
@@ -155,7 +164,7 @@ const Chatbot: React.FC<ChatbotProps> = (props) => {
155164
sessionId,
156165
model,
157166
chatMode,
158-
selectedFileNames
167+
selectedFileNames?.map((f) => f.name)
159168
);
160169
const chatresponse = chatbotAPI?.response;
161170
chatbotReply = chatresponse?.data?.data?.message;

frontend/src/components/Content.tsx

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { useEffect, useState, useMemo } from 'react';
1+
import { useEffect, useState, useMemo, useRef } from 'react';
22
import ConnectionModal from './Popups/ConnectionModal/ConnectionModal';
3-
import FileTable from './FileTable';
3+
import FileTable, { ChildRef } from './FileTable';
44
import { Button, Typography, Flex, StatusIndicator } from '@neo4j-ndl/react';
55
import { useCredentials } from '../context/UserCredentials';
66
import { useFileContext } from '../context/UsersFiles';
@@ -50,7 +50,6 @@ const Content: React.FC<ContentProps> = ({
5050
model,
5151
selectedNodes,
5252
selectedRels,
53-
selectedRows,
5453
setSelectedNodes,
5554
setRowSelection,
5655
setSelectedRels,
@@ -81,6 +80,7 @@ const Content: React.FC<ContentProps> = ({
8180
});
8281
}
8382
);
83+
const childRef = useRef<ChildRef>(null);
8484
const openGraphEnhancementDialog = () => {
8585
setshowEnhancementDialog(true);
8686
};
@@ -140,10 +140,10 @@ const Content: React.FC<ContentProps> = ({
140140
await extractHandler(fileItem, uid);
141141
}
142142
} else {
143-
const fileItem = selectedRows.find((f) => JSON.parse(f).id == uid);
143+
const fileItem = childRef.current?.getSelectedRows().find((f) => f.id == uid);
144144
if (fileItem) {
145145
setextractLoading(true);
146-
await extractHandler(JSON.parse(fileItem), uid);
146+
await extractHandler(fileItem, uid);
147147
}
148148
}
149149
};
@@ -164,7 +164,7 @@ const Content: React.FC<ContentProps> = ({
164164
setRowSelection((prev) => {
165165
const copiedobj = { ...prev };
166166
for (const key in copiedobj) {
167-
if (JSON.parse(key).id == uid) {
167+
if (key == uid) {
168168
copiedobj[key] = false;
169169
}
170170
}
@@ -252,8 +252,8 @@ const Content: React.FC<ContentProps> = ({
252252
const data = [];
253253
if (selectedfileslength && allowLargeFiles) {
254254
for (let i = 0; i < selectedfileslength; i++) {
255-
const row = JSON.parse(selectedRows[i]);
256-
if (row.status === 'New') {
255+
const row = childRef.current?.getSelectedRows()[i];
256+
if (row?.status === 'New') {
257257
data.push(extractData(row.id, true));
258258
}
259259
}
@@ -316,13 +316,19 @@ const Content: React.FC<ContentProps> = ({
316316
setSelectedRels([]);
317317
};
318318

319-
const selectedfileslength = useMemo(() => selectedRows.length, [selectedRows]);
319+
const selectedfileslength = useMemo(
320+
() => childRef.current?.getSelectedRows().length,
321+
[childRef.current?.getSelectedRows()]
322+
);
320323

321-
const newFilecheck = useMemo(() => selectedRows.filter((f) => JSON.parse(f).status === 'New').length, [selectedRows]);
324+
const newFilecheck = useMemo(
325+
() => childRef.current?.getSelectedRows().filter((f) => f.status === 'New').length,
326+
[childRef.current?.getSelectedRows()]
327+
);
322328

323329
const completedfileNo = useMemo(
324-
() => selectedRows.filter((f) => JSON.parse(f).status === 'Completed').length,
325-
[selectedRows]
330+
() => childRef.current?.getSelectedRows().filter((f) => f.status === 'Completed').length,
331+
[childRef.current?.getSelectedRows()]
326332
);
327333

328334
const dropdowncheck = useMemo(() => !filesData.some((f) => f.status === 'New'), [filesData]);
@@ -339,17 +345,17 @@ const Content: React.FC<ContentProps> = ({
339345

340346
// const processingCheck = () => {
341347
// const processingFiles = filesData.some((file) => file.status === 'Processing');
342-
// const selectedRowProcessing = selectedRows.some((row) =>
348+
// const selectedRowProcessing = childRef.current?.getSelectedRows().some((row) =>
343349
// filesData.some((file) => file.name === row && file.status === 'Processing')
344350
// );
345351
// return processingFiles || selectedRowProcessing;
346352
// };
347353

348354
const filesForProcessing = useMemo(() => {
349355
let newstatusfiles: CustomFile[] = [];
350-
if (selectedRows.length) {
351-
selectedRows.forEach((f) => {
352-
const parsedFile: CustomFile = JSON.parse(f);
356+
if (childRef.current?.getSelectedRows().length) {
357+
childRef.current?.getSelectedRows().forEach((f) => {
358+
const parsedFile: CustomFile = f;
353359
if (parsedFile.status === 'New') {
354360
newstatusfiles.push(parsedFile);
355361
}
@@ -358,12 +364,16 @@ const Content: React.FC<ContentProps> = ({
358364
newstatusfiles = filesData.filter((f) => f.status === 'New');
359365
}
360366
return newstatusfiles;
361-
}, [filesData, selectedRows]);
367+
}, [filesData, childRef.current?.getSelectedRows()]);
362368

363369
const handleDeleteFiles = async (deleteEntities: boolean) => {
364370
try {
365371
setdeleteLoading(true);
366-
const response = await deleteAPI(userCredentials as UserCredentials, selectedRows, deleteEntities);
372+
const response = await deleteAPI(
373+
userCredentials as UserCredentials,
374+
childRef.current?.getSelectedRows() as CustomFile[],
375+
deleteEntities
376+
);
367377
setRowSelection({});
368378
setdeleteLoading(false);
369379
if (response.data.status == 'Success') {
@@ -372,8 +382,8 @@ const Content: React.FC<ContentProps> = ({
372382
alertMessage: response.data.message,
373383
alertType: 'success',
374384
});
375-
const filenames = selectedRows.map((str) => JSON.parse(str).name);
376-
filenames.forEach((name) => {
385+
const filenames = childRef.current?.getSelectedRows().map((str) => str.name);
386+
filenames?.forEach((name) => {
377387
setFilesData((prev) => prev.filter((f) => f.name != name));
378388
});
379389
} else {
@@ -423,10 +433,10 @@ const Content: React.FC<ContentProps> = ({
423433

424434
const onClickHandler = () => {
425435
if (isSchema) {
426-
if (selectedRows.length) {
436+
if (childRef.current?.getSelectedRows().length) {
427437
let selectedLargeFiles: CustomFile[] = [];
428-
selectedRows.forEach((f) => {
429-
const parsedData: CustomFile = JSON.parse(f);
438+
childRef.current?.getSelectedRows().forEach((f) => {
439+
const parsedData: CustomFile = f;
430440
if (parsedData.fileSource === 'local file') {
431441
if (typeof parsedData.size === 'number' && parsedData.status === 'New' && parsedData.size > largeFileSize) {
432442
selectedLargeFiles.push(parsedData);
@@ -451,7 +461,7 @@ const Content: React.FC<ContentProps> = ({
451461
});
452462
const selectAllNewFiles = filesData.filter((f) => f.status === 'New');
453463
const stringified = selectAllNewFiles.reduce((accu, f) => {
454-
const key = JSON.stringify(f);
464+
const key = f.id;
455465
// @ts-ignore
456466
accu[key] = true;
457467
return accu;
@@ -467,10 +477,10 @@ const Content: React.FC<ContentProps> = ({
467477
}
468478
}
469479
} else {
470-
if (selectedRows.length) {
480+
if (childRef.current?.getSelectedRows().length) {
471481
let selectedLargeFiles: CustomFile[] = [];
472-
selectedRows.forEach((f) => {
473-
const parsedData: CustomFile = JSON.parse(f);
482+
childRef.current?.getSelectedRows().forEach((f) => {
483+
const parsedData: CustomFile = f;
474484
if (parsedData.fileSource === 'local file') {
475485
if (typeof parsedData.size === 'number' && parsedData.status === 'New' && parsedData.size > largeFileSize) {
476486
selectedLargeFiles.push(parsedData);
@@ -492,7 +502,7 @@ const Content: React.FC<ContentProps> = ({
492502
});
493503
const selectAllNewFiles = filesData.filter((f) => f.status === 'New');
494504
const stringified = selectAllNewFiles.reduce((accu, f) => {
495-
const key = JSON.stringify(f);
505+
const key = f.id;
496506
// @ts-ignore
497507
accu[key] = true;
498508
return accu;
@@ -555,7 +565,7 @@ const Content: React.FC<ContentProps> = ({
555565
{showDeletePopUp && (
556566
<DeletePopUp
557567
open={showDeletePopUp}
558-
no_of_files={selectedfileslength}
568+
no_of_files={selectedfileslength ?? 0}
559569
deleteHandler={(delentities: boolean) => handleDeleteFiles(delentities)}
560570
deleteCloseHandler={() => setshowDeletePopUp(false)}
561571
loading={deleteLoading}
@@ -629,6 +639,7 @@ const Content: React.FC<ContentProps> = ({
629639
setOpenGraphView(true);
630640
setViewPoint('tableView');
631641
}}
642+
ref={childRef}
632643
></FileTable>
633644
<Flex
634645
className={`${
@@ -688,7 +699,7 @@ const Content: React.FC<ContentProps> = ({
688699
label='Delete Files'
689700
>
690701
{buttonCaptions.deleteFiles}
691-
{selectedfileslength > 0 && `(${selectedfileslength})`}
702+
{selectedfileslength != undefined && selectedfileslength > 0 && `(${selectedfileslength})`}
692703
</ButtonWithToolTip>
693704
</Flex>
694705
</Flex>
@@ -698,6 +709,7 @@ const Content: React.FC<ContentProps> = ({
698709
open={openGraphView}
699710
setGraphViewOpen={setOpenGraphView}
700711
viewPoint={viewPoint}
712+
selectedRows={childRef.current?.getSelectedRows()}
701713
/>
702714
</>
703715
);

frontend/src/components/FileTable.tsx

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
TextLink,
1010
Typography,
1111
} from '@neo4j-ndl/react';
12-
import { useEffect, useMemo, useRef, useState } from 'react';
12+
import { forwardRef, HTMLProps, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
1313
import React from 'react';
1414
import {
1515
useReactTable,
@@ -41,7 +41,12 @@ import cancelAPI from '../services/CancelAPI';
4141
import IconButtonWithToolTip from './UI/IconButtonToolTip';
4242
import { largeFileSize } from '../utils/Constants';
4343

44-
const FileTable: React.FC<FileTableProps> = ({ isExpanded, connectionStatus, setConnectionStatus, onInspect }) => {
44+
export interface ChildRef {
45+
getSelectedRows: () => CustomFile[];
46+
}
47+
48+
const FileTable = forwardRef<ChildRef, FileTableProps>((props, ref) => {
49+
const { isExpanded, connectionStatus, setConnectionStatus, onInspect } = props;
4550
const { filesData, setFilesData, model, rowSelection, setRowSelection, setSelectedRows } = useFileContext();
4651
const { userCredentials } = useCredentials();
4752
const columnHelper = createColumnHelper<CustomFile>();
@@ -102,14 +107,24 @@ const FileTable: React.FC<FileTableProps> = ({ isExpanded, connectionStatus, set
102107
row.getIsSelected() && row.original.status != 'Uploading' && row.original.status != 'Processing';
103108
return (
104109
<div className='px-1'>
105-
<Checkbox
110+
{/* <Checkbox
106111
aria-label='row-checkbox'
107112
checked={checkedCase}
108113
disabled={
109114
!row.getCanSelect() || row.original.status === 'Uploading' || row.original.status === 'Processing'
110115
}
111116
onChange={row.getToggleSelectedHandler()}
112117
title='select row for deletion'
118+
/> */}
119+
120+
<IndeterminateCheckbox
121+
{...{
122+
checked: row.getIsSelected(),
123+
disabled:
124+
!row.getCanSelect() || row.original.status == 'Uploading' || row.original.status === 'Processing',
125+
indeterminate: row.getIsSomeSelected(),
126+
onChange: row.getToggleSelectedHandler(),
127+
}}
113128
/>
114129
</div>
115130
);
@@ -601,11 +616,17 @@ const FileTable: React.FC<FileTableProps> = ({ isExpanded, connectionStatus, set
601616
autoResetPageIndex: false,
602617
enableRowSelection: true,
603618
enableMultiRowSelection: true,
604-
getRowId: (row) => JSON.stringify({ ...row }),
619+
getRowId: (row) => row.id,
605620
enableSorting: true,
606621
getSortedRowModel: getSortedRowModel(),
607622
});
608-
623+
useImperativeHandle(
624+
ref,
625+
() => ({
626+
getSelectedRows: () => table.getSelectedRowModel().rows.map((r) => r.original),
627+
}),
628+
[table]
629+
);
609630
useEffect(() => {
610631
if (tableRef.current) {
611632
// Component has content, calculate maximum height for table
@@ -702,6 +723,21 @@ const FileTable: React.FC<FileTableProps> = ({ isExpanded, connectionStatus, set
702723
) : null}
703724
</>
704725
);
705-
};
726+
});
706727

707728
export default FileTable;
729+
function IndeterminateCheckbox({
730+
indeterminate,
731+
className = '',
732+
...rest
733+
}: { indeterminate?: boolean } & HTMLProps<HTMLInputElement>) {
734+
const ref = React.useRef<HTMLInputElement>(null!);
735+
736+
React.useEffect(() => {
737+
if (typeof indeterminate === 'boolean') {
738+
ref.current.indeterminate = !rest.checked && indeterminate;
739+
}
740+
}, [ref, indeterminate]);
741+
742+
return <Checkbox type='checkbox' ref={ref} className={className + ' cursor-pointer'} {...rest} />;
743+
}

frontend/src/components/Graph/GraphViewModal.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
nvlOptions,
2929
queryMap,
3030
} from '../../utils/Constants';
31-
import { useFileContext } from '../../context/UsersFiles';
3231
// import CheckboxSelection from './CheckboxSelection';
3332
import DropdownComponent from '../Dropdown';
3433
const GraphViewModal: React.FunctionComponent<GraphViewModalProps> = ({
@@ -38,6 +37,7 @@ const GraphViewModal: React.FunctionComponent<GraphViewModalProps> = ({
3837
viewPoint,
3938
nodeValues,
4039
relationshipValues,
40+
selectedRows,
4141
}) => {
4242
const nvlRef = useRef<NVL>(null);
4343
const [nodes, setNodes] = useState<Node[]>([]);
@@ -50,7 +50,6 @@ const GraphViewModal: React.FunctionComponent<GraphViewModalProps> = ({
5050
const [statusMessage, setStatusMessage] = useState<string>('');
5151
const { userCredentials } = useCredentials();
5252
const [scheme, setScheme] = useState<Scheme>({});
53-
const { selectedRows } = useFileContext();
5453
const [newScheme, setNewScheme] = useState<Scheme>({});
5554
const [dropdownVal, setDropdownVal] = useState<OptionType>({
5655
label: 'Knowledge Graph',
@@ -101,7 +100,7 @@ const GraphViewModal: React.FunctionComponent<GraphViewModalProps> = ({
101100
? await graphQueryAPI(
102101
userCredentials as UserCredentials,
103102
graphQuery,
104-
selectedRows.map((f) => JSON.parse(f).name)
103+
selectedRows?.map((f) => f.name)
105104
)
106105
: await graphQueryAPI(userCredentials as UserCredentials, graphQuery, [inspectedName ?? '']);
107106
return nodeRelationshipData;

0 commit comments

Comments
 (0)