lodash#reduce TypeScript Examples
The following examples show how to use
lodash#reduce.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts From erda-ui with GNU Affero General Public License v3.0 | 7 votes |
getNodeById = ({ treeData, id, recycled = true }: IById): TEST_SET.TestSetNode | any =>
reduce(
treeData,
(result, single: any) => {
if (result) {
// 已经查出来了
return result;
}
if (id === single.id && recycled === single.recycled) {
// 找到了
return single;
}
// 继续在子级查找
return getNodeById({ treeData: single.children, id, recycled });
},
null,
)
Example #2
Source File: utils.ts From erda-ui with GNU Affero General Public License v3.0 | 7 votes |
getNodeByPath = ({ treeData, eventKey, valueKey }: IFunc): any => {
if (!eventKey) {
return '';
}
const list = eventKey.split('-').join(' children ').split(' ');
if (valueKey) list.push(valueKey);
return reduce(
list,
(result, singleKey) => {
if (!result) {
// 第一次
const firstKey = get(treeData, [0, 'key']);
if (firstKey === singleKey) {
return get(treeData, [0]);
}
} else if (singleKey === 'children') {
// 子节点则继续返回
return get(result, ['children']);
} else if (isArray(result)) {
// 获取children中匹配的node
return find(result, ({ id }: any) => `${id}` === singleKey);
}
// 最终单个节点的某个字段,比如key、title、id等
return get(result, [singleKey]);
},
'',
);
}
Example #3
Source File: headerUtil.ts From S2 with MIT License | 6 votes |
generateSheetConfig = (
sheet: SpreadSheet,
result: SwitcherResult,
) => {
// 交叉表需要过滤掉被隐藏的字段,而明细表不需要,明细表需要将隐藏的字段通过hiddenColumnFields返回给options
const isTableSheet = sheet instanceof TableSheet;
const fields = SWITCHER_FIELDS.reduce((fields, fieldKey) => {
const items = result[fieldKey]?.items ?? [];
const hideItems = result[fieldKey]?.hideItems ?? [];
fields[fieldKey] = filter(
items,
(item) => !hideItems.find((hide) => !isTableSheet && hide.id === item.id),
).map((i) => i.id);
return fields;
}, {} as Fields);
const hiddenColumnFields = isTableSheet
? result[FieldType.Cols].hideItems.map((i) => i.id)
: undefined;
return { fields, hiddenColumnFields };
}
Example #4
Source File: api-editor.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
getConf = (data: Record<string, any>, key: string | string[]) => {
return isArray(key)
? reduce(
key,
(obj, k) => {
return { ...obj, [k]: data[k] };
},
{},
)
: data[key];
}
Example #5
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
topNMap = reduce(
topNConfig,
(prev, next) => {
return {
...prev,
[`service-list@${next.key}`]: {
op: {
clickRow: (item: CP_DATA_RANK.IItem) => {
listDetail(item.id, item.name);
},
},
props: {
theme: [
{
titleIcon: next.icon,
color: next.color,
},
],
},
},
};
},
{},
)
Example #6
Source File: overview.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
topNMap = reduce(
topNConfig,
(prev, next) => {
return {
...prev,
[`service-overview@${next.key}`]: {
props: {
theme: [
{
titleIcon: next.icon,
color: next.color,
},
],
},
},
};
},
{},
)
Example #7
Source File: paramsSerializer.ts From linkedin-private-api with MIT License | 6 votes |
paramsSerializer = (params: Record<string, string | Record<string, string>>): string => {
const encodedParams = mapValues(params, value => {
if (!isArray(value) && !isPlainObject(value)) {
return value.toString();
}
if (isArray(value)) {
return `List(${value.join(',')})`;
}
const encodedList = reduce(
value as Record<string, string>,
(res, filterVal, filterKey) => `${res}${res ? ',' : ''}${encodeFilter(filterVal, filterKey)}`,
'',
);
return `List(${encodedList})`;
});
return stringify(encodedParams, undefined, undefined, {
encodeURIComponent: uri => uri,
});
}
Example #8
Source File: apiConfig.ts From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
multiGroupsAndDimensionDataHandler =
(dataKeys: string[], tagLength?: number) => (originData: IOriginData) => {
if (isEmpty(originData)) return {};
const { time = [], results = [] } = originData || {};
const data = get(results, '[0].data') || [];
const parsedData = reduce(
data,
(result: any, value) => {
const reData: any[] = [];
const ip = value[dataKeys[0]].tag.slice(0, tagLength || 8);
forEach(dataKeys, (item) => {
const dataItem: any = value[item];
if (dataItem) {
dataItem.tag = dataItem.name;
reData.push(dataItem);
}
});
return { ...result, [ip]: reData };
},
{},
);
return { time, results: parsedData };
}
Example #9
Source File: login.ts From linkedin-private-api with MIT License | 6 votes |
private setRequestHeaders({ cookies }: { cookies: AuthCookies }): void {
const cookieStr = reduce(cookies, (res, v, k) => `${res}${k}="${v}"; `, '');
this.client.request.setHeaders({
...requestHeaders,
cookie: cookieStr,
'csrf-token': cookies.JSESSIONID!,
});
}
Example #10
Source File: headerUtil.ts From S2 with MIT License | 6 votes |
getSwitcherFields = (result: SwitcherResult) => {
return reduce(
result,
(cfg, value, field) => {
cfg.fields[field] = map(value.items, 'id');
cfg.hiddenFields.push(...map(value.hideItems, 'id'));
return cfg;
},
{
fields: {},
hiddenFields: [],
} as { fields: Fields; hiddenFields: string[] },
);
}
Example #11
Source File: headerUtil.ts From S2 with MIT License | 6 votes |
generateSwitcherFields = (
sheet: SpreadSheet,
{ fields = {}, meta = [] } = {} as Pick<S2DataConfig, 'fields' | 'meta'>,
hiddenColumnFields: string[] = [],
) => {
return SWITCHER_FIELDS.reduce((config, fieldKey) => {
const values = fields[fieldKey];
if (isEmpty(values)) {
return config;
}
const items = map(values, (id) => {
const target = find(meta, ['field', id]);
return {
id,
displayName: target?.name,
checked: !hiddenColumnFields.includes(id),
};
});
config[fieldKey] = { items, ...getSwitcherFieldCfg(sheet, fieldKey) };
return config;
}, {} as SwitcherFields);
}
Example #12
Source File: pivot-data-set.ts From S2 with MIT License | 6 votes |
/**
* 获取查询结果中的纬度值
* @param dimensions [province, city]
* @param query { province: '四川省', city: '成都市', type: '办公用品' }
* @returns ['四川省', '成都市']
*/
export function getQueryDimValues(
dimensions: string[],
query: DataType,
): string[] {
return reduce(
dimensions,
(res: string[], dimension: string) => {
// push undefined when not exist
res.push(query[dimension]);
return res;
},
[],
);
}
Example #13
Source File: data-set-operate.ts From S2 with MIT License | 6 votes |
flattenDeep = (data: Record<any, any>[] | Record<any, any>) =>
keys(data)?.reduce((pre, next) => {
const item = get(data, next);
if (Array.isArray(item)) {
pre = pre.concat(flattenDeep(item));
} else {
pre?.push(item);
}
return pre;
}, [])
Example #14
Source File: data-set-operate.ts From S2 with MIT License | 6 votes |
/**
* split total data from origin list data.
*/
export function splitTotal(rawData: Data[], fields: Fields): Data[] {
const { rows, columns } = fields;
return reduce(
rawData,
(result: Data[], data: Data) => {
if (isTotalData([].concat(rows).concat(columns), data)) {
result.push(data);
}
return result;
},
[],
);
}
Example #15
Source File: pivot-facet.ts From S2 with MIT License | 6 votes |
public getViewCellHeights(layoutResult: LayoutResult) {
const { rowLeafNodes } = layoutResult;
const heights = reduce(
rowLeafNodes,
(result: number[], node: Node) => {
result.push(last(result) + node.height);
return result;
},
[0],
);
return {
getTotalHeight: () => {
return last(heights);
},
getCellOffsetY: (index: number) => {
return heights[index];
},
getTotalLength: () => {
// 多了一个数据 [0]
return heights.length - 1;
},
getIndexRange: (minHeight: number, maxHeight: number) => {
return getIndexRangeWithOffsets(heights, minHeight, maxHeight);
},
};
}
Example #16
Source File: pivot-facet.ts From S2 with MIT License | 6 votes |
/**
* @description Auto calculate row no-leaf node's height and y coordinate
* @param rowLeafNodes
*/
private autoCalculateRowNodeHeightAndY(rowLeafNodes: Node[]) {
// 3、in grid type, all no-leaf node's height, y are auto calculated
let prevRowParent = null;
const leafNodes = rowLeafNodes.slice(0);
while (leafNodes.length) {
const node = leafNodes.shift();
const parent = node.parent;
if (prevRowParent !== parent && parent) {
leafNodes.push(parent);
// parent's y = first child's y
parent.y = parent.children[0].y;
// parent's height = all children's height
parent.height = parent.children
.map((value) => value.height)
.reduce((sum, current) => sum + current, 0);
prevRowParent = parent;
}
}
}
Example #17
Source File: pivot-facet.ts From S2 with MIT License | 6 votes |
/**
* Auto Auto Auto column no-leaf node's width and x coordinate
* @param colLeafNodes
*/
private autoCalculateColNodeWidthAndX(colLeafNodes: Node[]) {
let prevColParent = null;
const leafNodes = colLeafNodes.slice(0);
while (leafNodes.length) {
const node = leafNodes.shift();
const parent = node.parent;
if (prevColParent !== parent && parent) {
leafNodes.push(parent);
// parent's x = first child's x
parent.x = parent.children[0].x;
// parent's width = all children's width
parent.width = parent.children
.map((value: Node) => value.width)
.reduce((sum, current) => sum + current, 0);
prevColParent = parent;
}
}
}
Example #18
Source File: base-facet.ts From S2 with MIT License | 6 votes |
calculateCellWidthHeight = () => {
const { colLeafNodes } = this.layoutResult;
const widths = reduce(
colLeafNodes,
(result: number[], node: Node) => {
result.push(last(result) + node.width);
return result;
},
[0],
);
this.viewCellWidths = widths;
this.viewCellHeights = this.getViewCellHeights(this.layoutResult);
};
Example #19
Source File: semantic-model-provider.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
// Load the library files from the file system.
// To save the libraries to the file system use downloadLibraries.
function loadLibraries(version: TestModelVersion): Record<string, Json> {
const inputFolder = getModelFolder(version);
const files = readdirSync(inputFolder);
const LIBFILE_SUFFIX = ".designtime.api.json";
const libFiles = filter(files, (_) => _.endsWith(LIBFILE_SUFFIX));
const libToFileContent = reduce(
libFiles,
(libToFileContentMap, file) => {
const libName = file.substring(0, file.length - LIBFILE_SUFFIX.length);
libToFileContentMap[libName] = readJsonSync(resolve(inputFolder, file));
return libToFileContentMap;
},
Object.create(null)
);
return libToFileContent;
}
Example #20
Source File: convert.ts From ui5-language-assistant with Apache License 2.0 | 5 votes |
export function convertToSemanticModel(
libraries: Record<string, Json>,
jsonSymbols: Record<string, apiJson.ConcreteSymbol>,
strict: boolean,
printValidationErrors: boolean
): model.UI5SemanticModel {
const model: model.UI5SemanticModel = {
version: "",
includedLibraries: [],
classes: newMap(),
enums: newMap(),
functions: newMap(),
namespaces: newMap(),
typedefs: newMap(),
interfaces: newMap(),
};
// Convert to array (with deterministic order) to ensure consistency when inserting to maps
const libsArray = map(libraries, (fileContent, libraryName) => ({
libraryName,
fileContent,
}));
const sortedLibs = sortBy(libsArray, "libraryName");
model.includedLibraries = map(sortedLibs, (_) => _.libraryName);
reduce(
sortedLibs,
(model, { libraryName, fileContent }) => {
fixLibrary(libraryName, fileContent);
if (
isLibraryFile(libraryName, fileContent, strict, printValidationErrors)
) {
const libSemanticModel = convertLibraryToSemanticModel(
libraryName,
fileContent,
jsonSymbols,
strict
);
addLibraryToModel(libSemanticModel, model);
} else if (strict) {
throw new Error(`Entry for ${libraryName} is not a valid library file`);
}
return model;
},
model
);
return model;
}
Example #21
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
selectArr = reduce(
cloudAccountArr,
(arr: any[], { name, val: value }) => {
if (name && value) arr.push({ value, name });
return arr;
},
[],
)
Example #22
Source File: table-drawer.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
TableDrawer = (props) => {
const [tableRowClassNameMap, setTableRowClassNameMap] = React.useState({});
const initTableRowClassNameMap = (_centerRelatedGroup: any) => {
const COLOR_KEYS = ['purple', 'pink', 'green', 'purple-2', 'blue', 'red', 'green-2', 'orange'];
const result = reduce(
_centerRelatedGroup,
(acc, value) => ({ ...acc, [COLOR_KEYS.pop() || '']: value.map((item: any) => item.relAttr) }),
{},
);
setTableRowClassNameMap(result);
};
const {
drawerVisible,
closeDrawer,
isFetching,
tableAttrsList,
tableAttrsPaging,
centerRelatedGroup,
getTableAttrs,
selectedItem,
} = props;
const { pageNo: current, total } = tableAttrsPaging;
React.useEffect(() => {
centerRelatedGroup && initTableRowClassNameMap(centerRelatedGroup);
!isEmpty(selectedItem) && getTableAttrs({ filePath: get(selectedItem, 'file'), pageNo: 1 });
}, [centerRelatedGroup, getTableAttrs, selectedItem]);
const getRelatedGroupClassName = (enName: string) => {
return findKey(tableRowClassNameMap, (item: string[]) => item.includes(enName));
};
const onTableSearch = (searchKey: string) => {
getTableAttrs({ filePath: get(selectedItem, 'file'), searchKey, pageNo: 1 });
};
const onPageChange = (pageNo: number) => {
getTableAttrs({ filePath: get(selectedItem, 'file'), pageNo });
};
return (
<Drawer
destroyOnClose
title={i18n.t('dop:class catalog')}
width="50%"
visible={drawerVisible}
onClose={closeDrawer}
>
<Spin spinning={isFetching}>
<SearchTable
placeholder={i18n.t('dop:search by chinese/english name of attribute')}
onSearch={onTableSearch}
needDebounce
>
<Table
columns={columns}
rowKey="enName"
rowClassName={({ enName }) =>
centerRelatedGroup ? `with-group-tag group-tag-${getRelatedGroupClassName(enName)}` : ''
}
dataSource={tableAttrsList}
pagination={{
current,
pageSize: PAGINATION.pageSize,
total,
onChange: onPageChange,
}}
scroll={{ x: '100%' }}
/>
</SearchTable>
</Spin>
</Drawer>
);
}
Example #23
Source File: chart.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
Chart = ({ type, extraQuery = {} }: IProps) => {
const [{ layout, boardConfig, timeSpan, loading }, updater] = useUpdate<IState>({
layout: [],
boardConfig: [],
timeSpan: getTimeSpan(),
loading: false,
});
React.useEffect(() => {
updater.loading(true);
getDashboard({ type })
.then(({ data }: any) => updater.boardConfig(data.viewConfig || []))
.finally(() => {
updater.loading(false);
});
}, [type, updater]);
React.useEffect(() => {
updater.timeSpan(getTimeSpan());
}, [extraQuery, updater]);
const query = React.useMemo(() => {
return {
...extraQuery,
start: timeSpan.startTimeMs,
end: timeSpan.endTimeMs,
};
}, [extraQuery, timeSpan.endTimeMs, timeSpan.startTimeMs]);
React.useEffect(() => {
const { start, end, ...restQuery } = query;
const flag = !isEmpty(restQuery) && values(restQuery).every((t) => !!t);
if (!flag) {
return;
}
const _layout = boardConfig.map((viewItem) => {
const filters = get(viewItem, 'view.api.extraData.filters');
const _viewItem = merge({}, viewItem, {
view: {
api: {
query: {
start,
end,
...reduce(
filters,
(acc, { value, method, tag }) => {
const matchQuery = isString(value) ? getVariableStr(value) : undefined;
return {
...acc,
[`${method}_${tag}`]: matchQuery ? restQuery[matchQuery] : value.split(','),
};
},
{},
),
},
},
},
});
const { api, chartType } = _viewItem.view as any;
return merge({}, viewItem, { view: { loadData: createLoadDataFn(api, chartType) } });
});
updater.layout(_layout);
}, [boardConfig, query, updater]);
return (
<Spin spinning={loading}>
<CommonRangePicker
className="mb-3"
defaultTime={[timeSpan.startTimeMs, timeSpan.endTimeMs]}
onOk={(v) => updater.timeSpan(v)}
/>
<BoardGrid.Pure layout={layout} />
</Spin>
);
}
Example #24
Source File: form-editor.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
FormEditor = React.forwardRef((props: IProps, ref: any) => {
const { field, allField, fieldConfig = {}, onChange, Form = DefaultForm } = props;
const form = React.useRef();
React.useEffect(() => {
ref && (ref.current = form.current);
}, [ref]);
const onFieldChange = (data: any) => {
onChange(data, field);
};
// 整合一份总的field传递给Form,同时给field通过category分类,在Tab中使用
const fields = reduce(
fieldConfig,
(sum: any[], item, fKey) => {
return sum.concat(map(item.fields, (fItem) => ({ ...fItem, category: fKey })));
},
[],
);
return (
<div className="dice-form-editor">
<h4>{i18n.t('common:Form edit')}</h4>
<div className="content">
{isEmpty(field) ? (
<div className="tip">
<div className="tip-title mb-4">{i18n.t('common:how to edit a form')}</div>
<div className="tip-desc mb-4">1、{i18n.t('common:add form items on the left')}</div>
<div className="tip-desc mb-4">2、{i18n.t('common:click edit to complete the form')}</div>
</div>
) : (
<Form
key={field.key}
value={field}
formRef={form}
onChange={onFieldChange}
fields={fields}
formRender={({ RenderFields, form: formRef, fields: totalFields }: any) => {
return (
<Tabs
tabs={map(fieldConfig, (item) => {
// tab根据fieldConfig分类,再根据key对应上面注入的category收集对应分类下的field,这样达到同一个formRef控制多个RenderField
const { key, name } = item;
const curField = filter(totalFields, (fItem) => fItem.category === key);
return {
key,
name,
content: <RenderFields key={key} allField={allField} form={formRef} fields={curField} />,
};
})}
/>
);
}}
/>
)}
</div>
</div>
);
})
Example #25
Source File: summary.tsx From S2 with MIT License | 5 votes |
TooltipSummary: React.FC<SummaryProps> = React.memo((props) => {
const { summaries = [] } = props;
const renderSelected = () => {
const count = reduce(
summaries,
(pre, next) => pre + size(next?.selectedData),
0,
);
return (
<div className={`${TOOLTIP_PREFIX_CLS}-summary-item`}>
<span className={`${TOOLTIP_PREFIX_CLS}-selected`}>
{count} {i18n('项')}
</span>
{i18n('已选择')}
</div>
);
};
const renderSummary = () => {
return summaries?.map((item) => {
const { name = '', value } = item || {};
if (!name && !value) {
return;
}
return (
<div
key={`${name}-${value}`}
className={`${TOOLTIP_PREFIX_CLS}-summary-item`}
>
<span className={`${TOOLTIP_PREFIX_CLS}-summary-key`}>
{name}({i18n('总和')})
</span>
<span
className={cls(
`${TOOLTIP_PREFIX_CLS}-summary-val`,
`${TOOLTIP_PREFIX_CLS}-bold`,
)}
>
{value}
</span>
</div>
);
});
};
return (
<div className={`${TOOLTIP_PREFIX_CLS}-summary`}>
{renderSelected()}
{renderSummary()}
</div>
);
})
Example #26
Source File: login.ts From linkedin-private-api with MIT License | 5 votes |
parseCookies = <T>(cookies: string[]): Partial<T> =>
cookies.reduce((res, c) => {
let parsedCookie = parseCookie(c);
parsedCookie = pickBy(parsedCookie, (v, k) => k === Object.keys(parsedCookie)[0]);
return merge(res, parsedCookie);
}, {})
Example #27
Source File: utils.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
transformConfigRecursively = (fieldsConfig: Field[], componentMap: Map<CT, string>) => {
const propertiesArray: SchemaField[] = map(fieldsConfig, (item) => {
const {
name,
title,
label,
type = 'string',
customProps,
wrapperProps,
defaultValue,
component,
required,
validator,
items,
gridConfig,
layoutConfig,
display,
valuePropName,
noPropertyLayoutWrapper = false,
componentName: _componentName,
properties: fieldProperties,
} = item;
let componentName = '';
if (componentMap.has(component)) {
componentName = componentMap.get(component)!;
} else {
componentName = _componentName ?? uniqueId('component-');
if (valuePropName) {
componentMap.set(connect(component, mapProps({ value: valuePropName })), componentName);
} else {
componentMap.set(component, componentName);
}
}
let _items = {}; // for array fields
if (items) {
const _properties = transformConfigRecursively(items, componentMap);
_items = {
type: 'object',
properties: {
layout: {
type: 'void',
'x-component': 'FormLayout',
'x-component-props': { ...defaultLayoutConfig, ...layoutConfig },
properties: {
grid: {
type: 'void',
'x-component': 'FormGrid',
'x-component-props': {
maxColumns: gridConfig?.minColumns ? gridConfig.minColumns : 1,
...gridConfig,
},
properties: _properties,
},
},
},
},
};
}
let _properties;
if (fieldProperties) {
_properties = transformConfigRecursively(fieldProperties, componentMap);
if (!noPropertyLayoutWrapper) {
_properties = {
layout: {
type: 'void',
'x-component': 'FormLayout',
'x-component-props': { ...defaultLayoutConfig, ...layoutConfig },
properties: {
grid: {
type: 'void',
'x-component': 'FormGrid',
'x-component-props': {
maxColumns: gridConfig?.minColumns ? gridConfig.minColumns : 1,
...gridConfig,
},
properties: _properties,
},
},
},
};
}
}
return {
name,
title: title ?? label,
type,
required,
items: _properties ? undefined : _items,
default: defaultValue,
'x-validator': validator,
'x-decorator': _properties ? undefined : 'FormItem',
'x-component': componentName,
'x-component-props': customProps,
'x-display': display,
'x-decorator-props': _properties ? { ...wrapperProps } : { colon: false, ...wrapperProps },
properties: _properties,
};
});
const properties = reduce(
propertiesArray,
(acc, item) => {
const { name, ...rest } = item;
acc[name] = rest;
return acc;
},
{} as Obj<Omit<SchemaField, 'name'>>,
);
return properties as Obj<Omit<SchemaField, 'name'>>;
}
Example #28
Source File: trainings-chart.component.tsx From MyWay-client with MIT License | 4 votes |
export default function TrainingsChart({
trainingGoals,
}: {
trainingGoals: TrainingGoalDto[];
}) {
const ref = useRef<SVGSVGElement>(null);
// const colorGoals = (goals: ChartGoalDto[]) => {
// const colorGen = colorsGenerator();
// return goals
// .filter((goal) => goal.showOnChart)
// .filter((goal) => goal.tasks.length !== 0)
// .map((goal) => ({
// ...goal,
// color: colorGen.next().value,
// }));
// };
const filterShownGoals = (goals: ChartGoalDto[]) => {
return goals.filter((goal) => goal.showOnChart);
};
const isAnyGoalShown = (goals: ChartGoalDto[]) => {
return goals.some((goal) => goal.showOnChart);
};
const findMaxEndingTrainingInGoals = (goals: ChartGoalDto[]): number => {
return Math.max(
...goals.map((goal: ChartGoalDto) =>
findMaxEndingTrainingInTasks(goal.tasks)
)
);
};
const findMaxEndingTrainingInTasks = (
tasks: TrainingGoalTaskDto[]
): number => {
return Math.max(
...tasks.map((task: TrainingGoalTaskDto) => task.endingTraining)
);
};
const calcTotalNumberOfTasks = (goals: ChartGoalDto[]): number => {
return goals.reduce(
(acc: number, e: ChartGoalDto) => acc + e.tasks.length,
0
);
};
let goals: ChartGoalDto[] = [];
let tasksSoFar = 0;
for (const trainingGoal of trainingGoals) {
goals.push({
...trainingGoal,
color: "#000",
showOnChart: true,
tasksSoFar,
});
tasksSoFar += trainingGoal.tasks.length;
}
let chartGoals = filterShownGoals(goals);
const maxEndingTrainingInGoals = findMaxEndingTrainingInGoals(chartGoals);
const totalNumberOfTasks = calcTotalNumberOfTasks(chartGoals);
const draw = useCallback(
(ref) => {
d3.select("#x-axis").remove();
const svgClientSize = d3
.select(ref.current)
.node()
.getBoundingClientRect();
const xScale = d3
.scaleLinear()
.domain([1, maxEndingTrainingInGoals])
.range([svgClientSize.width * 0.85, 0]);
const xAxis = d3
.axisBottom(xScale)
.tickValues(
Array.from({ length: maxEndingTrainingInGoals }, (v, k) => k + 1)
)
.tickFormat(d3.format("d"));
d3.select(ref.current)
.append("g")
.attr("id", "x-axis")
.attr("transform", `translate(0, ${svgClientSize.height * 0.9})`)
.call(xAxis);
},
[ref]
);
useEffect(() => {
window.addEventListener("resize", () => draw(ref));
draw(ref);
return () => {
window.removeEventListener("resize", () => draw(ref));
};
}, [ref]);
return (
<svg
ref={ref}
style={{ border: "1px solid black" }}
width="100%"
height="100%"
>
{isAnyGoalShown(chartGoals) == false && <NoGoalsMarkedMessage />}
<svg>
{chartGoals.map((goal, idx) => (
<TrainingsChartGoalRow
key={goal.id}
idx={idx}
total={chartGoals.length}
goal={goal}
maxEndingTraining={maxEndingTrainingInGoals}
totalNumberOfTasks={totalNumberOfTasks}
/>
))}
</svg>
</svg>
);
}
Example #29
Source File: basic-params-config.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
PropertyItemForm = React.memo((props: IPropertyItemForm) => {
const { formData, onChange, formType = 'Query', isEditMode = true, index } = props;
const [
{
detailVisible,
curPropertyType,
innerParamList,
dataTempStorage,
paramListTempStorage,
paramsModalVisible,
arrayItemDataStorage,
errorMap,
formErrorMap,
},
updater,
update,
] = useUpdate({
detailVisible: props.detailVisible || false,
curPropertyType: formData.type || initialTypeMap[formType] || ('string' as API_SETTING.PropertyType),
innerParamList: [],
dataTempStorage: {},
paramListTempStorage: [],
paramsModalVisible: false,
arrayItemDataStorage: null,
errorMap: {
name: false,
maxLength: false,
minLength: false,
maximum: false,
minimum: false,
},
formErrorMap: {},
});
const formRef = React.useRef<IFormExtendType>({} as any);
const paramListTempStorageRef = React.useRef<any[]>([]);
const dataTempStorageRef = React.useRef<Obj>({});
React.useImperativeHandle(paramListTempStorageRef, () => paramListTempStorage);
React.useImperativeHandle(dataTempStorageRef, () => dataTempStorage);
const isCurTypeOf = React.useCallback(
(type: BASE_DATA_TYPE) => {
return curPropertyType === type || get(props, ['extraDataTypes', curPropertyType, 'type']) === type;
},
[curPropertyType, props],
);
const isBasicDataType = React.useMemo(() => {
return some(BASE_DATA_TYPE, (item) => item === curPropertyType);
}, [curPropertyType]);
const getRefTypePath = React.useCallback((data: Obj): string => {
return get(data, [QUOTE_PREFIX, 0, '$ref']) || get(data, [QUOTE_PREFIX_NO_EXTENDED]) || '';
}, []);
const getExampleData = React.useCallback(
(data: Obj, extraTypes?: Obj) => {
if (!data) return '';
const _extraTypes = extraTypes || props?.extraDataTypes;
const refTypePath = getRefTypePath(data);
const customType = refTypePath.split('/').slice(-1)[0];
const customTypeData = get(_extraTypes, [customType]) || customType || {};
if (typeof customTypeData === 'string') {
const _type =
get(props, ['allExtraDataTypes', customType, 'type']) || get(props, ['extraDataTypes', customType, 'type']);
return _type === 'array' ? [] : {};
}
const curType = data.type || customTypeData.type;
if (curType === 'object') {
const newExtraTypes = produce(_extraTypes, (draft) => {
draft && (draft[customType] = null);
});
const newExample: Obj = refTypePath ? getExampleData(customTypeData, newExtraTypes) : {};
const customProperties = data.properties || {};
forEach(keys(customProperties), (pName) => {
const propertyItem = customProperties[pName];
newExample[pName] = getExampleData(propertyItem, newExtraTypes);
});
return newExample;
} else if (curType === 'array') {
if (refTypePath) {
const newItemExtraTypes = produce(_extraTypes, (draft) => {
draft && (draft[customType] = null);
});
return getExampleData(customTypeData, newItemExtraTypes);
} else {
return [getExampleData(data.items, _extraTypes)];
}
} else if (refTypePath && customTypeData.example !== undefined) {
return customTypeData.example;
} else if (data.example !== undefined) {
return data.example;
} else {
return DATATYPE_EXAMPLE_MAP[curType] || '';
}
},
[getRefTypePath, props],
);
// 表单初始化加载
React.useEffect(() => {
formRef.current.resetFields();
update({
errorMap: {
name: false,
maxLength: false,
minLength: false,
maximum: false,
minimum: false,
},
formErrorMap: {},
});
const innerProperties = formData?.properties;
const requiredNames = formData?.required || [];
updater.dataTempStorage(formData);
const tempList = map(keys(innerProperties), (pKey: string) => {
const _temp = { ...innerProperties[pKey] };
if (formData?.type === 'object' && Array.isArray(formData?.required)) {
_temp[API_PROPERTY_REQUIRED] = requiredNames.includes(pKey);
}
_temp[API_FORM_KEY] = pKey;
return _temp;
});
updater.innerParamList(tempList);
updater.paramListTempStorage(tempList);
let _curPropertyType = formData?.type || formData?.schema?.type || 'object';
const tempFormData = { ...formData };
const refTypePath = getRefTypePath(formData);
if (refTypePath) {
const customType = refTypePath.split('/').slice(-1)[0];
tempFormData.type = customType;
_curPropertyType = customType;
}
updater.curPropertyType(_curPropertyType);
setTimeout(() => {
formRef.current!.setFieldsValue(tempFormData);
if (isEmpty(formData)) {
const _formData = formRef.current!.getFieldsValue();
updater.dataTempStorage(_formData);
} else {
updater.dataTempStorage(formData);
}
});
}, [updater, formData, getRefTypePath, update]);
const AllDataTypes = React.useMemo(() => {
return filter(props?.allDataTypes, (item) => item !== dataTempStorage[API_FORM_KEY]) || [];
}, [dataTempStorage, props]);
const onToggleDetail = React.useCallback(
(visible) => {
if (visible) {
const omitList = getRefTypePath(dataTempStorage) ? ['type', API_FORM_KEY] : [API_FORM_KEY];
const tempFormData = omit(dataTempStorage, omitList);
const example = getExampleData(tempFormData);
setTimeout(() => formRef.current!.setFieldsValue({ ...tempFormData, example }));
}
updater.dataTempStorage(dataTempStorageRef.current);
if (curPropertyType === 'array' && arrayItemDataStorage) {
updater.dataTempStorage(arrayItemDataStorage);
} else {
updater.dataTempStorage(dataTempStorageRef.current);
}
updater.innerParamList(paramListTempStorageRef.current);
updater.detailVisible(visible);
},
[arrayItemDataStorage, curPropertyType, dataTempStorage, getExampleData, getRefTypePath, updater],
);
const propertyNameMap = React.useMemo(() => {
const list = props?.siblingProperties || [];
return map(list, (item) => item[API_FORM_KEY]);
}, [props]);
const setFields = React.useCallback(
(fieldProps: ISetFieldProps) => {
const { propertyKey = '', propertyData } = fieldProps;
if (propertyKey === API_MEDIA && props.onSetMediaType) {
props.onSetMediaType(fieldProps as { propertyKey: string; propertyData: string });
return;
}
if (propertyKey === 'operation') {
updater.detailVisible(propertyData);
return;
}
if (formRef?.current) {
const newFormData = produce(dataTempStorageRef.current, (draft: any) => {
if (
curPropertyType === 'array' &&
!['description', 'type', API_FORM_KEY, API_PROPERTY_REQUIRED].includes(propertyKey)
) {
set(draft, `items.${propertyKey}`, propertyData);
} else {
set(draft, propertyKey, propertyData);
}
if (propertyKey === 'type') {
const curType = propertyData;
updater.curPropertyType(curType);
unset(draft, QUOTE_PREFIX);
unset(draft, QUOTE_PREFIX_NO_EXTENDED);
unset(draft, 'default');
unset(draft, 'enum');
if (curType === 'object' || curType === 'array') {
unset(draft, 'pattern');
unset(draft, 'maxLength');
unset(draft, 'minLength');
unset(draft, 'format');
unset(draft, 'maximum');
unset(draft, 'minimum');
if (curType === 'object') {
set(draft, 'properties', {});
set(draft, 'required', []);
unset(draft, 'items');
}
if (curType === 'array') {
const tempItemData = {
type: 'string',
example: 'Example',
};
tempItemData[API_FORM_KEY] = 'items';
set(draft, 'items', tempItemData);
unset(draft, 'properties');
updater.innerParamList([]);
updater.paramListTempStorage([]);
}
} else if (['boolean', 'string', 'number', 'integer'].includes(curType)) {
unset(draft, 'items');
unset(draft, 'properties');
unset(draft, 'required');
if (curType !== 'number') {
unset(draft, 'format');
unset(draft, 'maximum');
unset(draft, 'minimum');
}
if (curType !== 'string') {
unset(draft, 'pattern');
unset(draft, 'maxLength');
unset(draft, 'minLength');
}
updater.innerParamList([]);
updater.paramListTempStorage([]);
}
set(draft, 'example', DATATYPE_EXAMPLE_MAP[curType]);
}
});
if (propertyKey === 'type') {
if (!DATATYPE_EXAMPLE_MAP[propertyData]) {
const customTypeData = get(props, ['extraDataTypes', propertyData]) || {};
const _newTypeData = {
...omit(dataTempStorage, [QUOTE_PREFIX, QUOTE_PREFIX_NO_EXTENDED]),
example: customTypeData.example || getExampleData(customTypeData),
properties: customTypeData.type === 'object' ? {} : undefined,
required: dataTempStorage.required,
type: customTypeData.type,
};
// object类型的引用类型支持可拓展编辑
if (customTypeData.type === 'object') {
_newTypeData[QUOTE_PREFIX] = [{ $ref: `#/components/schemas/${propertyData}` }];
} else {
_newTypeData[QUOTE_PREFIX_NO_EXTENDED] = `#/components/schemas/${propertyData}`;
}
const typeQuotePath = _newTypeData[API_FORM_KEY];
update({
dataTempStorage: _newTypeData,
innerParamList: [],
paramListTempStorage: [],
});
formRef.current.setFieldsValue({ ..._newTypeData, type: propertyData });
onChange(dataTempStorage[API_FORM_KEY], _newTypeData, { typeQuotePath, quoteTypeName: propertyData });
return;
}
}
updater.dataTempStorage(newFormData);
onChange(dataTempStorage[API_FORM_KEY], newFormData);
}
},
[curPropertyType, dataTempStorage, onChange, props, update, updater],
);
const dataTypeOptions = React.useMemo(() => {
if (!props?.extraDataTypes) {
return map(BASE_DATA_TYPE, (item) => (
<Option key={item} value={item}>
{item.slice(0, 1).toUpperCase() + item.slice(1)}
</Option>
));
} else {
const basicDataTypeOptions = map(BASE_DATA_TYPE, (item) => (
<Option key={item} value={item}>
{item.slice(0, 1).toUpperCase() + item.slice(1)}
</Option>
));
const extraOptions =
map(keys(props.extraDataTypes), (typeName) => (
<Option key={typeName} value={typeName}>
{typeName}
</Option>
)) || [];
return [...basicDataTypeOptions, ...extraOptions];
}
}, [props]);
const updateErrorNum = React.useCallback(
(num, name) => {
const _formErrorMap: IFormErrorMap = {};
_formErrorMap[name] = num;
if (curPropertyType === 'object') {
forEach(paramListTempStorage, (param) => {
const pName = param[API_FORM_KEY];
if (pName === name) {
_formErrorMap[pName] = num;
} else {
_formErrorMap[pName] = formErrorMap[pName] || 0;
}
});
}
updater.formErrorMap(_formErrorMap);
const totalError = reduce(values(_formErrorMap), (total, cur) => total + cur, 0);
props.updateErrorNum && props.updateErrorNum(totalError, dataTempStorage[API_FORM_KEY]);
props.onFormErrorNumChange && props.onFormErrorNumChange(totalError, dataTempStorage[API_FORM_KEY]);
},
[curPropertyType, dataTempStorage, formErrorMap, paramListTempStorage, props, updater],
);
const onChangePropertyName = React.useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const newName = e.target.value;
const { pattern } = regRules.specialLetter;
const nameMap = formType === 'DataType' ? AllDataTypes : propertyNameMap;
let isErrorValue = true;
const isSameWithBaseType = formType === 'DataType' && newName.toLocaleLowerCase() in BASE_DATA_TYPE;
if (newName !== '' && !pattern.test(newName) && !nameMap.includes(newName) && !isSameWithBaseType) {
const temp = produce(dataTempStorageRef.current, (draft) => {
set(draft, API_FORM_KEY, newName);
});
isErrorValue = false;
updater.dataTempStorage(temp);
onChange(dataTempStorageRef.current[API_FORM_KEY], temp, {
typeQuotePath: newName,
quoteTypeName: curPropertyType,
});
}
// 统计name类型错误数量
const newErrorMap = { ...errorMap };
if (isErrorValue && !errorMap.name) {
newErrorMap.name = true;
updater.errorMap(newErrorMap);
const errorNum = reduce(values(newErrorMap), (total, cur) => (cur ? total + 1 : total), 0);
updateErrorNum(errorNum, dataTempStorage[API_FORM_KEY]);
} else if (!isErrorValue && errorMap.name) {
newErrorMap.name = false;
updater.errorMap(newErrorMap);
const errorNum = reduce(values(newErrorMap), (total, cur) => (cur ? total + 1 : total), 0);
updateErrorNum(errorNum, dataTempStorage[API_FORM_KEY]);
}
},
[
AllDataTypes,
curPropertyType,
dataTempStorage,
errorMap,
formType,
onChange,
propertyNameMap,
updateErrorNum,
updater,
],
);
const onChangeNumberValue = React.useCallback(
({ propertyKey, propertyData }: { propertyKey: string; propertyData: number }) => {
let isErrorValue = true;
if (propertyKey === 'minLength') {
const maxLength = dataTempStorageRef.current?.maxLength;
if (maxLength === undefined || maxLength >= propertyData) {
setFields({ propertyKey, propertyData });
isErrorValue = false;
}
} else if (propertyKey === 'maxLength') {
const minLength = dataTempStorageRef.current?.minLength;
if (minLength === undefined || minLength <= propertyData) {
setFields({ propertyKey, propertyData });
isErrorValue = false;
}
} else if (propertyKey === 'minimum') {
const maximum = dataTempStorageRef.current?.maximum;
if (maximum === undefined || maximum >= propertyData) {
setFields({ propertyKey, propertyData });
isErrorValue = false;
}
} else {
const minimum = dataTempStorageRef.current?.minimum;
if (minimum === undefined || minimum <= propertyData) {
setFields({ propertyKey, propertyData });
isErrorValue = false;
}
}
// 统计number类型错误数量
const newErrorMap = { ...errorMap };
if (isErrorValue && !errorMap[propertyKey]) {
newErrorMap[propertyKey] = true;
updater.errorMap(newErrorMap);
const errorNum = reduce(values(newErrorMap), (total, cur) => (cur ? total + 1 : total), 0);
updateErrorNum(errorNum, dataTempStorage[API_FORM_KEY]);
} else if (!isErrorValue && errorMap[propertyKey]) {
newErrorMap[propertyKey] = false;
updater.errorMap(newErrorMap);
const errorNum = reduce(values(newErrorMap), (total, cur) => (cur ? total + 1 : total), 0);
updateErrorNum(errorNum, dataTempStorage[API_FORM_KEY]);
}
},
[errorMap, dataTempStorage, setFields, updater, updateErrorNum],
);
// 参数详情选项
const propertyFields = React.useMemo(() => {
const fields = formType !== 'Parameters' ? [descriptionField] : [];
if (!getRefTypePath(dataTempStorage)) {
const tempFields = getPropertyDetailFields({ type: curPropertyType, curPropertyType, formData: dataTempStorage });
fields.push(...tempFields);
} else if (get(props, `extraDataTypes.${curPropertyType}.type`)) {
const tempFields = getPropertyDetailFields({
type: curPropertyType,
curPropertyType: get(props, ['extraDataTypes', curPropertyType, 'type']),
formData: dataTempStorage,
});
fields.push(...tempFields);
}
return map(fields, (fieldItem) => {
const tempFieldItem = produce(fieldItem, (draft) => {
if (['minLength', 'maxLength', 'minimum', 'maximum'].includes(draft.name)) {
set(draft, 'customProps.onChange', (e: React.ChangeEvent<HTMLInputElement> | any) => {
const newNum = !(Object.prototype.toString.call(e) === '[object Object]') ? e : +e.target.value;
onChangeNumberValue({ propertyKey: fieldItem?.name, propertyData: newNum });
});
} else {
set(draft, 'customProps.onChange', (e: React.ChangeEvent<HTMLInputElement> | any) => {
const newVal = !(Object.prototype.toString.call(e) === '[object Object]') ? e : e.target.value;
setFields({ propertyKey: fieldItem?.name, propertyData: newVal });
});
}
set(draft, 'customProps.disabled', !isEditMode);
});
return tempFieldItem;
});
}, [formType, getRefTypePath, dataTempStorage, props, curPropertyType, isEditMode, onChangeNumberValue, setFields]);
const onArrayItemChange = (_formKey: string, _formData: any, extraProps?: Obj) => {
const newExample = [getExampleData(_formData)];
const tempData = produce(dataTempStorageRef.current, (draft) => {
draft.items = _formData;
draft.example = newExample;
});
const _extraProps = {
quoteTypeName: extraProps?.quoteTypeName,
typeQuotePath: extraProps?.typeQuotePath
? `${dataTempStorageRef.current[API_FORM_KEY]}.${extraProps.typeQuotePath}`
: '',
};
props.onChange(dataTempStorageRef.current[API_FORM_KEY], tempData, _extraProps);
updater.arrayItemDataStorage(tempData);
};
const updateInnerParamList = (formKey: string, _formData: any, extraProps?: Obj) => {
const tempList = produce(paramListTempStorageRef.current, (draft) => {
forEach(draft, (item, index) => {
if (item[API_FORM_KEY] === formKey) {
draft[index] = _formData;
}
});
});
const requiredNames: string[] = [];
const refTypePath = getRefTypePath(dataTempStorage);
const customDataType = refTypePath ? refTypePath.split('/').slice(-1)[0] : '';
const objectExample: Obj = { ...getExampleData(get(props, ['extraDataTypes', customDataType])) };
forEach(tempList, (item) => {
const _example = item?.example || DATATYPE_EXAMPLE_MAP[item?.type];
if (item[API_PROPERTY_REQUIRED]) {
requiredNames.push(item[API_FORM_KEY]);
}
objectExample[item[API_FORM_KEY]] = _example;
});
updater.paramListTempStorage(tempList);
if (props.onChange && tempList?.length) {
const newProperties = {};
forEach(tempList, (item) => {
newProperties[item[API_FORM_KEY]] = item;
});
const tempData = produce(dataTempStorageRef.current, (draft) => {
draft.properties = newProperties;
draft.type = 'object';
draft.required = requiredNames;
draft.example = objectExample;
});
updater.dataTempStorage(tempData);
const typeQuotePath = extraProps?.typeQuotePath
? `${tempData[API_FORM_KEY] || 'schema'}.properties.${extraProps?.typeQuotePath}`
: '';
props.onChange(dataTempStorageRef.current[API_FORM_KEY], tempData, {
typeQuotePath,
quoteTypeName: extraProps?.quoteTypeName,
});
}
};
const deleteParamByFormKey = (_data: Obj, index: number) => {
const tempList = paramListTempStorage.filter((_record, i) => index !== i);
updater.innerParamList(tempList);
updater.paramListTempStorage(tempList);
const tempProperties = {};
const newExample = {};
const requiredNames: string[] = [];
forEach(tempList, (item) => {
tempProperties[item[API_FORM_KEY]] = item;
newExample[item[API_FORM_KEY]] = item?.example;
item[API_PROPERTY_REQUIRED] && requiredNames.push(item[API_FORM_KEY]);
});
const newFormData = produce(dataTempStorage, (draft) => {
set(draft, 'properties', tempProperties);
set(draft, 'example', newExample);
set(draft, 'required', requiredNames);
});
updater.dataTempStorage(newFormData);
props?.onChange && props.onChange(newFormData[API_FORM_KEY], newFormData);
};
const getExistNames = React.useCallback(() => {
const existNames = map(paramListTempStorage, (item) => item[API_FORM_KEY]);
const refTypePath = getRefTypePath(dataTempStorage);
const customDataType = refTypePath ? refTypePath.split('/').slice(-1)[0] : '';
if (refTypePath && get(props, `extraDataTypes.${curPropertyType}.type`) === 'object') {
const _extraProperties = get(props, ['extraDataTypes', customDataType, 'properties']);
existNames.push(...keys(_extraProperties));
}
return existNames;
}, [curPropertyType, dataTempStorage, getRefTypePath, paramListTempStorage, props]);
// object类型的批量添加参数
const addParamList = React.useCallback(
(newList: Obj[]) => {
const refTypePath = getRefTypePath(dataTempStorage);
const customDataType = refTypePath ? refTypePath.split('/').slice(-1)[0] : '';
const tempList = [...paramListTempStorage, ...newList];
updater.innerParamList(tempList);
updater.paramListTempStorage(tempList);
const tempProperties = {};
forEach(tempList, (item) => {
tempProperties[item[API_FORM_KEY]] = item;
});
const newExample = refTypePath ? { ...get(props, `extraDataTypes.${customDataType}.example`) } : {};
const requiredNames: string[] = [];
forEach(tempList, (property) => {
property[API_PROPERTY_REQUIRED] && requiredNames.push(property[API_FORM_KEY]);
newExample[property[API_FORM_KEY]] = property?.example;
});
const newFormData = produce(dataTempStorage, (draft) => {
set(draft, 'properties', tempProperties);
set(draft, 'type', 'object');
set(draft, 'example', newExample);
set(draft, 'required', requiredNames);
});
updater.dataTempStorage(newFormData);
props?.onChange && props.onChange(dataTempStorage[API_FORM_KEY], newFormData);
},
[dataTempStorage, getRefTypePath, paramListTempStorage, props, updater],
);
// object添加单个参数
const addParam = React.useCallback(() => {
let newPropertyName = `propertyName${innerParamList?.length + 1}`;
const existNames = getExistNames();
while (existNames.includes(newPropertyName)) {
newPropertyName += '1';
}
const tempObj = {
type: 'string',
example: 'Example',
};
tempObj[API_PROPERTY_REQUIRED] = true;
tempObj[API_FORM_KEY] = newPropertyName;
addParamList([tempObj]);
}, [addParamList, getExistNames, innerParamList]);
// 更新设置example示例
React.useEffect(() => {
const tempData = isCurTypeOf(BASE_DATA_TYPE.array) && arrayItemDataStorage ? arrayItemDataStorage : dataTempStorage;
if (tempData.example && typeof tempData.example === 'object') {
const newExample = getExampleData(tempData);
formRef.current.resetFields(['example']);
formRef.current.setFieldsValue({ example: newExample });
}
}, [arrayItemDataStorage, curPropertyType, dataTempStorage, getExampleData, isCurTypeOf]);
const onCloseParamsModal = () => updater.paramsModalVisible(false);
const onImport = (importedParams: Obj[]) => {
onCloseParamsModal();
addParamList(importedParams);
};
const formFieldsSelector = React.useMemo(() => {
const tempFields = getPropertyFormSelector({
formType,
dataTypeOptions,
propertyNameMap,
AllDataTypes,
detailVisible,
index,
});
return map(tempFields, (fieldItem: any) => {
const tempFieldItem = produce(fieldItem, (draft: { name: string }) => {
if (draft.name === API_FORM_KEY && ['DataType', 'Query'].includes(formType)) {
set(draft, 'customProps.onChange', onChangePropertyName);
} else if (draft.name === 'operation') {
set(draft, 'customProps.onChange', onToggleDetail);
} else {
set(draft, 'customProps.onChange', (e: React.ChangeEvent<HTMLInputElement> | string | boolean) => {
const newVal = typeof e === 'string' || typeof e === 'boolean' ? e : e.target.value;
setFields({ propertyKey: fieldItem?.name, propertyData: newVal });
});
}
set(draft, 'customProps.disabled', !isEditMode);
});
return tempFieldItem;
});
}, [
formType,
dataTypeOptions,
propertyNameMap,
AllDataTypes,
detailVisible,
isEditMode,
onChangePropertyName,
onToggleDetail,
setFields,
index,
]);
const detailType = React.useMemo(() => {
if (detailVisible) {
if (isCurTypeOf(BASE_DATA_TYPE.object)) {
return 'object';
} else if (isCurTypeOf(BASE_DATA_TYPE.array)) {
return 'array';
} else if (!isBasicDataType) {
return 'example';
}
}
return '';
}, [detailVisible, isBasicDataType, isCurTypeOf]);
return (
<FormBuilder isMultiColumn ref={formRef}>
{props?.formType !== 'Parameters' && <Fields fields={formFieldsSelector} />}
{detailVisible && isBasicDataType && <Fields fields={propertyFields} />}
{detailType === 'object' && (
<div>
{map(innerParamList, (record, index) => {
return (
<div className="param-form" key={record[API_FORM_KEY]}>
{isEditMode && (
<div className="param-form-operation">
<Popconfirm
title={`${i18n.t('common:confirm to delete')}?`}
onConfirm={() => deleteParamByFormKey(record, index)}
>
<CustomIcon type="shanchu" className="param-form-operation-btn cursor-pointer" />
</Popconfirm>
</div>
)}
<div className="param-form-content">
<FormBuilder isMultiColumn>
<PropertyItemForm
key={record[API_FORM_KEY]}
updateErrorNum={updateErrorNum}
formData={record}
isEditMode={isEditMode}
onChange={updateInnerParamList}
extraDataTypes={props?.extraDataTypes}
allExtraDataTypes={props?.allExtraDataTypes}
siblingProperties={filter(
paramListTempStorage,
(item) => item[API_FORM_KEY] !== record[API_FORM_KEY],
)}
index={index}
/>
</FormBuilder>
</div>
</div>
);
})}
{isEditMode && (
<>
<Button className="operation-btn mb-4" onClick={addParam}>
{i18n.t('common:add parameter')}
</Button>
<Button className="operation-btn mb-4 ml-2" onClick={() => updater.paramsModalVisible(true)}>
{i18n.t('dop:import parameters')}
</Button>
</>
)}
{props?.formType !== 'Parameters' && <Fields fields={[objectExampleField]} />}
</div>
)}
{detailType === 'array' && (
<>
{isBasicDataType && (
<div className="array-form">
<PropertyItemForm
formType="Array"
updateErrorNum={updateErrorNum}
formData={dataTempStorage.items || {}}
detailVisible
onChange={onArrayItemChange}
isEditMode={isEditMode}
extraDataTypes={props?.extraDataTypes}
allExtraDataTypes={props?.allExtraDataTypes}
siblingProperties={filter(
paramListTempStorage,
(item) => item[API_FORM_KEY] !== dataTempStorage.items[API_FORM_KEY],
)}
/>
</div>
)}
<Fields fields={[objectExampleField]} />
</>
)}
{detailType === 'example' && <Fields fields={[objectExampleField]} />}
<ApiParamsModal
visible={paramsModalVisible}
onImport={onImport}
onClose={onCloseParamsModal}
paramList={paramListTempStorage}
/>
</FormBuilder>
);
})