Skip to content

Commit a4dee22

Browse files
authored
Merge branch 'main' into service-access
2 parents 4412331 + d206969 commit a4dee22

22 files changed

+1330
-673
lines changed

packages/libs/eda/src/lib/core/components/computations/Types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface ComputationConfigProps extends ComputationProps {
2727
variableCollection: CollectionVariableTreeNode
2828
) => boolean; // Additional constraints for allowed collection variables
2929
hideConfigurationComponent?: boolean; // Whether to hide the configuration component entirely
30+
readonlyInputNames?: string[]; // Input names managed externally (e.g. by SharedComputeInputsNotebookCell). Plugins render these as read-only.
3031
}
3132

3233
export interface ComputationOverviewProps extends ComputationProps {}

packages/libs/eda/src/lib/core/components/computations/plugins/differentialExpression.tsx

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
useFindEntityAndVariable,
2222
useSubsettingClient,
2323
} from '../../../hooks/workspace';
24-
import { ReactNode, useEffect, useMemo, useRef } from 'react';
24+
import { ReactNode, useCallback, useEffect, useMemo, useRef } from 'react';
2525
import { ComputationStepContainer } from '../ComputationStepContainer';
2626
import { ValuePicker } from '../../visualizations/implementations/ValuePicker';
2727
import { useToggleStarredVariable } from '../../../hooks/starredVariables';
@@ -38,7 +38,7 @@ import {
3838
import { IsEnabledInPickerParams } from '../../visualizations/VisualizationTypes';
3939
import { entityTreeToArray } from '../../../utils/study-metadata';
4040
import { InputVariables } from '../../visualizations/InputVariables';
41-
import { enqueueSnackbar } from 'notistack';
41+
import useSnackbar from '@veupathdb/coreui/lib/components/notifications/useSnackbar';
4242
import { useCachedPromise } from '../../../hooks/cachedPromise';
4343
import { DataElementConstraintRecord } from '../../../utils/data-element-constraints';
4444
import { DifferentialExpressionConfig } from '../../../types/apps';
@@ -252,11 +252,13 @@ export function DifferentialExpressionConfiguration(
252252
visualizationId,
253253
changeConfigHandlerOverride,
254254
showStepNumber = true,
255+
readonlyInputNames,
255256
} = props;
256257

257258
const configuration = computation.descriptor
258259
.configuration as DifferentialExpressionConfig;
259260
const studyMetadata = useStudyMetadata();
261+
const { enqueueSnackbar } = useSnackbar();
260262
const dataClient = useDataClient();
261263
const toggleStarredVariable = useToggleStarredVariable(props.analysisState);
262264
const filters = analysisState.analysis?.descriptor.subset.descriptor;
@@ -286,11 +288,6 @@ export function DifferentialExpressionConfiguration(
286288
);
287289

288290
useEffect(() => {
289-
if (
290-
!configuration.comparator ||
291-
(!configuration.comparator.groupA && !configuration.comparator.groupB)
292-
)
293-
return;
294291
if (
295292
previousSubset.current &&
296293
!isEqual(
@@ -301,20 +298,25 @@ export function DifferentialExpressionConfiguration(
301298
previousSubset.current =
302299
analysisState.analysis?.descriptor.subset.descriptor;
303300

304-
// Reset the groupA and groupB values.
305-
changeConfigHandler('comparator', {
306-
variable: configuration.comparator.variable,
307-
groupA: undefined,
308-
groupB: undefined,
309-
});
310-
311-
enqueueSnackbar(
312-
<span>
313-
Reset differential expression group A and B values due to changed
314-
subset.
315-
</span>,
316-
{ variant: 'info' }
317-
);
301+
if (
302+
configuration.comparator &&
303+
(configuration.comparator.groupA || configuration.comparator.groupB)
304+
) {
305+
// Reset the groupA and groupB values.
306+
changeConfigHandler('comparator', {
307+
variable: configuration.comparator.variable,
308+
groupA: undefined,
309+
groupB: undefined,
310+
});
311+
312+
enqueueSnackbar(
313+
<span>
314+
Reset differential expression reference and comparison group
315+
specification due to changed subset.
316+
</span>,
317+
{ variant: 'info' }
318+
);
319+
}
318320
}
319321
}, [
320322
analysisState.analysis?.descriptor.subset.descriptor,
@@ -330,6 +332,17 @@ export function DifferentialExpressionConfiguration(
330332
[studyMetadata]
331333
);
332334

335+
// Helper to get display name for a variable descriptor (used for read-only labels)
336+
const getVariableDisplayName = useCallback(
337+
(varDescriptor: any) => {
338+
if (!varDescriptor) return undefined;
339+
const result = findEntityAndVariable(varDescriptor);
340+
if (!result) return undefined;
341+
return `${result.entity.displayName} > ${result.variable.displayName}`;
342+
},
343+
[findEntityAndVariable]
344+
);
345+
333346
const selectedComparatorVariable = useMemo(() => {
334347
if (
335348
configuration &&
@@ -458,17 +471,33 @@ export function DifferentialExpressionConfiguration(
458471
label: 'Gene Identifier',
459472
role: 'axis',
460473
titleOverride: 'Expression Data',
474+
...(readonlyInputNames?.includes('identifierVariable')
475+
? {
476+
readonlyValue:
477+
getVariableDisplayName(
478+
configuration.identifierVariable
479+
) ?? 'Not selected',
480+
}
481+
: {}),
461482
},
462483
{
463484
name: 'valueVariable',
464485
label: 'Count type',
465486
role: 'axis',
487+
...(readonlyInputNames?.includes('valueVariable')
488+
? {
489+
readonlyValue:
490+
getVariableDisplayName(configuration.valueVariable) ??
491+
'Not selected',
492+
}
493+
: {}),
466494
},
467495
{
468496
name: 'comparatorVariable',
469497
label: 'Metadata Variable',
470498
role: 'stratification',
471499
titleOverride: 'Group Comparison',
500+
styleOverride: { minWidth: '30em' },
472501
},
473502
]}
474503
entities={entities}
@@ -479,14 +508,18 @@ export function DifferentialExpressionConfiguration(
479508
}}
480509
onChange={(vars) => {
481510
if (
511+
!readonlyInputNames?.includes('identifierVariable') &&
482512
vars.identifierVariable !== configuration.identifierVariable
483513
) {
484514
changeConfigHandler(
485515
'identifierVariable',
486516
vars.identifierVariable
487517
);
488518
}
489-
if (vars.valueVariable !== configuration.valueVariable) {
519+
if (
520+
!readonlyInputNames?.includes('valueVariable') &&
521+
vars.valueVariable !== configuration.valueVariable
522+
) {
490523
changeConfigHandler('valueVariable', vars.valueVariable);
491524
}
492525
if (
@@ -508,6 +541,7 @@ export function DifferentialExpressionConfiguration(
508541
analysisState.analysis?.descriptor.starredVariables ?? []
509542
}
510543
toggleStarredVariable={toggleStarredVariable}
544+
labelWidth="12em"
511545
/>
512546
</div>
513547
<div className={cx('-DiffExpressionOuterConfigContainer')}>

packages/libs/eda/src/lib/core/components/computations/plugins/dimensionalityReduction.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import './Plugins.scss';
1717
import { makeClassNameHelper } from '@veupathdb/wdk-client/lib/Utils/ComponentUtils';
1818
import { IsEnabledInPickerParams } from '../../visualizations/VisualizationTypes';
1919
import { entityTreeToArray } from '../../../utils/study-metadata';
20-
import { useMemo } from 'react';
20+
import { useCallback, useMemo } from 'react';
2121
import { InputVariables } from '../../visualizations/InputVariables';
2222
import { useToggleStarredVariable } from '../../../hooks/starredVariables';
2323
import { DataElementConstraintRecord } from '../../../utils/data-element-constraints';
@@ -147,6 +147,7 @@ export function DimensionalityReductionConfiguration(
147147
visualizationId,
148148
changeConfigHandlerOverride,
149149
showStepNumber = true,
150+
readonlyInputNames,
150151
} = props;
151152

152153
assertComputationWithConfig(computation, DimensionalityReductionConfig);
@@ -165,6 +166,20 @@ export function DimensionalityReductionConfiguration(
165166
const changeConfigHandler =
166167
changeConfigHandlerOverride ?? workspaceChangeConfigHandler;
167168

169+
const filters = analysisState.analysis?.descriptor.subset.descriptor;
170+
const findEntityAndVariable = useFindEntityAndVariable(filters);
171+
172+
// Helper to get display name for a variable descriptor (used for read-only labels)
173+
const getVariableDisplayName = useCallback(
174+
(varDescriptor: any) => {
175+
if (!varDescriptor) return undefined;
176+
const result = findEntityAndVariable(varDescriptor);
177+
if (!result) return undefined;
178+
return `${result.entity.displayName} > ${result.variable.displayName}`;
179+
},
180+
[findEntityAndVariable]
181+
);
182+
168183
const entities = useMemo(
169184
() =>
170185
studyMetadata?.rootEntity
@@ -183,19 +198,34 @@ export function DimensionalityReductionConfiguration(
183198
>
184199
<div className={cx()}>
185200
<div className={cx('-DiffExpressionOuterConfigContainer')}>
186-
<H6>Expression Data</H6>
201+
<H6>Input Data</H6>
187202
<InputVariables
188203
inputs={[
189204
{
190205
name: 'identifierVariable',
191206
label: 'Gene Identifier',
192207
role: 'axis',
193208
titleOverride: 'Expression Data',
209+
...(readonlyInputNames?.includes('identifierVariable')
210+
? {
211+
readonlyValue:
212+
getVariableDisplayName(
213+
configuration.identifierVariable
214+
) ?? 'Not selected',
215+
}
216+
: {}),
194217
},
195218
{
196219
name: 'valueVariable',
197220
label: 'Count type',
198221
role: 'axis',
222+
...(readonlyInputNames?.includes('valueVariable')
223+
? {
224+
readonlyValue:
225+
getVariableDisplayName(configuration.valueVariable) ??
226+
'Not selected',
227+
}
228+
: {}),
199229
},
200230
]}
201231
entities={entities}
@@ -205,14 +235,18 @@ export function DimensionalityReductionConfiguration(
205235
}}
206236
onChange={(vars) => {
207237
if (
238+
!readonlyInputNames?.includes('identifierVariable') &&
208239
vars.identifierVariable !== configuration.identifierVariable
209240
) {
210241
changeConfigHandler(
211242
'identifierVariable',
212243
vars.identifierVariable
213244
);
214245
}
215-
if (vars.valueVariable !== configuration.valueVariable) {
246+
if (
247+
!readonlyInputNames?.includes('valueVariable') &&
248+
vars.valueVariable !== configuration.valueVariable
249+
) {
216250
changeConfigHandler('valueVariable', vars.valueVariable);
217251
}
218252
}}
@@ -222,6 +256,7 @@ export function DimensionalityReductionConfiguration(
222256
analysisState.analysis?.descriptor.starredVariables ?? []
223257
}
224258
toggleStarredVariable={toggleStarredVariable}
259+
labelWidth="12em"
225260
/>
226261
</div>
227262
</div>

0 commit comments

Comments
 (0)