Skip to content

Commit 2172143

Browse files
fomrat issues
1 parent a74e771 commit 2172143

File tree

9 files changed

+150
-128
lines changed

9 files changed

+150
-128
lines changed

frontend/src/components/Layout/PageLayout.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { envConnectionAPI } from '../../services/ConnectAPI';
1616
import { healthStatus } from '../../services/HealthStatus';
1717
import { useAuth0 } from '@auth0/auth0-react';
1818
import { showErrorToast } from '../../utils/Toasts';
19-
import { APP_SOURCES, LOCAL_KEYS } from '../../utils/Constants';
19+
import { APP_SOURCES } from '../../utils/Constants';
2020
import { createDefaultFormData } from '../../API/Index';
2121
import LoadDBSchemaDialog from '../Popups/GraphEnhancementDialog/EnitityExtraction/LoadExistingSchema';
2222
import PredefinedSchemaDialog from '../Popups/GraphEnhancementDialog/EnitityExtraction/PredefinedSchemaDialog';
@@ -187,7 +187,6 @@ const PageLayout: React.FC = () => {
187187
setSchemaValRels,
188188
setDbNodes,
189189
setDbRels,
190-
setSchemaView,
191190
setPreDefinedNodes,
192191
setPreDefinedRels,
193192
setPreDefinedPattern,
@@ -199,6 +198,9 @@ const PageLayout: React.FC = () => {
199198
setImporterPattern,
200199
setImporterNodes,
201200
setImporterRels,
201+
setSourceOptions,
202+
setTargetOptions,
203+
setTypeOptions,
202204
} = useFileContext();
203205
const navigate = useNavigate();
204206
const { user, isAuthenticated } = useAuth0();
@@ -386,10 +388,9 @@ const PageLayout: React.FC = () => {
386388
const combined = [...rels, ...prevRels];
387389
return deduplicateByFullPattern(combined);
388390
});
389-
setSchemaView('text');
390-
localStorage.setItem(LOCAL_KEYS.source, JSON.stringify(updatedSource));
391-
localStorage.setItem(LOCAL_KEYS.type, JSON.stringify(updatedType));
392-
localStorage.setItem(LOCAL_KEYS.target, JSON.stringify(updatedTarget));
391+
setSourceOptions((prev) => [...prev, ...updatedSource]);
392+
setTargetOptions((prev) => [...prev, ...updatedTarget]);
393+
setTypeOptions((prev) => [...prev, ...updatedType]);
393394
},
394395
[]
395396
);
@@ -415,7 +416,6 @@ const PageLayout: React.FC = () => {
415416
triggeredFrom: 'loadExistingSchemaApply',
416417
show: true,
417418
});
418-
setSchemaView('db');
419419
setDbNodes(nodes);
420420
setCombinedNodesVal((prevNodes: OptionType[]) => {
421421
const combined = [...nodes, ...prevNodes];
@@ -426,9 +426,9 @@ const PageLayout: React.FC = () => {
426426
const combined = [...rels, ...prevRels];
427427
return deduplicateByFullPattern(combined);
428428
});
429-
localStorage.setItem(LOCAL_KEYS.source, JSON.stringify(updatedSource));
430-
localStorage.setItem(LOCAL_KEYS.type, JSON.stringify(updatedType));
431-
localStorage.setItem(LOCAL_KEYS.target, JSON.stringify(updatedTarget));
429+
setSourceOptions((prev) => [...prev, ...updatedSource]);
430+
setTargetOptions((prev) => [...prev, ...updatedTarget]);
431+
setTypeOptions((prev) => [...prev, ...updatedType]);
432432
},
433433
[]
434434
);
@@ -453,7 +453,6 @@ const PageLayout: React.FC = () => {
453453
triggeredFrom: 'predefinedSchemaApply',
454454
show: true,
455455
});
456-
setSchemaView('preDefined');
457456
setPreDefinedNodes(nodes);
458457
setCombinedNodesVal((prevNodes: OptionType[]) => {
459458
const combined = [...nodes, ...prevNodes];
@@ -464,9 +463,9 @@ const PageLayout: React.FC = () => {
464463
const combined = [...rels, ...prevRels];
465464
return deduplicateByFullPattern(combined);
466465
});
467-
localStorage.setItem(LOCAL_KEYS.source, JSON.stringify(updatedSource));
468-
localStorage.setItem(LOCAL_KEYS.type, JSON.stringify(updatedType));
469-
localStorage.setItem(LOCAL_KEYS.target, JSON.stringify(updatedTarget));
466+
setSourceOptions((prev) => [...prev, ...updatedSource]);
467+
setTargetOptions((prev) => [...prev, ...updatedTarget]);
468+
setTypeOptions((prev) => [...prev, ...updatedType]);
470469
},
471470
[]
472471
);
@@ -492,7 +491,6 @@ const PageLayout: React.FC = () => {
492491
triggeredFrom: 'importerSchemaApply',
493492
show: true,
494493
});
495-
setSchemaView('importer');
496494
setImporterNodes(nodes);
497495
setCombinedNodesVal((prevNodes: OptionType[]) => {
498496
const combined = [...nodes, ...prevNodes];
@@ -503,9 +501,9 @@ const PageLayout: React.FC = () => {
503501
const combined = [...rels, ...prevRels];
504502
return deduplicateByFullPattern(combined);
505503
});
506-
localStorage.setItem(LOCAL_KEYS.source, JSON.stringify(updatedSource));
507-
localStorage.setItem(LOCAL_KEYS.type, JSON.stringify(updatedType));
508-
localStorage.setItem(LOCAL_KEYS.target, JSON.stringify(updatedTarget));
504+
setSourceOptions((prev) => [...prev, ...updatedSource]);
505+
setTargetOptions((prev) => [...prev, ...updatedTarget]);
506+
setTypeOptions((prev) => [...prev, ...updatedType]);
509507
},
510508
[]
511509
);

