Skip to content

Commit 7c9d039

Browse files
authored
fix: format attachment size in toolbar upload (#4069)
1 parent a847328 commit 7c9d039

3 files changed

Lines changed: 81 additions & 28 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2021 Terminus, Inc.
2+
//
3+
// This program is free software: you can use, redistribute, and/or modify
4+
// it under the terms of the GNU Affero General Public License, version 3
5+
// or later ("AGPL"), as published by the Free Software Foundation.
6+
//
7+
// This program is distributed in the hope that it will be useful, but WITHOUT
8+
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9+
// FITNESS FOR A PARTICULAR PURPOSE.
10+
//
11+
// You should have received a copy of the GNU Affero General Public License
12+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
13+
14+
import { getFormatter } from 'charts/utils';
15+
16+
describe('charts/utils#getFormatter', () => {
17+
it('formats storage size to human readable text', () => {
18+
const formatter = getFormatter('STORAGE', 'B');
19+
20+
expect(formatter.format(8238634)).toBe('7.86 MB'); // roughly 7.86MB
21+
expect(formatter.format(512)).toBe('512 B');
22+
});
23+
});

shell/app/common/components/markdown-editor/__tests__/upload-plugin.test.tsx

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,34 @@ jest.mock('antd', () => {
2525
const React = require('react');
2626
// eslint-disable-next-line @typescript-eslint/no-shadow
2727
const antd = jest.requireActual('antd');
28-
const OldUpload = antd.Upload;
29-
const Upload: React.FC<UploadProps> = ({ children, onChange, ...rest }) => {
28+
const Upload: React.FC<UploadProps> = ({ children, onChange }) => {
3029
return (
31-
<OldUpload
32-
{...rest}
33-
onChange={(data: UploadChangeParam) => {
34-
const file = data.file;
35-
const response = {};
36-
onChange?.({
37-
...data,
38-
file: {
39-
status: 'success',
40-
response: file.name
41-
? {
42-
success: true,
43-
err: {},
44-
data: {
45-
...file,
46-
url: 'filePath',
47-
},
48-
}
49-
: undefined,
50-
},
51-
});
52-
}}
53-
>
30+
<label>
31+
<input
32+
type="file"
33+
onChange={(e) => {
34+
const file = e.target.files?.[0];
35+
if (!file) return;
36+
onChange?.({
37+
file: {
38+
...file,
39+
status: 'success',
40+
response: {
41+
success: true,
42+
err: {},
43+
data: {
44+
name: file.name,
45+
size: file.size,
46+
url: 'filePath',
47+
},
48+
},
49+
},
50+
} as UploadChangeParam);
51+
}}
52+
style={{ display: 'none' }}
53+
/>
5454
{children}
55-
</OldUpload>
55+
</label>
5656
);
5757
};
5858
return {
@@ -65,6 +65,15 @@ describe('UploadPlugin', () => {
6565
const images = new File(['this is an images'], 'logo.png', {
6666
type: 'image/png',
6767
});
68+
const kbFile = new File([new ArrayBuffer(1024)], 'small.bin', {
69+
type: 'application/octet-stream',
70+
});
71+
const mbFile = new File([new ArrayBuffer(2 * 1024 * 1024)], 'big.bin', {
72+
type: 'application/octet-stream',
73+
});
74+
const decimalFile = new File([new Uint8Array(1500)], 'decimal.bin', {
75+
type: 'application/octet-stream',
76+
});
6877
beforeAll(() => {
6978
jest.mock('agent');
7079
agent.post = () => ({
@@ -100,7 +109,25 @@ describe('UploadPlugin', () => {
100109
userEvent.upload(imageUpload, images);
101110
await flushPromises();
102111
});
103-
expect(insertTextFn).toHaveBeenLastCalledWith('\n![logo.png(17)](filePath)\n');
112+
expect(insertTextFn).toHaveBeenLastCalledWith('\n![logo.png(17 B)](filePath)\n');
113+
114+
await act(async () => {
115+
userEvent.upload(imageUpload, kbFile);
116+
await flushPromises();
117+
});
118+
expect(insertTextFn).toHaveBeenLastCalledWith('\n![small.bin(1 KB)](filePath)\n');
119+
120+
await act(async () => {
121+
userEvent.upload(imageUpload, mbFile);
122+
await flushPromises();
123+
});
124+
expect(insertTextFn).toHaveBeenLastCalledWith('\n![big.bin(2 MB)](filePath)\n');
125+
126+
await act(async () => {
127+
userEvent.upload(imageUpload, decimalFile);
128+
await flushPromises();
129+
});
130+
expect(insertTextFn).toHaveBeenLastCalledWith('\n![decimal.bin(1.46 KB)](filePath)\n');
104131
spyOnError.mockClear();
105132
});
106133
});

shell/app/common/components/markdown-editor/upload-plugin.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ import { Popover, message, Upload } from 'antd';
1616
import { Icon as CustomIcon } from 'common';
1717
import { getOrgFromPath } from 'common/utils';
1818
import { getCSRFToken } from 'core/config';
19+
import { getFormatter } from 'charts/utils';
1920
import i18n from 'i18n';
2021
import './upload-plugin.scss';
2122

2223
let isLoading = false;
2324
let hideLoading: any;
2425
const UploadPlugin = (props: any) => {
26+
const formatSize = (size?: number | string) => getFormatter('STORAGE', 'B').format(Number(size) || 0);
2527
// let hideLoading: any;
2628
const getUploadProps = (isImage?: boolean) => ({
2729
action: '/api/files',
@@ -55,7 +57,8 @@ const UploadPlugin = (props: any) => {
5557
message.error(err.msg);
5658
} else {
5759
const { name, size, url } = data;
58-
props.editor.insertText(`\n${isImage ? '!' : ''}[${name}${size})](${url})\n`);
60+
const formattedSize = formatSize(size);
61+
props.editor.insertText(`\n${isImage ? '!' : ''}[${name}${formattedSize})](${url})\n`);
5962
}
6063
},
6164
});

0 commit comments

Comments
 (0)