import React from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Loading } from 'wdk-client/Components';
import { RootState } from 'wdk-client/Core/State/Types';
import { makeClassNameHelper } from 'wdk-client/Utils/ComponentUtils';
import { Question, RecordClass } from 'wdk-client/Utils/WdkModel';
import { AddStepOperationMenuProps } from 'wdk-client/Views/Strategy/AddStepPanel';
import { inputResultSetDescription } from 'wdk-client/Views/Strategy/AddStepUtils';
import 'wdk-client/Views/Strategy/ConvertStepMenu.scss';
const cx = makeClassNameHelper('ConvertStepMenu');
type StateProps = {
operatorChoices?: OperatorChoice[];
};
type OperatorChoice = { searchName: string, display: string };
type OwnProps = AddStepOperationMenuProps;
type Props = StateProps & OwnProps;
const ConvertStepMenuView = ({
inputRecordClass,
operandStep,
operatorChoices,
previousStep,
startOperationForm
}: Props) => (
{
!operatorChoices
?
:
Transform {inputResultSetDescription(operandStep.estimatedSize, inputRecordClass)} into...
{
!previousStep || operatorChoices.length === 0
? "No conversions available."
: (
<>
{
operatorChoices.map(({ searchName, display }) =>
)
}
>
)
}
}
);
const outputStepQuestion = (_: RootState, { outputStep, questionsByUrlSegment }: OwnProps) =>
outputStep && questionsByUrlSegment[outputStep.searchName]
// A search specifies a valid transform <=>
// (1) the search has a primary input and NO secondary input
// (2) the search's primary input is compatible with the input step's record class
// (3) if inserting before a step (the "output step"), the search's output record class is compatible with the output step's primary input
// (4) FIXME - ugly hardcoding - the search's outputRecordClassName is not "gene"
// (5) FIXME - ugly hardcoding - the search's shortDisplayName is not "Weight"
export const isValidTransformFactory = (inputRecordClass: RecordClass, outputStepQuestion?: Question) => (search: Question) =>
( // (1)
!!search.allowedPrimaryInputRecordClassNames && !search.allowedSecondaryInputRecordClassNames
) &&
( // (2)
search.allowedPrimaryInputRecordClassNames.includes(inputRecordClass.urlSegment)
) &&
( // (3)
!outputStepQuestion ||
!!outputStepQuestion.allowedPrimaryInputRecordClassNames &&
outputStepQuestion.allowedPrimaryInputRecordClassNames.includes(search.outputRecordClassName)
) &&
( // (4)
search.outputRecordClassName !== 'gene'
) &&
( // (5)
search.shortDisplayName !== 'Weight'
);
const isValidTransform = createSelector(
(_: RootState, { inputRecordClass }: OwnProps) => inputRecordClass,
outputStepQuestion,
isValidTransformFactory
);
const transformToOperatorChoiceFactory = (recordClassesByUrlSegment: Record, inputRecordClass: RecordClass) => (transform: Question): OperatorChoice => {
const outputRecordClass = recordClassesByUrlSegment[transform.outputRecordClassName];
if (!outputRecordClass) {
throw new Error(`Invalid record class with url segment '${transform.outputRecordClassName}' was encountered.`);
}
return {
searchName: transform.urlSegment,
display: inputRecordClass.urlSegment !== outputRecordClass.urlSegment
? outputRecordClass.displayNamePlural
: transform.shortDisplayName
};
};
const transformToOperatorChoice = createSelector(
(_: RootState, { recordClassesByUrlSegment }: OwnProps) => recordClassesByUrlSegment,
(_: RootState, { inputRecordClass }: OwnProps) => inputRecordClass,
(recordClassesByUrlSegment, inputRecordClass) => transformToOperatorChoiceFactory(recordClassesByUrlSegment, inputRecordClass)
);
const operatorChoices = createSelector(
(_: RootState, { questions }: OwnProps) => questions,
isValidTransform,
transformToOperatorChoice,
(questions, isValidTransform, transformToOperatorChoice) =>
questions &&
transformToOperatorChoice &&
questions
.filter(isValidTransform)
.map(transformToOperatorChoice)
);
const mapStateToProps = (state: RootState, props: OwnProps): StateProps => ({
operatorChoices: operatorChoices(state, props)
});
export const ConvertStepMenu = connect(mapStateToProps)(ConvertStepMenuView);