Skip to content

Commit 77a7718

Browse files
lilixxsDiamondYuan
authored andcommitted
feat: memos support enhance
1. 可在剪藏时添加 tag。 new memo tags support 2. 多语言支持,目前支持简体中文和英文。i18n language support: zh-cn and en-us 3. 可在剪藏时设定可见性:公开笔记/私有笔记。new memo visibility support
1 parent dc08386 commit 77a7718

File tree

7 files changed

+162
-40
lines changed

7 files changed

+162
-40
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ coverage/
77
tmp/
88
.DS_Store
99
.idea
10+
.vscode
1011
yarn-error.log
1112
dll/
1213
webclipper.zip

src/common/backend/services/memos/form.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import '@ant-design/compatible/assets/index.less';
33
import { Input } from 'antd';
44
import { FormComponentProps } from '@ant-design/compatible/es/form';
55
import React, { Fragment } from 'react';
6-
import { BaklibBackendServiceConfig } from './interface';
6+
import { MemosBackendServiceConfig } from './interface';
77
import useOriginForm from '@/hooks/useOriginForm';
88
import { FormattedMessage } from 'react-intl';
99

10-
interface BaklibFormProps {
10+
interface MemosFormProps {
1111
verified?: boolean;
12-
info?: BaklibBackendServiceConfig;
12+
info?: MemosBackendServiceConfig;
1313
}
1414

15-
const FormItem: React.FC<BaklibFormProps & FormComponentProps> = props => {
15+
const FormItem: React.FC<MemosFormProps & FormComponentProps> = props => {
1616
const {
1717
form,
1818
form: { getFieldDecorator },
@@ -25,7 +25,7 @@ const FormItem: React.FC<BaklibFormProps & FormComponentProps> = props => {
2525
initStatus: !!info,
2626
});
2727

28-
let initData: Partial<BaklibBackendServiceConfig> = {};
28+
let initData: Partial<MemosBackendServiceConfig> = {};
2929
if (info) {
3030
initData = info;
3131
}
@@ -34,20 +34,26 @@ const FormItem: React.FC<BaklibFormProps & FormComponentProps> = props => {
3434
<Fragment>
3535
<Form.Item label="Host">
3636
{getFieldDecorator('origin', {
37-
initialValue: initData.origin || 'https://www.baklib.com',
37+
initialValue: initData.origin || 'https://demo.usememos.com',
3838
rules: [
3939
{
4040
required: true,
41-
message: 'Host is required!',
41+
message: (
42+
<FormattedMessage
43+
id="backend.services.memos.form.authentication"
44+
defaultMessage="Host URL requeired!"
45+
/>
46+
),
47+
type: 'url',
4248
},
4349
...formRules,
4450
],
4551
})(
4652
<Input.Search
4753
enterButton={
4854
<FormattedMessage
49-
id="backend.services.baklib.form.authentication"
50-
defaultMessage="Authentication"
55+
id="backend.services.memos.form.hostTest"
56+
defaultMessage="test"
5157
/>
5258
}
5359
disabled={editMode || formVerified}
@@ -61,10 +67,16 @@ const FormItem: React.FC<BaklibFormProps & FormComponentProps> = props => {
6167
rules: [
6268
{
6369
required: true,
64-
message: 'AccessToken is required!',
70+
message: (
71+
<FormattedMessage
72+
id="backend.services.memos.accessToken.message"
73+
defaultMessage='AccessToken is required!'
74+
/>),
6575
},
6676
],
67-
})(<Input disabled={editMode || verified || !formVerified} />)}
77+
})(<Input
78+
disabled={editMode || verified || !formVerified}
79+
/>)}
6880
</Form.Item>
6981
</Fragment>
7082
);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Input, Tooltip, Select } from 'antd';
2+
import { Form } from '@ant-design/compatible';
3+
import '@ant-design/compatible/assets/index.less';
4+
import { FormComponentProps } from '@ant-design/compatible/lib/form';
5+
import React, { Fragment } from 'react';
6+
import locales from '@/common/locales';
7+
import { VisibilityType } from './interface';
8+
9+
const { Option } = Select;
10+
11+
const HeaderForm: React.FC<FormComponentProps> = ({ form: { getFieldDecorator } }) => {
12+
13+
return (
14+
<Fragment>
15+
<Form.Item>
16+
<Tooltip
17+
trigger={['focus']}
18+
title={locales.format({
19+
id: 'backend.services.memos.headerForm.tag',
20+
defaultMessage: 'Input tags (eg. tag1, tag2...)'
21+
})}
22+
placement="topLeft"
23+
overlayClassName="numeric-input"
24+
>
25+
{getFieldDecorator('tags', {
26+
rules: [
27+
{
28+
pattern: /^(?! )[^\u4e00-\u9fa5~`!@#$%^&*()_+={}\[\]:;"'<>.?\/\\|]*[^\s.,;:!?"'()]*$/,
29+
message: locales.format({
30+
id: 'backend.services.memos.headerForm.tag_error',
31+
}),
32+
},
33+
],
34+
})(
35+
<Input
36+
autoComplete="off"
37+
placeholder={locales.format({
38+
id: 'backend.services.memos.headerForm.tag',
39+
defaultMessage: 'Input tags (eg. tag1, tag2...)'
40+
})}
41+
/>
42+
)}
43+
</Tooltip>
44+
</Form.Item>
45+
46+
<Form.Item label={locales.format({
47+
id: 'backend.services.memos.headerForm.visibility',
48+
defaultMessage: 'visibility'
49+
})}>
50+
{getFieldDecorator('visibility', {
51+
initialValue: VisibilityType[0].value,
52+
})(
53+
<Select style={{ width: '100%' }}>
54+
{VisibilityType.map(option => (
55+
<Option key={option.value} value={option.value}>
56+
{option.label()}
57+
</Option>
58+
))}
59+
</Select>
60+
)}
61+
</Form.Item>
62+
</Fragment>
63+
);
64+
};
65+
66+
export default HeaderForm;

src/common/backend/services/memos/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ import { ServiceMeta } from '../interface';
22
import Service from './service';
33
import Form from './form';
44
import localeService from '@/common/locales';
5+
import headerForm from './headerForm';
56

67
export default (): ServiceMeta => {
78
return {
89
name: localeService.format({
910
id: 'backend.services.memos.name',
1011
}),
11-
icon: 'memos',
12+
icon: '',
1213
type: 'memos',
1314
service: Service,
15+
headerForm: headerForm,
1416
form: Form,
1517
homePage: 'https://www.usememos.com/',
1618
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
1+
import { CreateDocumentRequest } from './../interface';
2+
import locales from '@/common/locales';
3+
4+
export const VisibilityType = [
5+
{ label: () => locales.format({ id: 'backend.services.memos.headerForm.VisibilityType.private', defaultMessage: 'private' }), value: 'PRIVATE' },
6+
{ label: () => locales.format({ id: 'backend.services.memos.headerForm.VisibilityType.public', defaultMessage: 'public' }), value: 'PUBLIC' },
7+
] as const;
8+
9+
export type VisibilityType = typeof VisibilityType[number];
10+
111
export interface MemosBackendServiceConfig {
212
accessToken: string;
313
origin: string;
414
}
15+
16+
export interface MemosUserResponse {
17+
name: string;
18+
username: string;
19+
email: string;
20+
avatarUrl: string;
21+
description: string;
22+
}
23+
24+
export interface MemosUserInfo {
25+
name: string;
26+
avatar: string;
27+
homePage: string;
28+
description: string;
29+
}
30+
31+
export interface MemoCreateDocumentRequest extends CreateDocumentRequest {
32+
visibility?: VisibilityType;
33+
tags?: string;
34+
}

src/common/backend/services/memos/service.ts

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
1-
import { DocumentService, CreateDocumentRequest } from '../../index';
1+
import { DocumentService } from '../../index';
22
import { extend, RequestMethod } from 'umi-request';
3-
import md5 from '@web-clipper/shared/lib/md5';
4-
import { MemosBackendServiceConfig } from './interface';
53
import { CompleteStatus } from '../interface';
64
import { Repository } from '@/common/backend/services/interface';
5+
import {
6+
MemosBackendServiceConfig,
7+
MemoCreateDocumentRequest,
8+
MemosUserResponse,
9+
MemosUserInfo
10+
} from './interface';
711

8-
interface MemosUserResponse {
9-
name: string;
10-
username: string;
11-
email: string;
12-
avatarUrl: string;
13-
description: string;
14-
}
15-
16-
interface UserInfo {
17-
name: string;
18-
avatar: string;
19-
homePage: string;
20-
description: string;
21-
}
2212

2313
export default class MemosDocumentService implements DocumentService {
2414
private request: RequestMethod;
2515
private token: string;
2616
private origin: string;
27-
private userInfo: UserInfo | null;
17+
private UserInfo: MemosUserInfo | null;
2818

2919
constructor({ accessToken, origin }: MemosBackendServiceConfig) {
3020
const realHost = origin || 'https://demo.usememos.com';
@@ -54,17 +44,17 @@ export default class MemosDocumentService implements DocumentService {
5444
);
5545
this.token = accessToken;
5646
this.origin = realHost;
57-
this.userInfo = null;
47+
this.UserInfo = null;
5848
}
5949

6050
getId = () => {
6151
return '0';
6252
};
6353

64-
getUserInfo = async (): Promise<UserInfo> => {
54+
getUserInfo = async (): Promise<MemosUserInfo> => {
6555
const response = await this.request.post<MemosUserResponse>('v1/auth/status');
6656

67-
const userInfo: UserInfo = {
57+
const MemosUserInfo: MemosUserInfo = {
6858
name: response.username || 'Memos User',
6959
avatar: response.avatarUrl
7060
? `${this.origin}${response.avatarUrl}`
@@ -73,16 +63,25 @@ export default class MemosDocumentService implements DocumentService {
7363
description: response.description || 'Memos User',
7464
};
7565

76-
this.userInfo = userInfo;
77-
return userInfo;
66+
this.UserInfo = MemosUserInfo;
67+
return MemosUserInfo;
7868
};
7969

70+
private addTag = (tags: string, content: string): string => {
71+
const tagArray = tags.split(',').map(tag => tag.trim()).filter(tag => tag);
72+
const formattedTags = tagArray.map(tag => `#${tag}`).join(' ');
73+
return `${content}\n${formattedTags}`;
74+
};
8075

8176
createDocument = async (
82-
info: CreateDocumentRequest
77+
info: MemoCreateDocumentRequest
8378
): Promise<CompleteStatus> => {
84-
if (!this.userInfo) {
85-
this.userInfo = await this.getUserInfo();
79+
if (!this.UserInfo) {
80+
this.UserInfo = await this.getUserInfo();
81+
}
82+
83+
if (info.tags) {
84+
info.content = this.addTag(info.tags, info.content);
8685
}
8786

8887
const response = await this.request.post<{
@@ -92,12 +91,12 @@ export default class MemosDocumentService implements DocumentService {
9291
}>('v1/memos', {
9392
data: {
9493
content: info.content,
95-
visibility: 'PRIVATE',
94+
visibility: info.visibility || 'PRIVATE',
9695
},
9796
});
9897

9998
return {
100-
href: `${this.origin}/u/${this.userInfo.name}`,
99+
href: `${this.origin}/u/${this.UserInfo.name}`,
101100
};
102101
};
103102

src/common/locales/data/zh-CN.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525
"backend.imageHosting.wiznote.name": "为知笔记",
2626
"backend.imageHosting.wiznote.builtInRemark": "为知笔记内置图床",
2727
"backend.not.unavailable": "暂时无法剪辑此类型的页面。\n\n刷新页面可以解决。",
28+
29+
"backend.services.memos.name": "Memos",
30+
"backend.services.memos.form.hostTest": "检验",
31+
"backend.services.memos.accessToken.message": "请输入 AccessToken",
32+
"backend.services.memos.form.authentication": "请输入服务器地址",
33+
"backend.services.memos.headerForm.tag": "请输入标签名称,多个标签用英文逗号分隔,如 tag1,tag2...",
34+
"backend.services.memos.headerForm.visibility": "文档类型",
35+
"backend.services.memos.headerForm.VisibilityType.private": "私人",
36+
"backend.services.memos.headerForm.VisibilityType.public": "公开",
37+
"backend.services.memos.headerForm.tag_error": "标签格式错误,请检查",
38+
39+
"backend.services.baklib.form.hostTest": "测试",
2840
"backend.services.baklib.form.authentication": "授权",
2941
"backend.services.baklib.headerForm.channel": "栏目",
3042
"backend.services.baklib.headerForm.description": "描述",

0 commit comments

Comments
 (0)