Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions src/components/map-projects/Candidates.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import AIAssistantButton from './AIAssistantButton'
import {
buildAlgorithmRowViews,
buildQualityRowViews,
conceptBelongsToTargetRepo,
sortRowViews,
conceptForMapping,
resolveAICandidateID
Expand Down Expand Up @@ -193,7 +194,7 @@ const SubHeader = ({count, onClick, isCollapsed, header, indicatorColor, indicat
}


const CandidateList = ({rowViews, header, rowIndex, sortBy, order, setShowItem, showItem, setShowHighlights, isSelectedForMap, onMap, onFetchMore, bgColor, headerIndicatorIcon, bucketId, display, onDisplayChange, noToolbar, toolbarControl, repoVersion, alignToolbarLeft, rightControl, analysis, showAnalysis, openAnalysis, onCloseAnalysis, isInProgress, AIRecommendedCandidateId, AIAlternateCandidateIds, locales, scispacy, showAlgo, collapsed, onCollapse, candidatesScore, algoScoreFirst, byAlgorithm, showEmptyHeader, isFirst, isCoreUser, targetCanonical, analysisPage, setAnalysisPage}) => {
const CandidateList = ({rowViews, header, rowIndex, sortBy, order, setShowItem, showItem, setShowHighlights, isSelectedForMap, onMap, onFetchMore, bgColor, headerIndicatorIcon, bucketId, display, onDisplayChange, noToolbar, toolbarControl, repoVersion, alignToolbarLeft, rightControl, analysis, showAnalysis, openAnalysis, onCloseAnalysis, isInProgress, AIRecommendedCandidateId, AIAlternateCandidateIds, locales, scispacy, showAlgo, collapsed, onCollapse, candidatesScore, algoScoreFirst, byAlgorithm, showEmptyHeader, isFirst, isCoreUser, targetCanonical, targetRelativeUrl, analysisPage, setAnalysisPage}) => {
// Decorate rowViews so they work for BOTH renderers:
// - Table view: SearchResults/TableResults reads legacy concept fields
// (id, url, names, descriptions, source, search_meta, ...) via the
Expand All @@ -218,12 +219,12 @@ const CandidateList = ({rowViews, header, rowIndex, sortBy, order, setShowItem,
})
// Helper: a rowView is mappable only when its concept belongs to the
// project's target repo (cascade targets in bridge flows DO; bridge
// intermediaries don't). targetCanonical comes from buildProjectContext
// in MapProject — the same canonical the normalizer used to stamp the
// ConceptDefinition.reference.url, so the comparison is exact.
// intermediaries don't). The comparison uses canonical URL in the
// common case, but also tolerates canonical drift via the OCL
// relative-URL fallback.
const isTargetRepoView = (view) => {
if(!targetCanonical) return true
return view?.conceptDefinition?.reference?.url === targetCanonical
if(!targetCanonical && !targetRelativeUrl) return true
return conceptBelongsToTargetRepo(view?.conceptDefinition, targetCanonical, targetRelativeUrl)
}
const results = {total: onFetchMore ? rowsForTable.length : 1, results: rowsForTable}
const isCollapsed = collapsed.includes(bucketId)
Expand Down Expand Up @@ -347,6 +348,7 @@ const CandidateList = ({rowViews, header, rowIndex, sortBy, order, setShowItem,
candidatesScore={candidatesScore}
algoScoreFirst={algoScoreFirst}
targetCanonical={targetCanonical}
targetRelativeUrl={targetRelativeUrl}
/>
}}
display={display}
Expand Down Expand Up @@ -387,7 +389,7 @@ const CandidateList = ({rowViews, header, rowIndex, sortBy, order, setShowItem,
// conceptCache — project-wide ConceptDefinition store, keyed by concept_key.
// algosSelected — algorithm definitions (for headers/grouping).
// (plans/unified-mapper-model.md "How the views map onto this model".)
const Candidates = ({rowIndex, alert, setAlert, rowState, conceptCache, targetCanonical, setShowItem, showItem, setShowHighlights, isSelectedForMap, onMap, onFetchMore, isLoading, candidatesScore, repoVersion, analysis, onFetchRecommendation, appliedFacets, setAppliedFacets, filters, facets, columns, defaultFilters, locales, models, selectedModel, onModelChange, promptTemplates, promptTemplate, onPromptTemplateChange, onRefreshClick, rowStage, inAIAssistantGroup, algosSelected, isCoreUser}) => {
const Candidates = ({rowIndex, alert, setAlert, rowState, conceptCache, targetCanonical, targetRelativeUrl, setShowItem, showItem, setShowHighlights, isSelectedForMap, onMap, onFetchMore, isLoading, candidatesScore, repoVersion, analysis, onFetchRecommendation, appliedFacets, setAppliedFacets, filters, facets, columns, defaultFilters, locales, models, selectedModel, onModelChange, promptTemplates, promptTemplate, onPromptTemplateChange, onRefreshClick, rowStage, inAIAssistantGroup, algosSelected, isCoreUser}) => {
const { t } = useTranslation();
const [sortBy, setSortBy] = React.useState('rerank_score')
const [groupBy, setGroupBy] = React.useState('quality')
Expand Down Expand Up @@ -451,9 +453,9 @@ const Candidates = ({rowIndex, alert, setAlert, rowState, conceptCache, targetCa
// by-algorithm browsing.
const qualityRowViews = React.useMemo(() => {
const views = buildQualityRowViews(rowState, conceptCache)
if(!targetCanonical) return views
return views.filter(v => v.conceptDefinition?.reference?.url === targetCanonical)
}, [rowState, conceptCache, targetCanonical])
if(!targetCanonical && !targetRelativeUrl) return views
return views.filter(v => conceptBelongsToTargetRepo(v.conceptDefinition, targetCanonical, targetRelativeUrl))
}, [rowState, conceptCache, targetCanonical, targetRelativeUrl])
const hasAnyView = qualityRowViews.length > 0
const isNoneLoaded = !rowState || (isEmpty(rowState.candidates) && isEmpty(rowState.algorithm_responses))
const canFetchMore = hasAnyView
Expand Down Expand Up @@ -487,6 +489,7 @@ const Candidates = ({rowIndex, alert, setAlert, rowState, conceptCache, targetCa
algoScoreFirst: algoScoreFirst,
isCoreUser: isCoreUser,
targetCanonical: targetCanonical,
targetRelativeUrl: targetRelativeUrl,
analysisPage: analysisPage,
setAnalysisPage: setAnalysisPage
}
Expand Down
7 changes: 4 additions & 3 deletions src/components/map-projects/Concept.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Retired from '../common/Retired'
import Score from './Score'
import MapButton from './MapButton'
import ConceptSummaryProperties from '../concepts/ConceptSummaryProperties'
import { conceptForMapping } from './viewBuilders.js'
import { conceptBelongsToTargetRepo, conceptForMapping } from './viewBuilders.js'

// Format a contributor descriptor for the convergence tooltip:
// "via CIEL:1234 Activated partial thromboplastin time — SAME-AS"
Expand Down Expand Up @@ -307,7 +307,7 @@ const legacyToRowView = (legacy) => {
// Legacy callers (Target Code column, decision tables, search results)
// pass a flat concept-shape object instead — legacyToRowView wraps those
// so a single render path covers both worlds while PR3 cleanup is pending.
const Concept = ({_id, firstChild, lastChild, concept, setShowHighlights, isShown, onCardClick, onMap, isSelectedForMap, noScore, repoVersion, isAIRecommended, sx, notClickable, noSynonymPrefix, locales, showAlgo, candidatesScore, algoScoreFirst, asTarget, AIRecommendedCandidateId, AIAlternateCandidateIds, targetCanonical}) => {
const Concept = ({_id, firstChild, lastChild, concept, setShowHighlights, isShown, onCardClick, onMap, isSelectedForMap, noScore, repoVersion, isAIRecommended, sx, notClickable, noSynonymPrefix, locales, showAlgo, candidatesScore, algoScoreFirst, asTarget, AIRecommendedCandidateId, AIAlternateCandidateIds, targetCanonical, targetRelativeUrl}) => {
const rowView = concept?.conceptDefinition ? concept : legacyToRowView(concept)
if(!rowView?.conceptDefinition) return null
const { type, candidate, conceptDefinition, conceptRow, bridgeConceptDefinition, bridgeChildren, bridgeContributors, contributingAlgorithmIds, contributingAlgorithms } = rowView
Expand All @@ -316,7 +316,8 @@ const Concept = ({_id, firstChild, lastChild, concept, setShowHighlights, isShow
// mappable themselves — they're reference metadata about the cascade.
// Pass isSelectedForMap=false to Item so it renders the placeholder
// spacer instead of a MapButton.
const isMappable = !targetCanonical || conceptDefinition?.reference?.url === targetCanonical
const isMappable = (!targetCanonical && !targetRelativeUrl)
|| conceptBelongsToTargetRepo(conceptDefinition, targetCanonical, targetRelativeUrl)
const effectiveIsSelectedForMap = isMappable ? isSelectedForMap : false
const idForUI = conceptDefinition.ocl_url || conceptDefinition.id || conceptDefinition.reference?.code
const isSelectedToShow = isShown ? isShown(idForUI) : false
Expand Down
Loading