frontend/src/components/Popups/GraphEnhancementDialog/EnitityExtraction/GraphPattern.tsx

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import React, { useState, useRef, useEffect } from 'react';
22
import { Select } from '@neo4j-ndl/react';
33
import ButtonWithToolTip from '../../../UI/ButtonWithToolTip';
44
import { OptionType, TupleCreationProps } from '../../../../types';
5-
import { appLabels, LOCAL_KEYS } from '../../../../utils/Constants';
5+
import { appLabels } from '../../../../utils/Constants';
66
import { useFileContext } from '../../../../context/UsersFiles';
7+
import { useCredentials } from '../../../../context/UserCredentials';
78
interface IErrorState {
89
showError: boolean;
910
errorMessage: string;
@@ -15,8 +16,16 @@ const GraphPattern: React.FC<TupleCreationProps> = ({
1516
onPatternChange,
1617
onAddPattern,
1718
}) => {
18-
const { sourceOptions, setSourceOptions, typeOptions, setTypeOptions, targetOptions, setTargetOptions } =
19-
useFileContext();
19+
const {
20+
sourceOptions,
21+
setSourceOptions,
22+
typeOptions,
23+
setTypeOptions,
24+
targetOptions,
25+
setTargetOptions,
26+
setSelectedRels,
27+
selectedRels,
28+
} = useFileContext();
2029
const [inputValues, setInputValues] = useState<{ source: string; type: string; target: string }>({
2130
source: '',
2231
type: '',
@@ -28,19 +37,41 @@ const GraphPattern: React.FC<TupleCreationProps> = ({
2837
target: { showError: false, errorMessage: '' },
2938
});
3039
const sourceRef = useRef<HTMLDivElement | null>(null);
40+
const { userCredentials } = useCredentials();
3141

3242
useEffect(() => {
33-
const savedSources = JSON.parse(localStorage.getItem('customSourceOptions') ?? 'null');
34-
const savedTypes = JSON.parse(localStorage.getItem('customTypeOptions') ?? 'null');
35-
const savedTargets = JSON.parse(localStorage.getItem('customTargetOptions') ?? 'null');
36-
if (savedSources) {
37-
setSourceOptions(savedSources);
38-
}
39-
if (savedTypes) {
40-
setTypeOptions(savedTypes);
43+
const isGlobalStateSet =
44+
selectedRels.length > 0 || sourceOptions.length > 0 || typeOptions.length > 0 || targetOptions.length > 0;
45+
if (isGlobalStateSet) {
46+
return;
4147
}
42-
if (savedTargets) {
43-
setTargetOptions(savedTargets);
48+
const selectedNodeRelsStr = localStorage.getItem('selectedRelationshipLabels');
49+
if (selectedNodeRelsStr != null) {
50+
const selectedGraphOptions = JSON.parse(selectedNodeRelsStr);
51+
if (userCredentials?.uri === selectedGraphOptions.db) {
52+
const rels = selectedGraphOptions.selectedOptions;
53+
const sourceSet = new Set<string>();
54+
const typeSet = new Set<string>();
55+
const targetSet = new Set<string>();
56+
const mappedRels = rels.map((rel: { value: string }) => {
57+
const [sourceVal, typeVal, targetVal] = rel.value.split(',');
58+
sourceSet.add(sourceVal);
59+
typeSet.add(typeVal);
60+
targetSet.add(targetVal);
61+
return {
62+
source: { value: sourceVal, label: sourceVal },
63+
type: { value: typeVal, label: typeVal },
64+
target: { value: targetVal, label: targetVal },
65+
};
66+
});
67+
const savedSources: OptionType[] = Array.from(sourceSet).map((val) => ({ value: val, label: val }));
68+
const savedTypes: OptionType[] = Array.from(typeSet).map((val) => ({ value: val, label: val }));
69+
const savedTargets: OptionType[] = Array.from(targetSet).map((val) => ({ value: val, label: val }));
70+
setSelectedRels(mappedRels);
71+
setSourceOptions(savedSources);
72+
setTypeOptions(savedTypes);
73+
setTargetOptions(savedTargets);
74+
}
4475
}
4576
}, []);
4677

@@ -92,9 +123,6 @@ const GraphPattern: React.FC<TupleCreationProps> = ({
92123

93124
const handleAddPattern = () => {
94125
onAddPattern();
95-
localStorage.setItem(LOCAL_KEYS.source, JSON.stringify(sourceOptions));
96-
localStorage.setItem(LOCAL_KEYS.type, JSON.stringify(typeOptions));
97-
localStorage.setItem(LOCAL_KEYS.target, JSON.stringify(targetOptions));
98126
setTimeout(() => {
99127
const selectInput = sourceRef.current?.querySelector('input');
100128
selectInput?.focus();
Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,12 @@
1-
import { useState, useCallback, KeyboardEvent, ChangeEvent, FocusEvent } from 'react';
2-
import { Box, TextInput, Button } from '@neo4j-ndl/react';
3-
import { importerValidation } from '../../../../utils/Utils';
1+
import { Box, TextLink } from '@neo4j-ndl/react';
42

53
const ImporterInput = () => {
6-
const [value, setValue] = useState<string>('');
7-
const [isValid, setIsValid] = useState<boolean>(false);
8-
const [isFocused, setIsFocused] = useState<boolean>(false);
9-
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
10-
const newValue = e.target.value;
11-
setValue(newValue);
12-
setIsValid(importerValidation(newValue));
13-
};
14-
const handleBlur = () => {
15-
setIsFocused(false);
16-
setIsValid(importerValidation(value));
17-
};
18-
const handleFocus = () => {
19-
setIsFocused(true);
20-
};
21-
const handleSubmit = useCallback(() => {
22-
if (importerValidation(value)) {
23-
window.open(value, '_blank');
24-
}
25-
}, [value]);
26-
const handleCancel = () => {
27-
setValue('');
28-
setIsValid(false);
29-
};
30-
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
31-
if (e.code === 'Enter' && isValid) {
32-
handleSubmit();
33-
}
34-
};
35-
const isEmpty = value.trim() === '';
364
return (
37-
<Box>
38-
<div className='w-full inline-block mb-2'>
39-
<TextInput
40-
htmlAttributes={{
41-
onBlur: handleBlur,
42-
onFocus: handleFocus,
43-
onKeyDown: handleKeyDown,
44-
placeholder: 'Enter URL to import...',
45-
'aria-label': 'Importer URL Input',
46-
}}
47-
value={value}
48-
label='Import Link'
49-
isFluid
50-
isRequired
51-
onChange={handleChange}
52-
errorText={value && !isValid && isFocused ? 'Please enter a valid URL' : ''}
53-
/>
54-
</div>
55-
<div className='w-full flex justify-end gap-2'>
56-
<Button onClick={handleCancel} isDisabled={isEmpty} size='medium'>
57-
Cancel
58-
</Button>
59-
<Button onClick={handleSubmit} isDisabled={!isValid} size='medium'>
60-
Apply
61-
</Button>
62-
</div>
5+
<Box className='py-2'>
6+
<TextLink isExternalLink={true} href='https://console-preview.neo4j.io/tools/import/models' target='_blank'>
7+
Aura Data Models
8+
</TextLink>
639
</Box>
6410
);
6511
};
66-
6712
export default ImporterInput;

frontend/src/components/Popups/GraphEnhancementDialog/EnitityExtraction/LoadExistingSchema.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const LoadDBSchemaDialog = ({ open, onClose, onApply }: LoadDBSchemaDialogProps)
3636
} = useFileContext();
3737
const [openGraphView, setOpenGraphView] = useState<boolean>(false);
3838
const [viewPoint, setViewPoint] = useState<string>('');
39+
const [message, setMessage] = useState<string>('');
3940

4041
useEffect(() => {
4142
if (open) {
@@ -48,6 +49,13 @@ const LoadDBSchemaDialog = ({ open, onClose, onApply }: LoadDBSchemaDialogProps)
4849
try {
4950
const response = await getNodeLabelsAndRelTypes();
5051
const schemaData: string[] = response.data.data.triplets;
52+
if (!schemaData || schemaData.length === 0) {
53+
setDbNodes([]);
54+
setDbRels([]);
55+
setDbPattern([]);
56+
setMessage('No data found');
57+
return;
58+
}
5159
const schemaTuples: TupleType[] = schemaData
5260
.map((item: string) => {
5361
const matchResult = item.match(/^(.+?)-([A-Z_]+)->(.+)$/);
@@ -142,6 +150,7 @@ const LoadDBSchemaDialog = ({ open, onClose, onApply }: LoadDBSchemaDialogProps)
142150
onCancel={handleCancel}
143151
nodes={dbNodes}
144152
rels={dbRels}
153+
message={message}
145154
/>
146155
{openGraphView && (
147156
<SchemaViz

frontend/src/components/Popups/GraphEnhancementDialog/EnitityExtraction/NewEntityExtractionSetting.tsx

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export default function NewEntityExtractionSetting({
7272
setPreDefinedRels,
7373
preDefinedPattern,
7474
setPreDefinedPattern,
75+
setImporterNodes,
76+
setImporterRels,
77+
setImporterPattern,
78+
importerPattern,
7579
} = useFileContext();
7680
const { userCredentials } = useCredentials();
7781
const [openGraphView, setOpenGraphView] = useState<boolean>(false);
@@ -124,6 +128,10 @@ export default function NewEntityExtractionSetting({
124128
updateLocalStorage(userCredentials!, 'selectedRelationshipLabels', []);
125129
updateLocalStorage(userCredentials!, 'selectedPattern', []);
126130
showNormalToast(`Successfully Removed the Schema settings`);
131+
// Importer clear
132+
setImporterNodes([]);
133+
setImporterRels([]);
134+
setImporterPattern([]);
127135
};
128136

129137
const handleFinalApply = (pattern: string[], nodeLables: OptionType[], relationshipLabels: OptionType[]) => {
@@ -237,11 +245,12 @@ export default function NewEntityExtractionSetting({
237245

238246
const handleRemovePattern = (patternToRemove: string) => {
239247
const match = patternToRemove.match(/(.*?) -\[:(.*?)\]-> (.*)/);
240-
if (!match) {
241-
return;
248+
let source = '';
249+
let rel = '';
250+
let target = '';
251+
if (match) {
252+
[source, rel, target] = match.slice(1).map((s) => s.trim());
242253
}
243-
const [, source, type, target] = match.map((s) => s.trim());
244-
245254
if (userDefinedPattern.includes(patternToRemove)) {
246255
updateStore(userDefinedPattern, patternToRemove, setUserDefinedPattern, setUserDefinedNodes, setUserDefinedRels);
247256
}
@@ -254,9 +263,30 @@ export default function NewEntityExtractionSetting({
254263
if (schemaTextPattern.includes(patternToRemove)) {
255264
updateStore(schemaTextPattern, patternToRemove, setSchemaTextPattern, setSchemaValNodes, setSchemaValRels);
256265
}
257-
setCombinedPatterns((prev) => prev.filter((p) => p !== patternToRemove));
258-
setCombinedNodes((prev) => prev.filter((n) => n.value !== source && n.value !== target));
259-
setCombinedRels((prev) => prev.filter((r) => r.value !== type));
266+
if (importerPattern.includes(patternToRemove)) {
267+
updateStore(importerPattern, patternToRemove, setImporterPattern, setImporterNodes, setImporterRels);
268+
}
269+
const updatedCombinedPatterns = combinedPatterns.filter((p) => p !== patternToRemove);
270+
setCombinedPatterns(updatedCombinedPatterns);
271+
const updatedTuples: TupleType[] = updatedCombinedPatterns
272+
.map((item) => {
273+
const parts = item.match(/(.*?) -\[:(.*?)\]-> (.*)/);
274+
if (!parts) {
275+
return null;
276+
}
277+
const [src, rel, tgt] = parts.slice(1).map((s) => s.trim());
278+
return {
279+
value: `${src},${rel},${tgt}`,
280+
label: `${src} -[:${rel}]-> ${tgt}`,
281+
source: src,
282+
target: tgt,
283+
type: rel,
284+
};
285+
})
286+
.filter(Boolean) as TupleType[];
287+
const { nodeLabelOptions, relationshipTypeOptions } = extractOptions(updatedTuples);
288+
setCombinedNodes(nodeLabelOptions);
289+
setCombinedRels(relationshipTypeOptions);
260290
setTupleOptions((prev) => prev.filter((t) => t.label !== patternToRemove));
261291
};
262292

frontend/src/components/Popups/GraphEnhancementDialog/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ export default function GraphEnhancementDialog({
5151
setSelectedPreDefOption,
5252
allPatterns,
5353
setDataImporterSchemaDialog,
54+
setImporterNodes,
55+
setImporterPattern,
56+
setImporterRels,
5457
} = useFileContext();
5558
const isTablet = useMediaQuery(`(min-width:${breakpoints.xs}) and (max-width: ${breakpoints.lg})`);
5659

@@ -86,7 +89,14 @@ export default function GraphEnhancementDialog({
8689
setPreDefinedNodes([]);
8790
setPreDefinedRels([]);
8891
setPreDefinedPattern([]);
92+
// combined Nodes and rels
93+
setCombinedNodes([]);
94+
setCombinedRels([]);
8995
setCombinedPatterns([]);
96+
// Data Importer
97+
setImporterNodes([]);
98+
setImporterPattern([]);
99+
setImporterRels([]);
90100
setSelectedPreDefOption(null);
91101
onClose();
92102
};

0 commit comments

Comments
 (0)