feat: show file size in file popover (#47)
* feat: show file size in file popover * chore: update file popover content's props
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@edx/frontend-app-ora-enhanced-staff-grader",
|
||||
"name": "@edx/frontend-app-ora-grading",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
@@ -9930,10 +9930,9 @@
|
||||
}
|
||||
},
|
||||
"filesize": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
|
||||
"integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==",
|
||||
"dev": true
|
||||
"version": "8.0.6",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.6.tgz",
|
||||
"integrity": "sha512-sHvRqTiwdmcuzqet7iVwsbwF6UrV3wIgDf2SHNdY1Hgl8PC45HZg/0xtdw6U2izIV4lccnrY9ftl6wZFNdjYMg=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "4.0.0",
|
||||
@@ -20972,6 +20971,12 @@
|
||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||
"dev": true
|
||||
},
|
||||
"filesize": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
|
||||
"integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==",
|
||||
"dev": true
|
||||
},
|
||||
"globby": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-to-json": "^3.6.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"filesize": "^8.0.6",
|
||||
"font-awesome": "4.7.0",
|
||||
"history": "5.0.1",
|
||||
"html-react-parser": "^1.3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`FilePopoverContent component snapshot 1`] = `
|
||||
exports[`FilePopoverContent component snapshot default 1`] = `
|
||||
<Fragment>
|
||||
<div
|
||||
className="help-popover-option"
|
||||
@@ -28,5 +28,62 @@ exports[`FilePopoverContent component snapshot 1`] = `
|
||||
<br />
|
||||
long descriptive text...
|
||||
</div>
|
||||
<div
|
||||
className="help-popover-option"
|
||||
>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
defaultMessage="File Size"
|
||||
description="Popover title for file size"
|
||||
id="ora-grading.FilePopoverCellContent.fileSizeTitle"
|
||||
/>
|
||||
</strong>
|
||||
<br />
|
||||
filesize(6000)
|
||||
</div>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`FilePopoverContent component snapshot invalid size 1`] = `
|
||||
<Fragment>
|
||||
<div
|
||||
className="help-popover-option"
|
||||
>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
defaultMessage="File Name"
|
||||
description="Popover title for file name"
|
||||
id="ora-grading.FilePopoverContent.filePopoverNameTitle"
|
||||
/>
|
||||
</strong>
|
||||
<br />
|
||||
some file name
|
||||
</div>
|
||||
<div
|
||||
className="help-popover-option"
|
||||
>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
defaultMessage="File Description"
|
||||
description="Popover title for file description"
|
||||
id="ora-grading.FilePopoverCellContent.filePopoverDescriptionTitle"
|
||||
/>
|
||||
</strong>
|
||||
<br />
|
||||
long descriptive text...
|
||||
</div>
|
||||
<div
|
||||
className="help-popover-option"
|
||||
>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
defaultMessage="File Size"
|
||||
description="Popover title for file size"
|
||||
id="ora-grading.FilePopoverCellContent.fileSizeTitle"
|
||||
/>
|
||||
</strong>
|
||||
<br />
|
||||
Unknown
|
||||
</div>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
@@ -2,33 +2,39 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import filesize from 'filesize';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
export const FilePopoverContent = ({ file }) => (
|
||||
export const FilePopoverContent = ({ name, description, size }) => (
|
||||
<>
|
||||
<div className="help-popover-option">
|
||||
<strong><FormattedMessage {...messages.filePopoverNameTitle} /></strong>
|
||||
<br />
|
||||
{file.name}
|
||||
{name}
|
||||
</div>
|
||||
<div className="help-popover-option">
|
||||
<strong><FormattedMessage {...messages.filePopoverDescriptionTitle} /></strong>
|
||||
<br />
|
||||
{file.description}
|
||||
{description}
|
||||
</div>
|
||||
<div className="help-popover-option">
|
||||
<strong><FormattedMessage {...messages.fileSizeTitle} /></strong>
|
||||
<br />
|
||||
{typeof (size) === 'number' ? filesize(size) : 'Unknown'}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
FilePopoverContent.defaultProps = {
|
||||
description: '',
|
||||
size: null,
|
||||
};
|
||||
|
||||
FilePopoverContent.propTypes = {
|
||||
file: PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
downloadURL: PropTypes.string,
|
||||
}).isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
};
|
||||
|
||||
export default FilePopoverContent;
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import filesize from 'filesize';
|
||||
import FilePopoverContent from '.';
|
||||
|
||||
jest.mock('filesize', () => (size) => `filesize(${size})`);
|
||||
|
||||
describe('FilePopoverContent', () => {
|
||||
describe('component', () => {
|
||||
const props = {
|
||||
file: {
|
||||
name: 'some file name',
|
||||
description: 'long descriptive text...',
|
||||
downloadURL: 'this-url-is.working',
|
||||
},
|
||||
name: 'some file name',
|
||||
description: 'long descriptive text...',
|
||||
downloadURL: 'this-url-is.working',
|
||||
size: 6000,
|
||||
};
|
||||
let el;
|
||||
beforeEach(() => {
|
||||
el = shallow(<FilePopoverContent {...props} />);
|
||||
});
|
||||
test('snapshot', () => {
|
||||
expect(el).toMatchSnapshot();
|
||||
describe('snapshot', () => {
|
||||
test('default', () => expect(el).toMatchSnapshot());
|
||||
test('invalid size', () => {
|
||||
el.setProps({
|
||||
size: null,
|
||||
});
|
||||
expect(el).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('behavior', () => {
|
||||
test('content', () => {
|
||||
expect(el.text()).toContain(props.file.name);
|
||||
expect(el.text()).toContain(props.file.description);
|
||||
expect(el.text()).toContain(props.name);
|
||||
expect(el.text()).toContain(props.description);
|
||||
expect(el.text()).toContain(filesize(props.size));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'File Description',
|
||||
description: 'Popover title for file description',
|
||||
},
|
||||
fileSizeTitle: {
|
||||
id: 'ora-grading.FilePopoverCellContent.fileSizeTitle',
|
||||
defaultMessage: 'File Size',
|
||||
description: 'Popover title for file size',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const FileCard = ({ file, children }) => (
|
||||
<Card className="file-card" key={file.name}>
|
||||
<Collapsible className="file-collapsible" defaultOpen title={<h3>{file.name}</h3>}>
|
||||
<div className="preview-panel">
|
||||
<FileInfo><FilePopoverContent file={file} /></FileInfo>
|
||||
<FileInfo><FilePopoverContent {...file} /></FileInfo>
|
||||
{children}
|
||||
</div>
|
||||
</Collapsible>
|
||||
|
||||
@@ -19,13 +19,9 @@ exports[`File Preview Card component snapshot 1`] = `
|
||||
>
|
||||
<FileInfo>
|
||||
<FilePopoverContent
|
||||
file={
|
||||
Object {
|
||||
"description": "test-file description",
|
||||
"downloadUrl": "destination/test-file-name.pdf",
|
||||
"name": "test-file-name.pdf",
|
||||
}
|
||||
}
|
||||
description="test-file description"
|
||||
downloadUrl="destination/test-file-name.pdf"
|
||||
name="test-file-name.pdf"
|
||||
/>
|
||||
</FileInfo>
|
||||
<h1>
|
||||
|
||||
@@ -6,7 +6,7 @@ import FilePopoverContent from 'components/FilePopoverContent';
|
||||
|
||||
export const FilePopoverCell = ({ row: { original } }) => (
|
||||
<InfoPopover>
|
||||
<FilePopoverContent file={original} />
|
||||
<FilePopoverContent {...original} />
|
||||
</InfoPopover>
|
||||
);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('FilePopoverCell', () => {
|
||||
test('content', () => {
|
||||
const { original } = props.row;
|
||||
const content = el.find(FilePopoverContent);
|
||||
expect(content.props()).toEqual({ file: original });
|
||||
expect(content.props()).toEqual({ ...original });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,13 +3,9 @@
|
||||
exports[`FilePopoverCell component snapshot 1`] = `
|
||||
<InfoPopover>
|
||||
<FilePopoverContent
|
||||
file={
|
||||
Object {
|
||||
"description": "long descriptive text...",
|
||||
"downloadURL": "this-url-is.working",
|
||||
"name": "some file name",
|
||||
}
|
||||
}
|
||||
description="long descriptive text..."
|
||||
downloadURL="this-url-is.working"
|
||||
name="some file name"
|
||||
/>
|
||||
</InfoPopover>
|
||||
`;
|
||||
|
||||
@@ -51,6 +51,7 @@ const initialState = {
|
||||
* downloadURL: '',
|
||||
* description: '',
|
||||
* name: '',
|
||||
* size: 0,
|
||||
* }],
|
||||
* },
|
||||
*/
|
||||
|
||||
@@ -9,11 +9,11 @@ import * as module from './download';
|
||||
|
||||
/**
|
||||
* Generate a manifest file content based on files object
|
||||
* @param {obj[]} files - list of file entries with downloadUrl, name, and description
|
||||
* @param {obj[]} files - list of file entries with downloadUrl, name, description, and size
|
||||
* @return {string} - manifest text file content.
|
||||
*/
|
||||
export const genManifest = (files) => files.map(
|
||||
(file) => `Filename: ${file.name}\nDescription: ${file.description}`,
|
||||
(file) => `Filename: ${file.name}\nDescription: ${file.description}\nSize: ${file.size}`,
|
||||
).join('\n\n');
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ describe('download thunkActions', () => {
|
||||
downloadUrl: `home/${name}`,
|
||||
name,
|
||||
description: `${name} description`,
|
||||
size: name.length,
|
||||
});
|
||||
const files = [mockFile('test-file1.jpg'), mockFile('test-file2.pdf')];
|
||||
const blobs = ['blob1', 'blob2'];
|
||||
@@ -44,8 +45,8 @@ describe('download thunkActions', () => {
|
||||
describe('genManifest', () => {
|
||||
test('returns a list of strings with filename and description for each file', () => {
|
||||
expect(download.genManifest(response.files)).toEqual([
|
||||
`Filename: ${files[0].name}\nDescription: ${files[0].description}`,
|
||||
`Filename: ${files[1].name}\nDescription: ${files[1].description}`,
|
||||
`Filename: ${files[0].name}\nDescription: ${files[0].description}\nSize: ${files[0].size}`,
|
||||
`Filename: ${files[1].name}\nDescription: ${files[1].description}\nSize: ${files[0].size}`,
|
||||
].join('\n\n'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,10 +24,12 @@ const getFiles = (submissionUUID) => {
|
||||
const files = [];
|
||||
for (let i = 0; i < numFiles; i++) {
|
||||
const fileName = `${submissionUUID}_${allFiles[i]}`;
|
||||
const descriptionText = descriptiveText(fileName);
|
||||
files.push({
|
||||
name: allFiles[i],
|
||||
description: descriptiveText(fileName),
|
||||
description: descriptionText,
|
||||
downloadUrl: allFiles[i],
|
||||
size: descriptionText.length * 1024,
|
||||
});
|
||||
}
|
||||
return files;
|
||||
|
||||
Reference in New Issue
Block a user