diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/post_body.jsx | 51 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 33 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_files.scss | 32 |
3 files changed, 98 insertions, 18 deletions
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 641ffeef2..29687b94e 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -114,23 +114,48 @@ module.exports = React.createClass({ } fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; + var thumbnail; if (type === "image") { - if (i < Constants.MAX_DISPLAY_FILES) { - postFiles.push( - <div className="post-image__column" key={filenames[i]}> - <a href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }><div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}></div></a> + thumbnail = ( + <a className="post-image__thumbnail" href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }> + <div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}/> + </a> + ); + } else { + thumbnail = ( + <a href={fileInfo.path + (fileInfo.ext ? "." + fileInfo.ext : "")} download={fileInfo.name + (fileInfo.ext ? "." + fileInfo.ext : "")}> + <div className={"file-icon "+utils.getIconClassName(type)}/> + </a> + ); + } + + var containerClassName = "post-image__column"; + if (type !== "image") { + containerClassName += " custom-file"; + } + + postFiles.push( + <div className={containerClassName} key={filenames[i]}> + {thumbnail} + <div className="post-image__details"> + <div className="post-image__name">{fileInfo.name}</div> + <div> + <span className="post-image__type">{fileInfo.ext.toUpperCase()}</span> + <span className="post-image__size" ref={filenames[i] + "__size"}></span> </div> - ); + </div> + </div> + ); + + // asynchronously request the size of the file so that we can display it next to the thumbnail + utils.getFileSize(fileInfo.path + "." + fileInfo.ext, function(self, filename) { + return function(size) { + self.refs[filename + "__size"].getDOMNode().innerHTML = " " + utils.fileSizeToString(size); } + }(this, filenames[i])); + + if (type === "image") { images.push(filenames[i]); - } else if (i < Constants.MAX_DISPLAY_FILES) { - postFiles.push( - <div className="post-image__column custom-file" key={fileInfo.name+i}> - <a href={fileInfo.path + (fileInfo.ext ? "." + fileInfo.ext : "")} download={fileInfo.name + (fileInfo.ext ? "." + fileInfo.ext : "")}> - <div className={"file-icon "+utils.getIconClassName(type)}/> - </a> - </div> - ); } } } diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 8a4d92b85..aa59201cb 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -557,6 +557,23 @@ module.exports.splitFileLocation = function(fileLocation) { return {'ext': ext, 'name': filename, 'path': filePath}; } +// Asynchronously gets the size of a file by requesting its headers. If successful, it calls the +// provided callback with the file size in bytes as the argument. +module.exports.getFileSize = function(url, callback) { + var request = new XMLHttpRequest(); + + request.open('HEAD', url, true); + request.onreadystatechange = function() { + if (request.readyState == 4 && request.status == 200) { + if (callback) { + callback(parseInt(request.getResponseHeader("content-length"))); + } + } + }; + + request.send(); +}; + module.exports.toTitleCase = function(str) { return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); } @@ -847,4 +864,20 @@ module.exports.getWindowLocationOrigin = function() { windowLocationOrigin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); } return windowLocationOrigin; +} + +// Converts a file size in bytes into a human-readable string of the form "123MB". +module.exports.fileSizeToString = function(bytes) { + // it's unlikely that we'll have files bigger than this + if (bytes > 1024 * 1024 * 1024 * 1024) { + return Math.floor(bytes / (1024 * 1024 * 1024 * 1024)) + "TB"; + } else if (bytes > 1024 * 1024 * 1024) { + return Math.floor(bytes / (1024 * 1024 * 1024)) + "GB"; + } else if (bytes > 1024 * 1024) { + return Math.floor(bytes / (1024 * 1024)) + "MB"; + } else if (bytes > 1024) { + return Math.floor(bytes / 1024) + "KB"; + } else { + return bytes + "B"; + } }; diff --git a/web/sass-files/sass/partials/_files.scss b/web/sass-files/sass/partials/_files.scss index 56d03e171..2a4b21d01 100644 --- a/web/sass-files/sass/partials/_files.scss +++ b/web/sass-files/sass/partials/_files.scss @@ -117,13 +117,14 @@ } .post-image__column { position: relative; - width: 120px; + width: 240px; height: 100px; float: left; margin: 5px 10px 5px 0; + display: flex; + border: 1px solid lightgrey; &.custom-file { - width: 85px; - height: 100px; + // TODO remove this class if it doesn't end up getting used any more } .post__load { height: 100%; @@ -133,13 +134,34 @@ background-position: center; } .post__image { - height: 100%; width: 100%; - border: 1px solid #E2E2E2; + height: 100%; background-color: #FFF; background-repeat: no-repeat; background-position: top left; } + .post-image__thumbnail { + width: 50%; + height: 100%; + } + .post-image__details { + width: 50%; + height: 100%; + background: white; + border-left: 1px solid lightgrey; + font-size: small; + padding: 5px 5px; + .post-image__name { + font-weight: 600; + } + .post-image__type { + color: grey; + } + .post-image__size { + border-left: 2px; + color: grey; + } + } a { text-decoration: none; color: grey; |