From 9654768ca58c0997e5929c1a1afed6609a7ff0c1 Mon Sep 17 00:00:00 2001 From: Suyi Date: Thu, 6 Jan 2022 03:36:14 +0800 Subject: [PATCH 1/4] chore: add license (#20) --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..95a7894 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 CNodejs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 276e3168adfd3a356a0ca4a2ac5273bca4d6ce2f Mon Sep 17 00:00:00 2001 From: Suyi Date: Thu, 6 Jan 2022 03:41:53 +0800 Subject: [PATCH 2/4] docs: add contributors badge --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ca668f..140a5f9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > Frontend Powered By React For CNode.js -## Getting Started +## Development Install dependencies, @@ -15,3 +15,7 @@ Start the dev server, ```bash $ yarn dev ``` + +## Contributors + +[![contributors](https://ergatejs.implements.io/badges/contributors/cnodejs/react-cnode.svg?owner=cnodejs&repo=react-cnode&type=svg&width=1232&size=64&padding=8)](https://github.com/cnodejs/react-cnode/graphs/contributors) From fa0d8d1de1b7b3367490615625217536c4602b14 Mon Sep 17 00:00:00 2001 From: Suyi Date: Thu, 6 Jan 2022 04:25:04 +0800 Subject: [PATCH 3/4] refactor: split component & update doc (#22) * feat: update about page * feat: update title length limit * refactor: split component --- .../CommentForm/index.tsx} | 0 .../component/CommentList/index.less | 0 .../component/CommentList/index.tsx | 8 +++++- src/component/MessageList/index.tsx | 27 +++++++++---------- src/component/TopicList/index.tsx | 20 +++++++------- src/page/about/index.tsx | 18 +++++++++---- src/page/topic/create/index.tsx | 2 +- src/page/topic/detail.tsx | 10 +++---- 8 files changed, 47 insertions(+), 38 deletions(-) rename src/{page/topic/component/CommentForm.tsx => component/CommentForm/index.tsx} (100%) rename src/{page/topic => }/component/CommentList/index.less (100%) rename src/{page/topic => }/component/CommentList/index.tsx (91%) diff --git a/src/page/topic/component/CommentForm.tsx b/src/component/CommentForm/index.tsx similarity index 100% rename from src/page/topic/component/CommentForm.tsx rename to src/component/CommentForm/index.tsx diff --git a/src/page/topic/component/CommentList/index.less b/src/component/CommentList/index.less similarity index 100% rename from src/page/topic/component/CommentList/index.less rename to src/component/CommentList/index.less diff --git a/src/page/topic/component/CommentList/index.tsx b/src/component/CommentList/index.tsx similarity index 91% rename from src/page/topic/component/CommentList/index.tsx rename to src/component/CommentList/index.tsx index 9400cd6..f1fc184 100644 --- a/src/page/topic/component/CommentList/index.tsx +++ b/src/component/CommentList/index.tsx @@ -1,5 +1,6 @@ import React, { Fragment } from 'react'; import dayjs from 'dayjs'; +import { Link } from 'umi'; import Markdown from '@/component/Markdown'; import { Comment, Avatar, Divider } from 'antd'; @@ -38,6 +39,7 @@ const CommentList: React.FC = (props) => { data: Node; }> = ({ data }) => { const { id, author, content, create_at, children } = data; + const { loginname, avatar_url } = author; return ( @@ -63,7 +65,11 @@ const CommentList: React.FC = (props) => { datetime={ {dayjs(create_at).format('YYYY-MM-DD hh:mm:ss')} } - avatar={} + avatar={ + + + + } content={
diff --git a/src/component/MessageList/index.tsx b/src/component/MessageList/index.tsx index d7faf22..5418f99 100644 --- a/src/component/MessageList/index.tsx +++ b/src/component/MessageList/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import dayjs from 'dayjs'; -import { useHistory } from 'umi'; +import { useHistory, Link } from 'umi'; import { Space, Avatar, Tag } from 'antd'; import { ListToolBarProps } from '@ant-design/pro-table'; import ProList, { ProListMetas } from '@ant-design/pro-list'; @@ -10,14 +10,13 @@ import { MESSAGE_TYPE_MAP, MessageType } from '@/constants'; import * as styles from './index.less'; const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { - const history = useHistory(); - const metas: ProListMetas = { avatar: { dataIndex: 'author.avatar_url', render: (_, entity: MessageModel) => { const { type: _type, author } = entity; const type = MESSAGE_TYPE_MAP[_type as MessageType]; + const { loginname, avatar_url } = author; return ( @@ -26,10 +25,12 @@ const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { width: '200px', }} > - - - {author.loginname} - + + + + {loginname} + +
{type.name} @@ -41,7 +42,10 @@ const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { dataIndex: 'title', valueType: 'text', render: (_, entity: MessageModel) => { - return entity.topic.title; + const { + topic: { id, title }, + } = entity; + return {title}; }, }, actions: { @@ -60,13 +64,6 @@ const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { metas={metas} className={styles.list} toolbar={toolbar} - onRow={(record: MessageModel) => { - return { - onClick: () => { - history.push(`/topic/${record.topic.id}`); - }, - }; - }} /> ); }; diff --git a/src/component/TopicList/index.tsx b/src/component/TopicList/index.tsx index ce6ee7e..6dfaa6c 100644 --- a/src/component/TopicList/index.tsx +++ b/src/component/TopicList/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import dayjs from 'dayjs'; -import { useHistory } from 'umi'; +import { Link } from 'umi'; import { Space, Avatar, Tag } from 'antd'; import { ListToolBarProps } from '@ant-design/pro-table'; import ProList, { ProListMetas } from '@ant-design/pro-list'; @@ -10,8 +10,6 @@ import { TABS_MAP, TabType } from '@/constants'; import * as styles from './index.less'; const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { - const history = useHistory(); - const metas: ProListMetas = { avatar: { dataIndex: 'author.avatar_url', @@ -19,6 +17,7 @@ const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { const { tab: _tab, author, reply_count, visit_count, top } = entity; const category = TABS_MAP[_tab as TabType]; + const { loginname, avatar_url } = author; const renderReplyVisit = () => typeof visit_count === 'number' && ( @@ -41,7 +40,9 @@ const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { return ( - + + + {renderReplyVisit()} {top ? ( 置顶 @@ -55,6 +56,10 @@ const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { title: { dataIndex: 'title', valueType: 'text', + render: (_, entity: TopicModel) => { + const { id, title } = entity; + return {title}; + }, }, actions: { render: (_, entity: TopicModel) => { @@ -73,13 +78,6 @@ const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { metas={metas} className={styles.list} toolbar={toolbar} - onRow={(record) => { - return { - onClick: () => { - history.push(`/topic/${record.id}`); - }, - }; - }} /> ); }; diff --git a/src/page/about/index.tsx b/src/page/about/index.tsx index 42011fc..f4a76a9 100644 --- a/src/page/about/index.tsx +++ b/src/page/about/index.tsx @@ -4,25 +4,33 @@ import Markdown from '@/component/Markdown'; const content = ` ## 关于 -- CNode 社区为国内最大最具影响力的 Node.js 开源技术社区,致力于 Node.js 的技术研究。 +CNode 社区为国内最大最具影响力的 Node.js 开源技术社区,致力于 Node.js 的技术研究。 -- CNode 社区由一批热爱 Node.js 技术的工程师发起,目前已经吸引了互联网各个公司的专业技术人员加入,我们非常欢迎更多对 Node.js 感兴趣的朋友。 +CNode 社区由一批热爱 Node.js 技术的工程师发起,目前已经吸引了互联网各个公司的专业技术人员加入,我们非常欢迎更多对 Node.js 感兴趣的朋友。 -- CNode 的 SLA 保证是,一个9,即 90.000000%。 +CNode 的 SLA 保证是,一个9,即 90.000000%。 社区目前由 [@alsotang](http://cnodejs.org/user/alsotang) 在维护,有问题请联系:[https://github.com/alsotang](https://github.com/alsotang) 请关注我们的官方微博:[http://weibo.com/cnodejs](http://weibo.com/cnodejs) + ## 客户端 -- 客户端由 [@soliury](https://cnodejs.org/user/soliury) 开发维护。 +客户端由 [@soliury](https://cnodejs.org/user/soliury) 开发维护。 -- 源码地址: [https://github.com/soliury/noder-react-native](https://github.com/soliury/noder-react-native) 。 +源码地址: [https://github.com/soliury/noder-react-native](https://github.com/soliury/noder-react-native) 。 立即体验 CNode 客户端,直接扫描页面右侧二维码。 另,安卓用户同时可选择:[https://github.com/TakWolf/CNode-Material-Design](https://github.com/TakWolf/CNode-Material-Design) ,这是 Java 原生开发的安卓客户端。 + + +## 贡献者 + +> egg-cnode + +[![contributors](https://ergatejs.implements.io/badges/contributors/cnodejs/egg-cnode.svg?owner=cnodejs&repo=egg-cnode&type=svg&width=1232&size=64&padding=8)](https://github.com/cnodejs/egg-cnode/graphs/contributors) `; const AboutPage: React.FC = (props) => { diff --git a/src/page/topic/create/index.tsx b/src/page/topic/create/index.tsx index 5ab332d..c0161ae 100644 --- a/src/page/topic/create/index.tsx +++ b/src/page/topic/create/index.tsx @@ -55,7 +55,7 @@ const CreateTopic: React.FC = (props) => { diff --git a/src/page/topic/detail.tsx b/src/page/topic/detail.tsx index bb3aad0..4066dd1 100644 --- a/src/page/topic/detail.tsx +++ b/src/page/topic/detail.tsx @@ -5,12 +5,12 @@ import { useRequest } from 'ahooks'; import { PageHeader, Divider } from 'antd'; import * as API from '@/service/topic'; -import SubTitle from './component/SubTitle'; import Markdown from '@/component/Markdown'; -import CommentForm from './component/CommentForm'; -import CommentList from './component/CommentList'; +import CommentList from '@/component/CommentList'; +import CommentForm from '@/component/CommentForm'; +import SubTitle from './component/SubTitle'; -const TopicDetail: React.FC> = (props) => { +const TopicDetailPage: React.FC> = (props) => { const params: Record = useParams(); const topicId = params?.id; @@ -174,6 +174,6 @@ const TopicDetail: React.FC> = (props) => { ); }; -export default TopicDetail; +export default TopicDetailPage; interface Props {} From 23b3201a90b63fefcc6f5fd44be42ae72a6e7fd4 Mon Sep 17 00:00:00 2001 From: Suyi Date: Fri, 7 Jan 2022 23:43:32 +0800 Subject: [PATCH 4/4] feat: mark one or all message (#24) --- src/component/MessageList/index.less | 10 +++++++++ src/component/MessageList/index.tsx | 23 ++++++++++++++++++--- src/component/TopicList/index.less | 10 +++++++++ src/component/TopicList/index.tsx | 6 +++++- src/model/message.ts | 31 +++++++++++++++++++++++++++- src/page/message/index.tsx | 26 +++++++++++++++++++---- src/service/message.ts | 31 ++++++++++++++++++++++++++++ 7 files changed, 128 insertions(+), 9 deletions(-) diff --git a/src/component/MessageList/index.less b/src/component/MessageList/index.less index 2532459..2655d9e 100644 --- a/src/component/MessageList/index.less +++ b/src/component/MessageList/index.less @@ -1,3 +1,5 @@ +@import '~antd/dist/antd.less'; + .list { :global { .ant-card { @@ -8,3 +10,11 @@ } } } + +.link { + color: @text-color; + + &:hover { + color: @primary-color; + } +} diff --git a/src/component/MessageList/index.tsx b/src/component/MessageList/index.tsx index 5418f99..6847eae 100644 --- a/src/component/MessageList/index.tsx +++ b/src/component/MessageList/index.tsx @@ -9,7 +9,12 @@ import { MESSAGE_TYPE_MAP, MessageType } from '@/constants'; import * as styles from './index.less'; -const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { +const MessageList: React.FC = ({ + dataSource, + loading, + toolbar, + onClick, +}) => { const metas: ProListMetas = { avatar: { dataIndex: 'author.avatar_url', @@ -25,7 +30,7 @@ const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { width: '200px', }} > - + {loginname} @@ -43,9 +48,20 @@ const MessageList: React.FC = ({ dataSource, loading, toolbar }) => { valueType: 'text', render: (_, entity: MessageModel) => { const { + id: messageId, topic: { id, title }, } = entity; - return {title}; + return ( + { + onClick && onClick(messageId); + }} + > + {title} + + ); }, }, actions: { @@ -74,4 +90,5 @@ interface Props { dataSource?: MessageModel[]; loading?: boolean; toolbar?: ListToolBarProps; + onClick?: (id: string) => void; } diff --git a/src/component/TopicList/index.less b/src/component/TopicList/index.less index 2532459..2655d9e 100644 --- a/src/component/TopicList/index.less +++ b/src/component/TopicList/index.less @@ -1,3 +1,5 @@ +@import '~antd/dist/antd.less'; + .list { :global { .ant-card { @@ -8,3 +10,11 @@ } } } + +.link { + color: @text-color; + + &:hover { + color: @primary-color; + } +} diff --git a/src/component/TopicList/index.tsx b/src/component/TopicList/index.tsx index 6dfaa6c..c6c6692 100644 --- a/src/component/TopicList/index.tsx +++ b/src/component/TopicList/index.tsx @@ -58,7 +58,11 @@ const TopicList: React.FC = ({ dataSource, loading, toolbar }) => { valueType: 'text', render: (_, entity: TopicModel) => { const { id, title } = entity; - return {title}; + return ( + + {title} + + ); }, }, actions: { diff --git a/src/model/message.ts b/src/model/message.ts index e09a8dc..888a641 100644 --- a/src/model/message.ts +++ b/src/model/message.ts @@ -45,5 +45,34 @@ export default () => { setUnreadMessage(data.hasnot_read_messages); }, [token]); - return { count, message, unreadMessage, load, fetch }; + const mark = useCallback( + async (id: string) => { + if (!token) { + return; + } + + await API.markMessage(id, { + accesstoken: token, + }); + + load(); + fetch(); + }, + [token], + ); + + const markAll = useCallback(async () => { + if (!token) { + return; + } + + await API.markAllMessage({ + accesstoken: token, + }); + + load(); + fetch(); + }, [token]); + + return { count, message, unreadMessage, load, fetch, mark, markAll }; }; diff --git a/src/page/message/index.tsx b/src/page/message/index.tsx index d304b4d..ae36802 100644 --- a/src/page/message/index.tsx +++ b/src/page/message/index.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { useModel } from 'umi'; -import { Divider } from 'antd'; +import { Divider, Button } from 'antd'; import ProCard from '@ant-design/pro-card'; import MessageList from '@/component/MessageList'; const MessagePage: React.FC = (props) => { - const { message, unreadMessage } = useModel('message'); + const { message, unreadMessage, mark, markAll } = useModel('message'); console.debug('===message', message); console.debug('===unreadMessage', unreadMessage); @@ -15,12 +15,30 @@ const MessagePage: React.FC = (props) => { return 暂无新消息; } - return ; + return ( + mark(id)} /> + ); }; return (
- {renderUnreadMessage()} + { + markAll(); + }} + > + 标记全部 + + } + > + {renderUnreadMessage()} + diff --git a/src/service/message.ts b/src/service/message.ts index d6b373e..c81a753 100644 --- a/src/service/message.ts +++ b/src/service/message.ts @@ -29,6 +29,37 @@ export const getMessages = async (params: { return res; }; +export const markMessage = async ( + id: string, + data: { + accesstoken: string; + }, +) => { + const options: any = { + method: 'POST', + data, + }; + const res: any = await request( + `${BASE_URL}/api/v1/message/mark_one/${id}`, + options, + ); + + return res; +}; + +export const markAllMessage = async (data: { accesstoken: string }) => { + const options: any = { + method: 'POST', + data, + }; + const res: any = await request( + `${BASE_URL}/api/v1/message/mark_all`, + options, + ); + + return res; +}; + interface MessageCollection { has_read_messages: MessageModel[]; hasnot_read_messages: MessageModel[];