import { orderBy, partition } from 'lodash'; import React from 'react'; import { ofType } from 'redux-observable'; import { EMPTY, from, merge, of } from 'rxjs'; import { mergeMap } from 'rxjs/operators'; import { DatasetParam, Parameter } from 'wdk-client/Utils/WdkModel'; import { StrategySummary } from 'wdk-client/Utils/WdkUser'; import { datasetItemToString, idListToArray } from 'wdk-client/Views/Question/Params/DatasetParamUtils'; import { Props, Context, createParamModule, ParamModule } from 'wdk-client/Views/Question/Params/Utils'; import { makeClassNameHelper } from 'wdk-client/Utils/ComponentUtils'; import 'wdk-client/Views/Question/Params/DatasetParam.scss'; import { DatasetConfig } from 'wdk-client/Service/Mixins/DatasetsService'; import { INIT_PARAM, InitParamAction } from 'wdk-client/Actions/QuestionActions'; import { SET_BASKET_COUNT, SET_FILE, SET_FILE_PARSER, SET_ID_LIST, SET_LOADING_ID_LIST, SET_SOURCE_TYPE, SET_STRATEGY_ID, SET_STRATEGY_LIST, SET_URL, SET_URL_PARSER, setBasketCount, setFile, setFileParser, setIdList, setLoadingIdList, setSourceType, setStrategyId, setStrategyList, setUrl, setUrlParser, } from 'wdk-client/Actions/DatasetParamActions'; import { Action } from 'wdk-client/Actions'; import { TextBox } from 'wdk-client/Components'; const cx = makeClassNameHelper('wdk-DatasetParam'); // TODO We will have to include an onSubmit hook that will convert the user's // selection to a Dataset using the DatasetService. We need an API that allows // awaiting of some sort, using Promises, some state flag, or something else. type State = { sourceType: | 'idList' | 'file' | 'basket' | 'strategy' | 'url'; idList?: string; loadingIdList?: boolean; file?: File | null; strategyList?: StrategySummary[]; strategyId?: number; basketCount?: number; fileParser?: DatasetParam['parsers'][number]['name']; url?: string; urlParser?: DatasetParam['parsers'][number]['name']; } function isType(parameter: Parameter): parameter is DatasetParam { return parameter.type === 'input-dataset'; } function isParamValueValid(ctx: Context) { // return !isEmpty(ctx.paramValues[ctx.parameter.name]); return true; } const defaultState: State = { sourceType: 'idList' } const getInitialParser = (parameter: DatasetParam) => parameter.parsers[0].name function reduce(state: State = defaultState, action: Action): State { switch(action.type) { case INIT_PARAM: { const { parameter, initialParamData } = action.payload; const initialListName = `${parameter.name}.idList`; const initialList = initialParamData?.[initialListName]; const initialUrlName = `${parameter.name}.url`; const initialUrl = initialParamData?.[initialUrlName]; return { ...state, sourceType: initialUrl != null ? 'url' : 'idList', idList: initialList != null ? initialList : (parameter as DatasetParam).defaultIdList, url: initialUrl, } } case SET_SOURCE_TYPE: return { ...state, sourceType: action.payload.sourceType }; case SET_ID_LIST: return { ...state, idList: action.payload.idList }; case SET_LOADING_ID_LIST: { return { ...state, loadingIdList: action.payload.loadingIdList }; } case SET_FILE: return { ...state, file: action.payload.file }; case SET_STRATEGY_LIST: return { ...state, strategyList: action.payload.strategyList, strategyId: action.payload.strategyList.length > 0 ? action.payload.strategyList[0].strategyId : undefined }; case SET_STRATEGY_ID: return { ...state, strategyId: action.payload.strategyId }; case SET_BASKET_COUNT: return { ...state, basketCount: action.payload.basketCount }; case SET_FILE_PARSER: return { ...state, fileParser: action.payload.fileParser }; case SET_URL: return { ...state, url: action.payload.url }; case SET_URL_PARSER: return { ...state, urlParser: action.payload.urlParser }; default: return state; } } const getIdList = (uiState: State, parameter: DatasetParam) => uiState.idList const getParser = ( parserStateSelector: (uiState: State) => string | undefined, uiState: State, parameter: DatasetParam ) => { const parserState = parserStateSelector(uiState); return parserState == null ? getInitialParser(parameter) : parserState; } const getStrategyId = (uiState: State, parameter: DatasetParam) => uiState.strategyId != null ? uiState.strategyId : uiState.strategyList && uiState.strategyList.length > 0 ? uiState.strategyList[0].strategyId : undefined; type Section = { sourceType: State['sourceType']; label: string; render: React.StatelessComponent>; isAvailable?: (props: Props) => boolean; } const sections: Section[] = [ { sourceType: 'idList', label: 'Enter a list of IDs or text', isAvailable: ({ uiState }) => !uiState.loadingIdList, render: ({ ctx, dispatch, parameter, uiState }) =>