From 429d867d6d008836927ce8a99bc4c8045f78c399 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Tue, 20 Mar 2018 11:16:39 -0700 Subject: [PATCH] Download assets (#361) * Created download button component for assets * Added download component to asset manager * Added click handler for downloading assets * Installed mime package. Added extension property to object returned by dataurl.parse. Updated click handler in download component. * Added css to make asset-download float right like asset-copy * removed console log in dataurl * Updated styles for asset manager * Added title attributes to download and clipboard buttons for tooltip --- common/lib/dataurl.js | 2 ++ package.json | 3 +- .../components/asset_manager/asset_manager.js | 10 ++++++- .../asset_manager/asset_manager.less | 21 +++++++++++-- public/components/download/download.js | 30 +++++++++++++++++++ public/components/download/index.js | 3 ++ 6 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 public/components/download/download.js create mode 100644 public/components/download/index.js diff --git a/common/lib/dataurl.js b/common/lib/dataurl.js index 51303367cd3cc..ad168cfe2f6ed 100644 --- a/common/lib/dataurl.js +++ b/common/lib/dataurl.js @@ -1,4 +1,5 @@ import { fromByteArray } from 'base64-js'; +import mime from 'mime/lite'; export const imageTypes = ['image/svg+xml', 'image/jpeg', 'image/png', 'image/gif']; @@ -14,6 +15,7 @@ export function parse(str, withData = false) { charset: matches[2] && matches[2].split('=')[1], data: !withData ? null : str.split(',')[1], isImage: imageTypes.indexOf(matches[1]) >= 0, + extension: mime.getExtension(matches[1]), }; } diff --git a/package.json b/package.json index f052bbf47115a..d43c847377f4c 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "lz-string": "^1.4.4", "markdown-it": "^8.3.2", "metalsmith-snippet": "^2.0.0", + "mime": "^2.2.0", "moment": "^2.18.1", "object-path-immutable": "^0.5.1", "prop-types": "^15.5.8", @@ -134,4 +135,4 @@ "sinon": "^2.3.2", "through2": "^2.0.3" } -} \ No newline at end of file +} diff --git a/public/components/asset_manager/asset_manager.js b/public/components/asset_manager/asset_manager.js index af63cb89dc107..4902f9cde72a3 100644 --- a/public/components/asset_manager/asset_manager.js +++ b/public/components/asset_manager/asset_manager.js @@ -4,6 +4,7 @@ import { Button } from 'react-bootstrap'; import './asset_manager.less'; import { RemoveIcon } from '../remove_icon'; import { Clipboard } from '../clipboard'; +import { Download } from '../download'; export const AssetManager = ({ assets, removeAsset }) => { return ( @@ -37,13 +38,20 @@ export const AssetManager = ({ assets, removeAsset }) => { onClick={() => removeAsset(asset.id)} />
-
+
+
+ + + +
{asset.id}
diff --git a/public/components/asset_manager/asset_manager.less b/public/components/asset_manager/asset_manager.less index 3fa8a94c6de63..e2cc20a37d53a 100644 --- a/public/components/asset_manager/asset_manager.less +++ b/public/components/asset_manager/asset_manager.less @@ -1,4 +1,4 @@ -@import (reference) "../../style/main"; +@import (reference) '../../style/main'; .canvas__asset-manager { .canvas__asset-manager--thumb { @@ -14,7 +14,6 @@ background-size: cover; background-position: left; background-repeat: no-repeat; - } .canvas__asset-manager--asset-identifier { @@ -23,9 +22,25 @@ background-color: fade(@darkestGrey, 80%); border-radius: 0 0 @borderRadius @borderRadius; padding: @spacingXS; + white-space: nowrap; + overflow: hidden; + width: 100%; - .asset-copy { + .asset-copy, + .asset-download { float: right; + margin-right: @spacingXS; + + &:first-child { + margin-right: 0px; + } + } + + .asset-id { + font-size: @textXSmall; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } } } diff --git a/public/components/download/download.js b/public/components/download/download.js new file mode 100644 index 0000000000000..fac6fe1c08c52 --- /dev/null +++ b/public/components/download/download.js @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import fileSaver from 'file-saver'; +import { toByteArray } from 'base64-js'; +import { parse } from '../../../common/lib/dataurl'; + +export class Download extends React.PureComponent { + static propTypes = { + children: PropTypes.element.isRequired, + fileName: PropTypes.string, + content: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + onCopy: PropTypes.func, + }; + + onClick = () => { + const { fileName, content } = this.props; + const asset = parse(content, true); + const assetBlob = new Blob([toByteArray(asset.data)], { type: asset.mimetype }); + const ext = asset.extension ? `.${asset.extension}` : ''; + fileSaver.saveAs(assetBlob, `canvas-${fileName}${ext}`); + }; + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} diff --git a/public/components/download/index.js b/public/components/download/index.js new file mode 100644 index 0000000000000..8659c2a3adfa0 --- /dev/null +++ b/public/components/download/index.js @@ -0,0 +1,3 @@ +import { Download as Component } from './download'; + +export const Download = Component;