feat: 增加修改面板属性的功能

pull/81/head
moonrailgun 4 years ago
parent b243f64227
commit 4c9f5ec5f2

@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react';
import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import { useFormik } from 'formik';
import _isNil from 'lodash/isNil';
import _fromPairs from 'lodash/fromPairs';
@ -22,6 +22,7 @@ export interface FastFormProps {
schema?: ObjectSchema<any>; // yup schame object 用于表单校验
layout?: 'horizontal' | 'vertical'; // 布局方式(默认水平)
submitLabel?: string; // 提交按钮的标签名
initialValues?: any;
onSubmit: (values: any) => Promise<void> | void; // 点击提交按钮的回调
onChange?: (values: any) => void; // 数据更新回调
}
@ -32,13 +33,21 @@ export interface FastFormProps {
*/
export const FastForm: React.FC<FastFormProps> = React.memo((props) => {
const initialValues = useMemo(() => {
return _fromPairs(
return {
..._fromPairs(
props.fields.map((field) => [field.name, field.defaultValue ?? ''])
);
}, [props.fields]);
),
...props.initialValues,
};
}, [props.fields, props.initialValues]);
const [loading, setLoading] = useState(false);
useLayoutEffect(() => {
// 加载时提交一次initialValues
typeof props.onChange === 'function' && props.onChange(initialValues);
}, []);
const formik = useFormik({
initialValues,
validationSchema: props.schema,

@ -110,6 +110,7 @@ export {
applyGroupInvite,
modifyGroupField,
createGroupPanel,
modifyGroupPanel,
deleteGroupPanel,
} from './model/group';
export type { GroupPanel, GroupInfo, GroupBasicInfo } from './model/group';

@ -170,6 +170,27 @@ export async function createGroupPanel(
});
}
/**
*
*/
export async function modifyGroupPanel(
groupId: string,
panelId: string,
options: {
name: string;
parentId?: string;
provider?: string;
pluginPanelName?: string;
meta?: Record<string, unknown>;
}
) {
await request.post('/api/group/modifyGroupPanel', {
...options,
groupId,
panelId,
});
}
/**
*
* @param groupId Id

@ -10,6 +10,8 @@ import type { DataNode } from 'antd/lib/tree';
import { buildTreeDataWithGroupPanel } from './utils';
import { Icon } from '@iconify/react';
import { useGroupPanelTreeDrag } from './useGroupPanelTreeDrag';
import { closeModal, openModal } from '@/components/Modal';
import { ModalModifyGroupPanel } from '../../GroupPanel/ModifyGroupPanel';
interface GroupPanelTree {
groupId: string;
@ -25,6 +27,19 @@ export const GroupPanelTree: React.FC<GroupPanelTree> = React.memo((props) => {
[props.groupPanels]
);
const handleModifyPanel = useCallback(
(panelId: string) => {
const key = openModal(
<ModalModifyGroupPanel
groupId={props.groupId}
groupPanelId={panelId}
onSuccess={() => closeModal(key)}
/>
);
},
[props.groupId]
);
const handleDeletePanel = useCallback(
(panelId: string, panelName: string, isGroup: boolean) => {
showAlert({
@ -47,6 +62,17 @@ export const GroupPanelTree: React.FC<GroupPanelTree> = React.memo((props) => {
<div className="flex group">
<span>{node.title}</span>
<div className="opacity-0 group-hover:opacity-100">
<Button
type="text"
size="small"
icon={<Icon className="anticon" icon="mdi:pencil-outline" />}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleModifyPanel(String(node.key));
}}
/>
<Button
type="text"
size="small"

@ -52,7 +52,7 @@ export const GroupPanel: React.FC<{
const key = openModal(
<ModalCreateGroupPanel
groupId={groupId}
onCreateSuccess={() => {
onSuccess={() => {
closeModal(key);
isEditingRef.current = false;
}}

@ -28,7 +28,7 @@ const schema = createFastFormSchema({
*/
export const ModalCreateGroupPanel: React.FC<{
groupId: string;
onCreateSuccess: () => void;
onSuccess?: () => void;
}> = React.memo((props) => {
const [currentValues, setValues] = useState<Partial<GroupPanelValues>>({});
@ -36,9 +36,9 @@ export const ModalCreateGroupPanel: React.FC<{
async (values: GroupPanelValues) => {
await createGroupPanel(props.groupId, buildDataFromValues(values));
showToasts(t('创建成功'), 'success');
props.onCreateSuccess();
typeof props.onSuccess === 'function' && props.onSuccess();
},
[props.groupId, props.onCreateSuccess]
[props.groupId, props.onSuccess]
);
const fields = useGroupPanelFields(props.groupId, currentValues);

@ -0,0 +1,69 @@
import { LoadingSpinner } from '@/components/LoadingSpinner';
import React, { useEffect, useLayoutEffect, useState } from 'react';
import {
t,
useAsyncRequest,
modifyGroupPanel,
createFastFormSchema,
fieldSchema,
showToasts,
useGroupPanel,
} from 'tailchat-shared';
import { ModalWrapper } from '../../Modal';
import { WebFastForm } from '../../WebFastForm';
import { buildDataFromValues, pickValuesFromGroupPanelInfo } from './helper';
import type { GroupPanelValues } from './types';
import { useGroupPanelFields } from './useGroupPanelFields';
import _omit from 'lodash/omit';
const schema = createFastFormSchema({
name: fieldSchema
.string()
.required(t('面板名不能为空'))
.max(20, t('面板名过长')),
type: fieldSchema.string().required(t('面板类型不能为空')),
});
/**
*
*/
export const ModalModifyGroupPanel: React.FC<{
groupId: string;
groupPanelId: string;
onSuccess?: () => void;
}> = React.memo((props) => {
const groupPanelInfo = useGroupPanel(props.groupId, props.groupPanelId);
const [currentValues, setValues] = useState<Partial<GroupPanelValues>>({});
const [, handleSubmit] = useAsyncRequest(
async (values: GroupPanelValues) => {
await modifyGroupPanel(
props.groupId,
props.groupPanelId,
_omit(buildDataFromValues(values), 'type') // 发送时不传type
);
showToasts(t('修改成功'), 'success');
typeof props.onSuccess === 'function' && props.onSuccess();
},
[props.groupId, props.groupPanelId, props.onSuccess]
);
const fields = useGroupPanelFields(props.groupId, currentValues);
if (!groupPanelInfo) {
return <LoadingSpinner />;
}
return (
<ModalWrapper title={t('创建群组面板')} style={{ maxWidth: 440 }}>
<WebFastForm
schema={schema}
fields={fields.filter((f) => f.type !== 'type')} // 变更时不显示类型
initialValues={pickValuesFromGroupPanelInfo(groupPanelInfo)}
onChange={setValues}
onSubmit={handleSubmit}
/>
</ModalWrapper>
);
});
ModalModifyGroupPanel.displayName = 'ModalModifyGroupPanel';

@ -1,5 +1,5 @@
import { findPluginPanelInfoByName } from '@/utils/plugin-helper';
import { GroupPanelType } from 'tailchat-shared';
import { GroupPanel, GroupPanelType } from 'tailchat-shared';
import type { GroupPanelValues } from './types';
/**
@ -32,3 +32,19 @@ export function buildDataFromValues(values: GroupPanelValues) {
meta,
};
}
/**
*
*/
export function pickValuesFromGroupPanelInfo(
groupPanelInfo: GroupPanel
): GroupPanelValues {
return {
...groupPanelInfo.meta,
name: groupPanelInfo.name,
type:
groupPanelInfo.type === GroupPanelType.PLUGIN
? String(groupPanelInfo.pluginPanelName)
: groupPanelInfo.type,
};
}

@ -2,6 +2,6 @@ import type { GroupPanelType } from 'tailchat-shared';
export interface GroupPanelValues {
name: string;
type: string | GroupPanelType;
type: string | GroupPanelType.TEXT | GroupPanelType.GROUP;
[key: string]: unknown;
}

Loading…
Cancel
Save