feat: 创建群组面板

pull/13/head
moonrailgun 4 years ago
parent 9a3a0868ac
commit dffd9afa9d

@ -2,6 +2,8 @@ import { io, Socket } from 'socket.io-client';
import _isNil from 'lodash/isNil'; import _isNil from 'lodash/isNil';
import { getServiceUrl } from '../manager/service'; import { getServiceUrl } from '../manager/service';
import { isDevelopment } from '../utils/environment'; import { isDevelopment } from '../utils/environment';
import { showToasts } from '../manager/ui';
import { t } from '../i18n';
let socket: Socket; let socket: Socket;
@ -88,7 +90,13 @@ export function createSocket(token: string): Promise<AppSocket> {
socket.once('connect', () => { socket.once('connect', () => {
// 连接成功 // 连接成功
const appSocket = new AppSocket(socket); const appSocket = new AppSocket(socket);
appSocket.request('chat.converse.findAndJoinRoom'); // 立即请求加入房间 appSocket.request('chat.converse.findAndJoinRoom').catch((err) => {
console.error(err);
showToasts(
t('无法加入房间, 您将无法获取到最新的信息, 请刷新页面后重试'),
'error'
);
}); // 立即请求加入房间
resolve(appSocket); resolve(appSocket);
}); });
socket.once('error', () => { socket.once('error', () => {

@ -0,0 +1,8 @@
import { useRef, MutableRefObject } from 'react';
export function useUpdateRef<T>(state: T): MutableRefObject<T> {
const ref = useRef<T>(state);
ref.current = state;
return ref;
}

@ -33,6 +33,7 @@ export { useAsyncFn } from './hooks/useAsyncFn';
export { useAsyncRequest } from './hooks/useAsyncRequest'; export { useAsyncRequest } from './hooks/useAsyncRequest';
export { useMountedState } from './hooks/useMountedState'; export { useMountedState } from './hooks/useMountedState';
export { useRafState } from './hooks/useRafState'; export { useRafState } from './hooks/useRafState';
export { useUpdateRef } from './hooks/useUpdateRef';
// manager // manager
export { getStorage, setStorage, useStorage } from './manager/storage'; export { getStorage, setStorage, useStorage } from './manager/storage';

@ -135,3 +135,22 @@ export async function applyGroupInvite(inviteCode: string): Promise<void> {
code: inviteCode, code: inviteCode,
}); });
} }
/**
*
*/
export async function createGroupPanel(
groupId: string,
options: {
name: string;
type: number;
parentId?: string;
provider?: string;
meta?: Record<string, unknown>;
}
) {
await request.post('/api/group/createGroupPanel', {
...options,
groupId,
});
}

@ -1,13 +1,68 @@
import React from 'react'; import React from 'react';
import { t } from 'tailchat-shared'; import {
FastFormFieldMeta,
GroupPanelType,
t,
useAsyncRequest,
} from 'tailchat-shared';
import { createGroupPanel } from '../../../../shared/model/group';
import { ModalWrapper } from '../Modal'; import { ModalWrapper } from '../Modal';
import { WebFastForm } from '../WebFastForm';
type Values = {
name: string;
type: string;
};
const baseFields: FastFormFieldMeta[] = [
{ type: 'text', name: 'name', label: t('面板名') },
{
type: 'select',
name: 'type',
label: t('类型'),
options: [
{
label: t('聊天频道'),
value: GroupPanelType.TEXT,
},
{
label: t('面板分组'),
value: GroupPanelType.GROUP,
},
],
},
];
/**
*
*/
export const ModalCreateGroupPanel: React.FC<{ export const ModalCreateGroupPanel: React.FC<{
groupId: string; groupId: string;
onCreateSuccess: () => void;
}> = React.memo((props) => { }> = React.memo((props) => {
const [, handleSubmit] = useAsyncRequest(
async (values: Values) => {
const { name, type } = values;
let panelType: number;
if (typeof type === 'string') {
panelType = GroupPanelType.PLUGIN;
} else {
panelType = type;
}
await createGroupPanel(props.groupId, {
name,
type: panelType,
});
props.onCreateSuccess();
},
[props.groupId, props.onCreateSuccess]
);
return ( return (
<ModalWrapper title={t('创建群组面板')}> <ModalWrapper title={t('创建群组面板')} style={{ width: 440 }}>
: {props.groupId} <WebFastForm fields={baseFields} onSubmit={handleSubmit} />
</ModalWrapper> </ModalWrapper>
); );
}); });

