feat: 创建话题

pull/56/head
moonrailgun 3 years ago
parent 21f6442634
commit 0f58129c74

@ -8,14 +8,14 @@ export function useAsyncRequest<T extends FunctionReturningPromise>(
fn: T, fn: T,
deps: DependencyList = [] deps: DependencyList = []
) { ) {
const [{ loading }, call] = useAsyncFn(async (...args) => { const [{ loading, value }, call] = useAsyncFn(async (...args: any[]) => {
try { try {
await fn(...args); return await fn(...args);
} catch (err) { } catch (err) {
showErrorToasts(isDevelopment ? err : t('系统忙, 请稍后再试')); showErrorToasts(isDevelopment ? err : t('系统忙, 请稍后再试'));
console.error(err); console.error(err);
} }
}, deps); }, deps);
return [{ loading }, call as T] as const; return [{ loading, value }, call as T] as const;
} }

@ -310,6 +310,7 @@ declare module '@capital/component' {
size?: 'small' | 'middle' | 'large'; size?: 'small' | 'middle' | 'large';
shape?: 'circle' | 'square'; shape?: 'circle' | 'square';
title?: string; title?: string;
onClick?: React.MouseEventHandler<HTMLElement>;
}>; }>;
export const PillTabs: any; export const PillTabs: any;

@ -1,7 +1,7 @@
const path = require('path'); const path = require('path');
module.exports = { module.exports = {
externalDeps: ['react'], externalDeps: ['react', 'styled-components'],
pluginRoot: path.resolve(__dirname, './web'), pluginRoot: path.resolve(__dirname, './web'),
outDir: path.resolve(__dirname, '../../public'), outDir: path.resolve(__dirname, '../../public'),
}; };

@ -71,6 +71,7 @@ class GroupTopicService extends TcService {
}) })
.limit(size) .limit(size)
.skip((page - 1) * 20) .skip((page - 1) * 20)
.sort({ _id: 'desc' })
.exec(); .exec();
const json = await this.transformDocuments(ctx, {}, topic); const json = await this.transformDocuments(ctx, {}, topic);

@ -8,6 +8,8 @@
"sync:declaration": "tailchat declaration github" "sync:declaration": "tailchat declaration github"
}, },
"devDependencies": { "devDependencies": {
"react": "18.2.0" "@types/styled-components": "^5.1.26",
"react": "18.2.0",
"styled-components": "^5.3.6"
} }
} }

@ -0,0 +1,33 @@
import { useAsyncRequest } from '@capital/common';
import { Button, ModalWrapper, TextArea } from '@capital/component';
import React, { useState } from 'react';
import styled from 'styled-components';
import { Translate } from '../../translate';
const Footer = styled.div({
textAlign: 'right',
paddingTop: 10,
});
export const TopicCreate: React.FC<{
onCreate: (text: string) => Promise<void>;
}> = React.memo((props) => {
const [text, setText] = useState('');
const [{ loading }, handleCreate] = useAsyncRequest(async () => {
await props.onCreate(text);
}, [text]);
return (
<ModalWrapper title={Translate.createBtn}>
<TextArea value={text} onChange={(e) => setText(e.target.value)} />
<Footer>
<Button type="primary" loading={loading} onClick={handleCreate}>
{Translate.createBtn}
</Button>
</Footer>
</ModalWrapper>
);
});
TopicCreate.displayName = 'TopicCreate';

