ATLAS-5322: Fix glossary bulk import relation parsing and error reporting. - #712
ATLAS-5322: Fix glossary bulk import relation parsing and error reporting.#712UmeshPatil-1 wants to merge 2 commits into
Conversation
pawarprasad123
left a comment
There was a problem hiding this comment.
UI comments added
| const successCount = response.successImportInfoList?.length || 0; | ||
| const totalCount = failedCount + successCount; | ||
|
|
||
| return `Glossary import completed with ${failedCount} failure(s) out of ${totalCount} term(s). See error details.`; |
There was a problem hiding this comment.
Summary string is hardcoded glossary-specific ("Glossary import completed...")
- Consider renaming to make scope explicit, e.g. buildGlossaryImportFailureSummary, and do not reuse for Business Metadata
| export const formatGlossaryImportFailure = ( | ||
| failure: GlossaryImportFailure | ||
| ): string => { | ||
| const termLabel = |
There was a problem hiding this comment.
Requires both childObjectName and parentObjectName for @ format
-add test for childObjectName-only case (same-glossary shorthand failures from backend)
| toast.dismiss(toastId.current); | ||
| toastId.current = toast.error( | ||
| importResp.data.failedImportInfoList[0].remarks | ||
| buildGlossaryImportFailureSummary(importResp.data) |
There was a problem hiding this comment.
Critical issue Blovker: — Business Metadata regression:
ImportDialog serves both glossary and business metadata (title == "Import Business Metadata"). The PR applies glossary-specific formatting to the shared failure block:
toastId.current = toast.error(
buildGlossaryImportFailureSummary(importResp.data) // ← "Glossary import completed..."
);
-And error details use formatGlossaryImportFailure(), which assumes glossary semantics (child@parent). For business metadata, backend stores fields differently (parentObjectName = guid, childObjectName = attributes), producing misleading labels like attributes@guid: error.
solution:
ImportDialog is shared between glossary and business metadata imports. Please guard glossary-specific formatting:
const isGlossaryImport = title !== "Import Business Metadata";
toast.error(
isGlossaryImport
? buildGlossaryImportFailureSummary(importResp.data)
: importResp.data.failedImportInfoList[0]?.remarks ?? "Import failed"
);
Same guard needed in the error details list (line 207–218).
| toast.dismiss(toastId.current); | ||
| toastId.current = toast.error( | ||
| importResp.data.failedImportInfoList[0].remarks | ||
| buildGlossaryImportFailureSummary(importResp.data) |
There was a problem hiding this comment.
Please add tests for glossary import failure: summary toast, formatted error list, and back-to-upload navigation — similar to ImportDialog.test.tsx.
| }); | ||
| var modalTitle = '<div class="back-button importBackBtn" title="Back to import file"><i class="fa fa-angle-left "></i> </div> <div class="modal-name">Error Details</div>'; | ||
| _.each(response.failedImportInfoList, function(err_obj, index) { | ||
| var termLabel = err_obj.childObjectName || 'Unknown term'; |
There was a problem hiding this comment.
line 131–134
issue:
termLabel bug: if parentObjectName exists but childObjectName is missing, label becomes "undefined@Glossary"
Suggestion:
Match React logic: only use @ when both exist
var termLabel = 'Unknown term';
if (err_obj.childObjectName && err_obj.parentObjectName) {
termLabel = err_obj.childObjectName + '@' + err_obj.parentObjectName;
} else if (err_obj.childObjectName) {
termLabel = err_obj.childObjectName;
}
| failedCount = response.failedImportInfoList.length, | ||
| successCount = (response.successImportInfoList && response.successImportInfoList.length) || 0, | ||
| totalCount = failedCount + successCount, | ||
| notificationMsg = 'Glossary import completed with ' + failedCount + ' failure(s) out of ' + totalCount + ' term(s). See error details.'; |
There was a problem hiding this comment.
hardcoded "Glossary import completed..."
Use that.isGlossary for notification text; BM import should not say "Glossary import completed...".
Suggestion:
ImportLayoutView is used for BM too (isGlossary flag exists). Use that.isGlossary to pick message
| termLabel = err_obj.childObjectName + '@' + err_obj.parentObjectName; | ||
| } | ||
| errorStr += '<li>' + (index + 1) + '. ' + _.escape(termLabel) + ': ' + _.escape(err_obj.remarks || '') + '</li>'; | ||
| }); |
There was a problem hiding this comment.
line 131-136
Duplicated formatting logic vs React util
Acceptable for legacy JS, but consider extracting shared helper if both dashboards must stay in sync
| "Glossary import completed with 1 failure(s) out of 2 term(s). See error details." | ||
| ); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing negative / edge cases:
Only remarks (no names)
Only childObjectName
Empty both lists → "0 failure(s) out of 0 term(s)"
Only failures, no successes
Empty remarks → fallback "Import failed"
suggestion:
line 23:
Please add negative/edge tests: remarks-only, child-only, empty lists, failures-only (no successes).
| primary={`${index + 1}. ${formatGlossaryImportFailure(value)}`} | ||
| /> | ||
| </ListItem> | ||
| ) |
There was a problem hiding this comment.
Blocker:
Test Suites: 1 failed, 2 passed, 3 total
Tests: 1 failed, 48 passed, 49 total
Failure: ImportDialog.test.tsx — expectations not updated for new behavior:
Suggestion: (ImportDialog.test.tsx line ~103–122):
Tests must be updated to match new toast summary and formatted error lines. Also add a Business Metadata failure test to ensure glossary formatting is not applied there.
… resolved review comments.
What changes were proposed in this pull request?
Problem
GlossaryName:TermName,TermName@GlossaryName, and same-glossaryTermNameshorthand), but parsing/lookup was inconsistent.BulkImportResponse.Backend changes (repository)
GlossaryTermUtils.javaresolveRelatedTermReference()to normalize and validate three relation formats:TermName@GlossaryName(qualified name)GlossaryName:TermName(legacy colon format — backward compatible)TermName(same-glossary shorthand — best-effort, not a hard failure if unresolved)lookupGlossaryTermGuid()to resolve related terms from graph or in-import GUID cache.cacheImportedTermGuid()so terms created/seen during import are available for relation linking in pass 2.GlossaryService.javareconcileBulkImportResponse()after relation pass:successImportInfoListif they appear infailedImportInfoList(prevents misleading partial-success reporting)GlossaryServiceTest.javaglossary_healthcare_filled.csv— expects 20 successes, 0 failures.UI changes
React dashboard (
dashboard/)glossaryImportUtils.tswith:formatGlossaryImportFailure()→ e.g.Patient@Healthcare Glossary: Reference not foundbuildGlossaryImportFailureSummary()→ e.g.Glossary import completed with 1 failure(s) out of 2 term(s). See error details.ImportDialog.tsxandAddUpdateGlossaryForm.tsxto use formatted toast + Error Details list.glossaryImportUtils.test.tsLegacy dashboard (
dashboardv2/)ImportLayoutView.jsto show summary notification and formatted per-term errors in Error Details modal (always shown when failures exist).How was this patch tested?
Unit tests
GlossaryServiceTest— existing bulk import tests pass with updated invalid-relation expectationGlossaryServiceTest— new test withglossary_healthcare_filled.csv: 20 success, 0 failedglossaryImportUtils.test.ts— failure formatting and summary messageManual REST tests
Tested using glossary_healthcare_filled.csv (20 data rows + 1 header = 20 terms) and curl commands.
Health check — GET /api/atlas/v2/glossary?limit=1
Result: HTTP 200
Import healthcare CSV — POST /api/atlas/v2/glossary/import
Result: Success: 20, Failed: 0
Verify term count — GET /api/atlas/v2/glossary/{guid}
Result: Term count: 20
Patient term seeAlso relation — GET /api/atlas/v2/glossary/term/{patientTermGuid}
Result: seeAlso count: 1, linked to Provider
Provider preferredTerms — GET /api/atlas/v2/glossary/term/{providerTermGuid}
Result: 2 terms — Physician, Nurse
Colon format backward compatibility — import CSV with GlossaryName:TermName references
Result: Success: 2, Failed: 0
Negative test — invalid explicit @ reference — MissingTerm@BadRelGlossary
Result: Entry in failedImportInfoList with clear error (not silent drop)
Re-import same CSV (idempotency) — POST /api/atlas/v2/glossary/import
Result: Success: 20, Failed: 0
Automated verification script — scripts/atlas5322_verify.sh
Result: ALL CHECKS PASSED
Example import verification:
curl -s -u admin:admin -X POST
-F "file=@glossary_healthcare_filled.csv"
"http://localhost:21000/api/atlas/v2/glossary/import"
Expected: successImportInfoList size = 20, failedImportInfoList empty.
Example relation verification:
GET /api/atlas/v2/glossary/term/{patientTermGuid}
Expected: "seeAlso" contains Provider; Provider has 2 preferredTerms.
UI manual test