diff --git a/src/app.tsx b/src/app.tsx index 07eb500..98b3d0c 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -15,6 +15,7 @@ import { queryCurrentUser, queryInvitations, refreshTokens } from './services/ap import type { SiderMenuProps } from '@ant-design/pro-layout/lib/components/SiderMenu/SiderMenu'; import { getDefaultSiteConfigAPI } from './helpers/index'; import { FetchPostsStorageParamsState } from './services/constants'; +import MenuFeedbackButton from './components/menu/MenuFeedbackButton'; const { Text } = Typography; @@ -195,6 +196,10 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => { history.push('/user/login'); } }, - links: [, ], + links: [ + , + , + , + ], }; }; diff --git a/src/components/Guide/StoreSetting.tsx b/src/components/Guide/StoreSetting.tsx index 9294c45..fa50344 100644 --- a/src/components/Guide/StoreSetting.tsx +++ b/src/components/Guide/StoreSetting.tsx @@ -56,8 +56,12 @@ export default () => { return Promise.resolve(); }; const updateRepoSettings = async (values: { storeRepo: string; publishRepo: string }) => { - setStoreSetting((prev) => ({ ...prev, repos: values })); - message.success(intl.formatMessage({ id: 'messages.store.setRepoName' }, values)); + if (values.storeRepo !== values.publishRepo) { + setStoreSetting((prev) => ({ ...prev, repos: values })); + message.success(intl.formatMessage({ id: 'messages.store.setRepoName' }, values)); + } else { + message.error(intl.formatMessage({ id: 'messages.store.form.sameRepoName' }, values)); + } }; return ( diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx new file mode 100644 index 0000000..16ebe0b --- /dev/null +++ b/src/components/Icon/index.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import Icon from '@ant-design/icons'; + +const MatrixSvg = () => ( + + + + + +); +export const MatrixIcon: React.FC = (props) => ; + +const TelegramSvg = () => ( + + + +); +export const TelegramIcon: React.FC = (props) => ; + +const DiscordSvg = () => ( + + + + +); +export const DiscordIcon: React.FC = (props) => ; +const MetaLogoSvg = () => ( + + + + +); +export const MetaLogoIcon: React.FC = (props) => ; + +const ElementSvg = () => ( + + + +); +export const ElementIcon: React.FC = (props) => ; diff --git a/src/components/menu/MenuFeedbackButton/index.tsx b/src/components/menu/MenuFeedbackButton/index.tsx new file mode 100644 index 0000000..839eb57 --- /dev/null +++ b/src/components/menu/MenuFeedbackButton/index.tsx @@ -0,0 +1,18 @@ +import { MatrixIcon } from '../../Icon/index'; +import { Tooltip } from 'antd'; + +const feedbackLink = 'https://forms.gle/1HAZ8puQ9vhBSqMGA'; + +export default () => { + return ( +
{ + window.open(feedbackLink, '_blank'); + }} + > + + + +
+ ); +}; diff --git a/src/components/menu/MenuLanguageSwitch/index.tsx b/src/components/menu/MenuLanguageSwitch/index.tsx index 9c6820e..f15c628 100644 --- a/src/components/menu/MenuLanguageSwitch/index.tsx +++ b/src/components/menu/MenuLanguageSwitch/index.tsx @@ -1,7 +1,8 @@ +import { setLocale } from 'umi'; +import { useState } from 'react'; import { GlobalOutlined } from '@ant-design/icons'; import { Dropdown, Menu, Typography } from 'antd'; import style from './index.less'; -import { setLocale } from 'umi'; const languages = [ { @@ -29,13 +30,25 @@ const menu = ( ); -export default () => ( - - - -); +export default () => { + const [visible, setVisible] = useState(false); + + return ( +
{ + setVisible((v) => !v); + return; + }} + > + setVisible(isVisible)} + overlayClassName={style.menuLanguageSwitch} + > + + +
+ ); +}; diff --git a/src/components/menu/MenuMoreInfo/index.tsx b/src/components/menu/MenuMoreInfo/index.tsx index 87ae443..998b00f 100644 --- a/src/components/menu/MenuMoreInfo/index.tsx +++ b/src/components/menu/MenuMoreInfo/index.tsx @@ -1,96 +1,126 @@ +import { Dropdown, Menu } from 'antd'; +import { Fragment, useState } from 'react'; +import { FormattedMessage } from 'umi'; import { - GithubOutlined, - LinkOutlined, + TwitterOutlined, MediumOutlined, + LinkOutlined, QuestionOutlined, - TwitterOutlined, + YoutubeOutlined, } from '@ant-design/icons'; -import { Dropdown, Menu } from 'antd'; -import { FormattedMessage } from 'umi'; +import { TelegramIcon, DiscordIcon, ElementIcon, MetaLogoIcon } from '../../Icon/index'; import style from './index.less'; +const menuJson = [ + { + title: , + item: [ + { + url: 'https://matrix.to/#/!jrjmzTFiYYIuKnRpEg:matrix.org?via=matrix.org', + icon: , + name: 'Matrix Group', + }, + { + url: 'https://discord.com/invite/59cXXWCWUT', + icon: , + name: 'Discord', + }, + { + url: 'https://t.me/metanetwork', + icon: , + name: 'Telegram', + }, + { + url: 'https://twitter.com/realMetaNetwork', + icon: , + name: 'Twitter', + }, + { + url: 'https://medium.com/meta-network', + icon: , + name: 'Medium', + }, + { + url: 'https://www.youtube.com/channel/UC-rNon6FUm3blTnSrXta2gw', + icon: , + name: 'Youtube', + }, + ], + }, + { + title: , + item: [ + { + url: 'https://www.meta.io', + icon: , + name: 'Meta.io', + }, + { + url: 'https://www.matataki.io', + icon: , + name: 'Matataki', + }, + { + url: 'https://home.metanetwork.online', + icon: , + name: 'home', + }, + ], + }, + { + title: , + item: [ + { + url: 'https://metanetwork.online/terms', + icon: , + name: , + }, + { + url: 'https://metanetwork.online/privacy', + icon: , + name: , + }, + ], + }, +]; + const menu = ( - - - - }> - - Twitter - - - }> - - Telegram - - - }> - - Discord - - - }> - - Medium - - - }> - - Github - - - - - - - - - - - - - - - - - - Meta.io - - - - - Meta Space - - - - - Meta Network - - - - - - - - - - - - - - - - + {menuJson.map((i, idx) => ( + + {i.title} + {i.item.map((j, idxJ) => ( + + + {j.name} + + + ))} + {idx < menuJson.length - 1 ? : null} + + ))} ); -export default () => ( - - - -); +export default () => { + const [visible, setVisible] = useState(false); + + return ( +
{ + setVisible((v) => !v); + return; + }} + > + setVisible(isVisible)} + overlayClassName={style.menuMoreInfo} + > + + +
+ ); +}; diff --git a/src/locales/en-US/component.ts b/src/locales/en-US/component.ts index b601235..dbc57d2 100644 --- a/src/locales/en-US/component.ts +++ b/src/locales/en-US/component.ts @@ -22,7 +22,6 @@ export default { 'component.button.regenerate': 'regenerate', 'component.status.alreadyBound': 'Already bound', 'component.status.notBound': 'Not bound', - 'component.badge.invitationAvailable': 'Invitation code available', - 'component.badge.invitationUsed': 'Used invitation code', + 'component.status.used': 'Used', 'component.full.tip': 'If the page does not respond, you can manually close it!', }; diff --git a/src/locales/en-US/menu.ts b/src/locales/en-US/menu.ts index 2064fdd..56d65e9 100644 --- a/src/locales/en-US/menu.ts +++ b/src/locales/en-US/menu.ts @@ -22,7 +22,7 @@ export default { 'menu.moreInfo.policy': 'Policy', 'menu.moreInfo.terms': 'Terms', 'menu.moreInfo.privacyPolicy': 'Privacy Policy', - 'menu.moreInfo.versions': 'Version record', + 'menu.moreInfo.home': 'Home', 'menu.post.create': 'Create', 'menu.settings': 'Settings', }; diff --git a/src/locales/en-US/messages.ts b/src/locales/en-US/messages.ts index a3a898c..481268f 100644 --- a/src/locales/en-US/messages.ts +++ b/src/locales/en-US/messages.ts @@ -49,14 +49,16 @@ export default { 'The storage repository already exists, please set a new name', 'messages.store.form.repoName': 'Please set the name of the storage repository', 'messages.store.form.repoNameAvailable': 'This name is available!', + 'messages.store.form.sameRepoName': + 'The names of the repositories should not be the same, please set a new name', 'messages.invitation.title': 'Invitation code management', 'messages.invitation.description': 'Manage the invitation codes you have here.\nYou can edit the invitation information below to customize the information that the other party will accept after sending.', - 'messages.invitation.cardTitle': 'Invitation code #{id}', + 'messages.invitation.inviteMessage': + 'Hi, Meta Network Natives are inviting you to be their neighbors!,visit https://home.metanetwork.online,join us with your invitation code! ', 'messages.info.updateSuccess': 'Information update completed', 'messages.info.updateFailed': 'Information update failed', 'messages.info.copySuccess': 'Copy successfully', - 'messages.invitation.cardLabel': 'Invitation code', 'messages.invitation.editInfoHere': 'You can edit the information here', 'messages.invitation.inviteeLabel': 'Invited people', 'messages.invitation.inviteeName': 'The name of the invitee', @@ -180,7 +182,6 @@ export default { 'messages.editor.submit.generateKey.fail': 'Generated failed', 'messages.editor.submit.bindStorage': 'Please bind GitHub', 'messages.editor.submit.uploadMetadata.fail': 'Failed to upload metadata, please try again!', - 'messages.invitation.card.title': 'Invitation code #{codeId}', 'messages.delete.success': 'deleted successfully', 'messages.delete.fail': 'delete failed', 'messages.dashboard.lastPublishDate': 'Last publish date: {time, time, ::yyyyMMddHHmmss}', diff --git a/src/locales/zh-CN/component.ts b/src/locales/zh-CN/component.ts index 7fe1628..d063c83 100644 --- a/src/locales/zh-CN/component.ts +++ b/src/locales/zh-CN/component.ts @@ -22,7 +22,6 @@ export default { 'component.button.regenerate': '重新生成', 'component.status.alreadyBound': '已绑定', 'component.status.notBound': '未绑定', - 'component.badge.invitationAvailable': '邀请码可用', - 'component.badge.invitationUsed': '邀请码已使用', + 'component.status.used': '已使用', 'component.full.tip': '如遇到页面失去反馈,可手动关闭!', }; diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts index 849199f..686bb7a 100644 --- a/src/locales/zh-CN/menu.ts +++ b/src/locales/zh-CN/menu.ts @@ -21,7 +21,7 @@ export default { 'menu.moreInfo.policy': '政策', 'menu.moreInfo.terms': '条款', 'menu.moreInfo.privacyPolicy': '隐私政策', - 'menu.moreInfo.versions': '版本记录', + 'menu.moreInfo.home': '首页', 'menu.post.create': '创作', 'menu.settings': '设置', }; diff --git a/src/locales/zh-CN/messages.ts b/src/locales/zh-CN/messages.ts index 84b54b8..40d7d6e 100644 --- a/src/locales/zh-CN/messages.ts +++ b/src/locales/zh-CN/messages.ts @@ -39,14 +39,13 @@ export default { 'messages.store.repoNameAlreadyExists': '该存储仓库已存在,请设定一个新的名称', 'messages.store.form.repoName': '请设定存储仓库的名称', 'messages.store.form.repoNameAvailable': '可以使用该名称!', + 'messages.store.form.sameRepoName': '仓库名称不可以重复,请重新设定名称', 'messages.invitation.title': '邀请码管理', 'messages.invitation.description': '在这里管理你拥有的邀请码。\n你可以在下方编辑邀请信息,定制发送后对方会接受的信息。', - 'messages.invitation.cardTitle': '邀请码 #{id}', 'messages.info.updateSuccess': '信息更新完成', 'messages.info.updateFailed': '信息更新失败', 'messages.info.copySuccess': '复制成功', - 'messages.invitation.cardLabel': '邀请代码', 'messages.invitation.editInfoHere': '可以在此处编辑信息', 'messages.invitation.inviteeLabel': '受邀人', 'messages.invitation.inviteeName': '受邀人的称呼', @@ -161,7 +160,6 @@ export default { 'messages.editor.submit.generateKey.fail': '生成失败', 'messages.editor.submit.bindStorage': '请绑定 GitHub', 'messages.editor.submit.uploadMetadata.fail': '上传 metadata 失败, 请重试!', - 'messages.invitation.card.title': '邀请码 #{codeId}', 'messages.delete.success': '删除成功', 'messages.delete.fail': '删除失败', 'messages.dashboard.lastPublishDate': '上次发布时间:{time, time, ::yyyyMMddHHmmss}', @@ -170,4 +168,6 @@ export default { 'messages.dashboard.publishing': '正在发布中...', 'messages.dashboard.submitted': '已提交', 'messages.dashboard.settings': '设置项', + 'messages.invitation.inviteMessage': + 'Hi,Meta Network原住民正在邀请您来做邻居,快去 https://home.metanetwork.online,通过您的邀请码来入驻吧!', }; diff --git a/src/pages/Invitation.less b/src/pages/Invitation.less new file mode 100644 index 0000000..1fd8942 --- /dev/null +++ b/src/pages/Invitation.less @@ -0,0 +1,7 @@ +.lessMargin > form > div { + margin: 1vh 0; +} + +.flexedListElement { + margin: 0 1vw; +} diff --git a/src/pages/Invitation.tsx b/src/pages/Invitation.tsx index f1ba549..d44a4a9 100644 --- a/src/pages/Invitation.tsx +++ b/src/pages/Invitation.tsx @@ -1,14 +1,16 @@ import { useIntl, useRequest } from 'umi'; +import { List, notification } from 'antd'; import { CopyOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-layout'; -import { List, Badge, Card, Divider, notification } from 'antd'; -import ProForm, { ProFormText } from '@ant-design/pro-form'; +import ProFrom, { ProFormText } from '@ant-design/pro-form'; +import { queryInvitations } from '@/services/api/meta-ucenter'; import FormattedDescription from '@/components/FormattedDescription'; -import { queryInvitations, updateInvitation } from '@/services/api/meta-ucenter'; + +import styles from './Invitation.less'; export default () => { - const intl = useIntl(); const { data, loading } = useRequest(() => queryInvitations()); + const intl = useIntl(); const list = data || []; return ( @@ -18,110 +20,48 @@ export default () => { content={} > { - const isUnused: boolean = item.invitee_user_id === 0; - return ( - - + null, + }} > - - { - const body = { - sub: values.sub, - message: values.message, - } as GLOBAL.InvitationInfo; - const result = await updateInvitation(item.signature, body); - if (result.message === 'ok') { - notification.success({ - message: intl.formatMessage({ id: 'messages.info.updateSuccess' }), - }); - } else { - notification.error({ - message: intl.formatMessage({ id: 'messages.info.updateFailed' }), - description: result.message, - }); - } - }} - > - { - const sigArea = document.querySelector( - `#signature_${item.id}`, - ) as HTMLInputElement; - sigArea?.select(); - document.execCommand('copy'); - notification.success({ - message: intl.formatMessage({ id: 'messages.info.copySuccess' }), - }); - }} - > - - - ) : ( - - ), - }} - initialValue={item.signature} - label={intl.formatMessage({ id: 'messages.invitation.cardLabel' })} - width="md" - name="signature" - disabled={!isUnused} - /> - -

{intl.formatMessage({ id: 'messages.invitation.editInfoHere' })}

- - -
-
-
+ { + await navigator.clipboard.writeText( + intl.formatMessage({ id: 'messages.invitation.inviteMessage' }) + + item.signature, + ); + notification.success({ + message: intl.formatMessage({ id: 'messages.info.copySuccess' }), + }); + }} + > + + + ), + }} + initialValue={item.signature} + wrapperCol={{ span: 24 }} + width="md" + name="signature" + disabled={item.invitee_user_id !== 0} // invitation code used + /> + + + {intl.formatMessage({ id: 'component.status.used' })} +
); }} diff --git a/src/pages/content/PublishedPosts.tsx b/src/pages/content/PublishedPosts.tsx index cfecf56..ffedbc5 100644 --- a/src/pages/content/PublishedPosts.tsx +++ b/src/pages/content/PublishedPosts.tsx @@ -117,7 +117,7 @@ export default () => { return ( } > diff --git a/src/pages/manage/Source/index.tsx b/src/pages/manage/Source/index.tsx index 7858ba5..842ac77 100644 --- a/src/pages/manage/Source/index.tsx +++ b/src/pages/manage/Source/index.tsx @@ -1,17 +1,19 @@ -import FormattedDescription from '@/components/FormattedDescription'; +import { useIntl } from 'umi'; +import { useEffect, useState } from 'react'; +import { Button, List, message, Spin, Tag } from 'antd'; +import { GridContent, PageContainer } from '@ant-design/pro-layout'; import { getSourceStatus } from '@/services/api/meta-cms'; -import { deleteSourcePlatformToken } from '@/services/api/meta-ucenter'; import syncPostsRequest from '@/utils/sync-posts-request'; -import { GridContent, PageContainer } from '@ant-design/pro-layout'; -import { Button, List, message, Spin, Tag } from 'antd'; -import { useEffect, useState } from 'react'; -import { useIntl } from 'umi'; +import FormattedDescription from '@/components/FormattedDescription'; +import { deleteSourcePlatformToken } from '@/services/api/meta-ucenter'; import styles from './index.less'; -const status: GLOBAL.SourcePlatforms = { +/* The default status for every platform */ +const status: GLOBAL.SourcePlatformStatus = { matataki: { name: 'matataki', active: false, + username: '', }, }; @@ -20,9 +22,40 @@ export default () => { const [pageLoading, setPageLoading] = useState(true); const [syncLoading, setSyncLoading] = useState(false); const [unbindLoading, setUnbindLoading] = useState(false); - const [sourceStatus, setSourceStatus] = useState(status); + const [sourceStatus, setSourceStatus] = useState(status); + + const getStatus = (platform: GLOBAL.SourcePlatformStatusProperties) => + platform.active ? ( + + {intl.formatMessage({ id: 'component.status.alreadyBound' })} + + ) : ( + + {intl.formatMessage({ id: 'component.status.notBound' })} + + ); + + const loadSourceStatus = async () => { + const result = await getSourceStatus(); + setSourceStatus((source: GLOBAL.SourcePlatformStatus) => { + const newStatus = { ...source }; + result.data.forEach((service: CMS.SourceStatusResponse) => { + if (newStatus[service.platform]) { + newStatus[service.platform].active = service.active; + newStatus[service.platform].username = service.username; + } + }); + return newStatus; + }); + setPageLoading(false); + }; + + useEffect(() => { + loadSourceStatus(); + }, []); - const actions = { + /* Actions on page for every platform */ + const actionsOnPage = { matataki: { sync: ( , + , ], }; } @@ -62,7 +62,7 @@ export default () => { , ], actions: [ - , ], @@ -108,9 +108,11 @@ export default () => { rowKey={(record) => record.name} dataSource={stores} renderItem={(store) => { - if (store.actions.length && store.title.length) { + if (store.title.length) { return ( - + // + // TODO: no actions are supported now +