@ -1,20 +1,23 @@
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
import { TopicCard } from '../components/TopicCard'; import { TopicCard } from '../components/TopicCard';
import { useAsyncRequest, useGroupPanelContext } from '@capital/common';
import { import {
showToasts, Button,
useAsyncRequest, Empty,
useGroupPanelContext, IconBtn,
} from '@capital/common'; openModal,
import { Button, Empty, IconBtn } from '@capital/component'; closeModal,
} from '@capital/component';
import { request } from '../request'; import { request } from '../request';
import './GroupTopicPanelRender.less';
import { Translate } from '../translate'; import { Translate } from '../translate';
import { TopicCreate } from '../components/modals/TopicCreate';
import './GroupTopicPanelRender.less';
const GroupTopicPanelRender: React.FC = React.memo(() => { const GroupTopicPanelRender: React.FC = React.memo(() => {
const panelInfo = useGroupPanelContext(); const panelInfo = useGroupPanelContext();
const [{ value: list = [] }, fetch] = useAsyncRequest(async () => { const [{ value: list = [] }, fetch] = useAsyncRequest(async () => {
if (!panelInfo) { if (!panelInfo.groupId || !panelInfo.panelId) {
return []; return [];
} }
@ -26,15 +29,29 @@ const GroupTopicPanelRender: React.FC = React.memo(() => {
}); });
return data; return data;
}, [panelInfo]); }, [panelInfo.groupId, panelInfo.panelId]);
useEffect(() => { useEffect(() => {
fetch(); fetch();
}, [fetch]); }, [fetch]);
const handleCreateTopic = useCallback(() => { const handleCreateTopic = useCallback(() => {
showToasts('TODO: 创建话题'); const key = openModal(
}, []); <TopicCreate
onCreate={async (text) => {
await request.post('create', {
groupId: panelInfo.groupId,
panelId: panelInfo.panelId,
content: text,
});
fetch();
closeModal(key);
}}
/>
);
}, [panelInfo, fetch]);
return ( return (
<div className="plugin-topic-group-panel"> <div className="plugin-topic-group-panel">

@ -1,4 +1,5 @@
import { regGroupPanel, Loadable } from '@capital/common'; import { regGroupPanel } from '@capital/common';
import { Loadable } from '@capital/component';
import { Translate } from './translate'; import { Translate } from './translate';
const PLUGIN_NAME = 'com.msgbyte.topic'; const PLUGIN_NAME = 'com.msgbyte.topic';

@ -16,6 +16,7 @@ declare module '@capital/common' {
/** /**
* *
* @deprecated @capital/component
*/ */
export const openModal: ( export const openModal: (
content: React.ReactNode, content: React.ReactNode,
@ -39,16 +40,34 @@ declare module '@capital/common' {
} }
) => number; ) => number;
/**
* @deprecated @capital/component
*/
export const closeModal: any; export const closeModal: any;
/**
* @deprecated @capital/component
*/
export const ModalWrapper: any; export const ModalWrapper: any;
/**
* @deprecated @capital/component
*/
export const useModalContext: any; export const useModalContext: any;
/**
* @deprecated @capital/component
*/
export const openConfirmModal: any; export const openConfirmModal: any;
/**
* @deprecated @capital/component
*/
export const openReconfirmModal: any; export const openReconfirmModal: any;
/**
* @deprecated @capital/component
*/
export const Loadable: any; export const Loadable: any;
export const getGlobalState: any; export const getGlobalState: any;
@ -109,13 +128,16 @@ declare module '@capital/common' {
export const uploadFile: any; export const uploadFile: any;
export const showToasts: any; export const showToasts: (
message: string,
type?: 'info' | 'success' | 'error' | 'warning'
) => void;
export const showErrorToasts: any; export const showErrorToasts: (error: any) => void;
export const fetchAvailableServices: any; export const fetchAvailableServices: any;
export const isValidStr: any; export const isValidStr: (str: any) => str is string;
export const useGroupPanelInfo: any; export const useGroupPanelInfo: any;
@ -215,6 +237,14 @@ declare module '@capital/common' {
required?: string[]; required?: string[];
}) => void; }) => void;
export const pluginGroupPanelBadges: any;
export const regGroupPanelBadge: any;
export const pluginGroupTextPanelExtraMenus: any;
export const regPluginGroupTextPanelExtraMenu: any;
export const useGroupIdContext: () => string; export const useGroupIdContext: () => string;
export const useGroupPanelContext: () => { export const useGroupPanelContext: () => {
@ -233,8 +263,6 @@ declare module '@capital/component' {
export const Checkbox: any; export const Checkbox: any;
export const Empty: any;
export const Input: any; export const Input: any;
export const Divider: any; export const Divider: any;
@ -254,6 +282,17 @@ declare module '@capital/component' {
*/ */
export const notification: any; export const notification: any;
export const Empty: React.FC<
React.PropsWithChildren<{
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
imageStyle?: React.CSSProperties;
image?: React.ReactNode;
description?: React.ReactNode;
}>
>;
export const Avatar: any; export const Avatar: any;
export const SensitiveText: React.FC<{ className?: string; text: string }>; export const SensitiveText: React.FC<{ className?: string; text: string }>;
@ -266,7 +305,9 @@ declare module '@capital/component' {
export const IconBtn: React.FC<{ export const IconBtn: React.FC<{
icon: string; icon: string;
className?: string;
iconClassName?: string; iconClassName?: string;
size?: 'small' | 'middle' | 'large';
shape?: 'circle' | 'square'; shape?: 'circle' | 'square';
title?: string; title?: string;
}>; }>;
@ -291,7 +332,27 @@ declare module '@capital/component' {
export const DefaultFullModalTextAreaEditorRender: any; export const DefaultFullModalTextAreaEditorRender: any;
export const openModal: any; export const openModal: (
content: React.ReactNode,
props?: {
/**
*
* @default false
*/
closable?: boolean;
/**
*
*/
maskClosable?: boolean;
/**
* modal
*/
onCloseModal?: () => void;
}
) => number;
export const closeModal: any; export const closeModal: any;
@ -303,6 +364,8 @@ declare module '@capital/component' {
export const openReconfirmModal: any; export const openReconfirmModal: any;
export const Loadable: any;
export const Loading: any; export const Loading: any;
export const SidebarView: any; export const SidebarView: any;

Loading…
Cancel
Save