@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { import {
useGroupInfo, useGroupInfo,
GroupPanel as GroupPanelInfo, GroupPanel as GroupPanelInfo,
@ -11,7 +11,7 @@ import { Button } from 'antd';
import _isEqual from 'lodash/isEqual'; import _isEqual from 'lodash/isEqual';
import { GroupPanelTree } from './GroupPanelTree'; import { GroupPanelTree } from './GroupPanelTree';
import { FullModalCommonTitle } from '@/components/FullModal/CommonTitle'; import { FullModalCommonTitle } from '@/components/FullModal/CommonTitle';
import { openModal } from '@/components/Modal'; import { closeModal, openModal } from '@/components/Modal';
import { ModalCreateGroupPanel } from '../../CreateGroupPanel'; import { ModalCreateGroupPanel } from '../../CreateGroupPanel';
export const GroupPanel: React.FC<{ export const GroupPanel: React.FC<{
@ -21,34 +21,50 @@ export const GroupPanel: React.FC<{
const groupInfo = useGroupInfo(groupId); const groupInfo = useGroupInfo(groupId);
const groupPanels = groupInfo?.panels ?? []; const groupPanels = groupInfo?.panels ?? [];
const [editingGroupPanels, setEditingGroupPanels] = useState(groupPanels); const [editingGroupPanels, setEditingGroupPanels] = useState(groupPanels);
const isEditingRef = useRef(false);
useEffect(() => {
// 如果不处于编辑状态, 则一直更新最新的面板
if (isEditingRef.current === true) {
return;
}
setEditingGroupPanels(groupPanels);
}, [groupPanels]);
const handleChange = useCallback((newGroupPanels: GroupPanelInfo[]) => { const handleChange = useCallback((newGroupPanels: GroupPanelInfo[]) => {
isEditingRef.current = true;
setEditingGroupPanels(newGroupPanels); setEditingGroupPanels(newGroupPanels);
}, []); }, []);
const [{ loading }, handleSave] = useAsyncRequest(async () => { const [{ loading }, handleSave] = useAsyncRequest(async () => {
await modifyGroupField(groupId, 'panels', editingGroupPanels); await modifyGroupField(groupId, 'panels', editingGroupPanels);
isEditingRef.current = false;
showToasts(t('保存成功'), 'success'); showToasts(t('保存成功'), 'success');
}, [editingGroupPanels]); }, [editingGroupPanels]);
const [{ loading: createLoading }, handleCreatePanel] = const handleReset = useCallback(() => {
useAsyncRequest(async () => { setEditingGroupPanels(groupPanels);
// TODO isEditingRef.current = false;
}, []); }, [groupPanels]);
const handleOpenCreatePanelModal = useCallback(() => { const handleOpenCreatePanelModal = useCallback(() => {
openModal(<ModalCreateGroupPanel groupId={groupId} />); const key = openModal(
}, [handleCreatePanel]); <ModalCreateGroupPanel
groupId={groupId}
onCreateSuccess={() => {
closeModal(key);
isEditingRef.current = false;
}}
/>
);
}, []);
return ( return (
<div> <div>
<FullModalCommonTitle <FullModalCommonTitle
extra={ extra={
<Button <Button type="primary" onClick={handleOpenCreatePanelModal}>
type="primary"
loading={createLoading}
onClick={handleOpenCreatePanelModal}
>
{t('创建面板')} {t('创建面板')}
</Button> </Button>
} }
@ -62,9 +78,12 @@ export const GroupPanel: React.FC<{
/> />
{!_isEqual(groupPanels, editingGroupPanels) && ( {!_isEqual(groupPanels, editingGroupPanels) && (
<Button className="mt-2" loading={loading} onClick={handleSave}> <div className="space-x-1 mt-2">
{t('保存')} <Button type="primary" loading={loading} onClick={handleSave}>
</Button> {t('保存')}
</Button>
<Button onClick={handleReset}>{t('重置')}</Button>
</div>
)} )}
</div> </div>
); );

Loading…
Cancel
Save