View details for different persons without rebuilding the tree (#281)

This commit is contained in:
Frank Buchholz
2026-04-20 17:41:03 +02:00
committed by GitHub
parent fbe82dd9fc
commit 4800b04eb1
2 changed files with 30 additions and 3 deletions

View File

@@ -224,6 +224,8 @@ export function App() {
const [data, setData] = useState<TopolaData>(); const [data, setData] = useState<TopolaData>();
/** Selected individual. */ /** Selected individual. */
const [selection, setSelection] = useState<IndiInfo>(); const [selection, setSelection] = useState<IndiInfo>();
/** Selected individual which should be displayed in the details pane. */
const [detailIndi, setDetailIndi] = useState<string>();
/** Error to display. */ /** Error to display. */
const [error, setError] = useState<string>(); const [error, setError] = useState<string>();
/** Whether the side panel is shown. */ /** Whether the side panel is shown. */
@@ -257,6 +259,7 @@ export function App() {
selection!.generation !== newSelection.generation selection!.generation !== newSelection.generation
) { ) {
setSelection(newSelection); setSelection(newSelection);
setDetailIndi(newSelection.id);
} }
} }
@@ -380,6 +383,7 @@ export function App() {
// Set state from URL parameters. // Set state from URL parameters.
setSourceSpec(args.sourceSpec); setSourceSpec(args.sourceSpec);
setSelection(args.selection); setSelection(args.selection);
setDetailIndi(args.selection?.id);
setStandalone(args.standalone); setStandalone(args.standalone);
setShowWikiTreeMenus(args.showWikiTreeMenus); setShowWikiTreeMenus(args.showWikiTreeMenus);
setChartType(args.chartType); setChartType(args.chartType);
@@ -414,6 +418,7 @@ export function App() {
const newSelection = getSelection(data.chartData, args.selection); const newSelection = getSelection(data.chartData, args.selection);
setData(data); setData(data);
setSelection(newSelection); setSelection(newSelection);
setDetailIndi(newSelection.id);
setState(AppState.SHOWING_CHART); setState(AppState.SHOWING_CHART);
} catch (error: any) { } catch (error: any) {
setState(AppState.SHOWING_CHART); setState(AppState.SHOWING_CHART);
@@ -456,6 +461,13 @@ export function App() {
gen: selection.generation, gen: selection.generation,
}); });
} }
/**
* Called when the user shift+clicks an individual box in the chart.
* Shows the individual in the details pane.
*/
function onDetailSelection(selection: IndiInfo) {
setDetailIndi(selection.id);
}
function onPrint() { function onPrint() {
analyticsEvent('print'); analyticsEvent('print');
@@ -524,6 +536,7 @@ export function App() {
selection={selection} selection={selection}
chartType={chartType} chartType={chartType}
onSelection={onSelection} onSelection={onSelection}
onDetailSelection={onDetailSelection}
freezeAnimation={freezeAnimation} freezeAnimation={freezeAnimation}
colors={config.color} colors={config.color}
hideIds={config.id} hideIds={config.id}
@@ -550,7 +563,7 @@ export function App() {
<SidebarPushable> <SidebarPushable>
<SidePanel <SidePanel
data={data!} data={data!}
selectedIndiId={updatedSelection.id} selectedIndiId={detailIndi || updatedSelection.id}
config={config} config={config}
expanded={showSidePanel} expanded={showSidePanel}
onToggle={onToggleSidePanel} onToggle={onToggleSidePanel}

View File

@@ -314,6 +314,7 @@ export interface ChartProps {
selection: IndiInfo; selection: IndiInfo;
chartType: ChartType; chartType: ChartType;
onSelection: (indiInfo: IndiInfo) => void; onSelection: (indiInfo: IndiInfo) => void;
onDetailSelection: (indiInfo: IndiInfo) => void;
freezeAnimation?: boolean; freezeAnimation?: boolean;
colors?: ChartColors; colors?: ChartColors;
hideIds?: Ids; hideIds?: Ids;
@@ -370,7 +371,16 @@ class ChartWrapper {
chartType: getChartType(props.chartType), chartType: getChartType(props.chartType),
renderer: getRendererType(props.chartType), renderer: getRendererType(props.chartType),
svgSelector: '#chart', svgSelector: '#chart',
indiCallback: (info) => props.onSelection(info), indiCallback: (info) => { // ths is called when an individual is selected in the chart
if (info.modifiers?.shiftKey) {
// If the shift key is pressed, we just update the details tab without changing the selection in the chart.
// This allows users to quickly view details of multiple individuals without losing their place in the chart.
props.onDetailSelection(info)
} else {
// If the shift key is not pressed, we update the selection in the chart as usual.
props.onSelection(info)
}
},
colors: chartColors.get(props.colors!), colors: chartColors.get(props.colors!),
animate: true, animate: true,
updateSvgSize: false, updateSvgSize: false,
@@ -474,7 +484,11 @@ export function Chart(props: ChartProps) {
const resetPosition = const resetPosition =
props.chartType !== prevProps?.chartType || props.chartType !== prevProps?.chartType ||
props.data !== prevProps.data || props.data !== prevProps.data ||
props.selection !== prevProps.selection; // This does not work as the objects are always different instances.
//props.selection !== prevProps.selection;
// Therefore, compare id and generation instead.
props.selection.id !== prevProps.selection.id ||
props.selection.generation !== prevProps.selection.generation;
chartWrapper.current.renderChart(props, intl, { chartWrapper.current.renderChart(props, intl, {
initialRender, initialRender,
resetPosition, resetPosition,