From eddb79d97d72a63fc3af6741567077e3e59b2871 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Wed, 22 Jul 2015 17:18:33 -0400 Subject: Add an info box next to image thumbnails which provides the name, type, and size of a file. --- web/react/components/post_body.jsx | 51 ++++++++++++++++++++++++++++---------- web/react/utils/utils.jsx | 33 ++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 13 deletions(-) (limited to 'web/react') 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( -
-
+ thumbnail = ( + +
+ + ); + } else { + thumbnail = ( + +
+ + ); + } + + var containerClassName = "post-image__column"; + if (type !== "image") { + containerClassName += " custom-file"; + } + + postFiles.push( +
+ {thumbnail} +
+
{fileInfo.name}
+
+ {fileInfo.ext.toUpperCase()} +
- ); +
+
+ ); + + // 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( -
- -
- -
- ); } } } 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"; + } }; -- cgit v1.2.3-1-g7c22 From 5488b5e2164518d9b2a745a9906152a4e6c0be10 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 23 Jul 2015 16:45:16 -0400 Subject: Reconcile the code to display attachment previews into a FileAttachmentList class to clean up duplicated code. --- web/react/components/file_attachment.jsx | 109 +++++++++++++++++++++ web/react/components/file_attachment_list.jsx | 47 +++++++++ web/react/components/post_body.jsx | 123 ++---------------------- web/react/components/post_right.jsx | 131 +++----------------------- 4 files changed, 176 insertions(+), 234 deletions(-) create mode 100644 web/react/components/file_attachment.jsx create mode 100644 web/react/components/file_attachment_list.jsx (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx new file mode 100644 index 000000000..4a81dd8f3 --- /dev/null +++ b/web/react/components/file_attachment.jsx @@ -0,0 +1,109 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +var utils = require('../utils/utils.jsx'); + +module.exports = React.createClass({ + displayName: "FileAttachment", + propTypes: { + filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, + index: React.PropTypes.number.isRequired, + imageModalId: React.PropTypes.string.isRequired, + handleImageClick: React.PropTypes.func + }, + componentDidMount: function() { + var filename = this.props.filenames[this.props.index]; + + var self = this; + + if (filename) { + var fileInfo = utils.splitFileLocation(filename); + if (Object.keys(fileInfo).length === 0) return; + + var type = utils.getFileType(fileInfo.ext); + + // This is a temporary patch to fix issue with old files using absolute paths + if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { + fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; + } + fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; + + if (type === "image") { + $('').attr('src', fileInfo.path+'_thumb.jpg').load(function(path, name){ return function() { + $(this).remove(); + if (name in self.refs) { + var imgDiv = self.refs[name].getDOMNode(); + + $(imgDiv).removeClass('post__load'); + $(imgDiv).addClass('post__image'); + + var re1 = new RegExp(' ', 'g'); + var re2 = new RegExp('\\(', 'g'); + var re3 = new RegExp('\\)', 'g'); + var url = path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); + $(imgDiv).css('background-image', 'url('+url+'_thumb.jpg)'); + } + }}(fileInfo.path, filename)); + } + } + }, + render: function() { + var filenames = this.props.filenames; + var filename = filenames[this.props.index]; + + var fileInfo = utils.splitFileLocation(filename); + if (Object.keys(fileInfo).length === 0) return null; + + var type = utils.getFileType(fileInfo.ext); + + // This is a temporary patch to fix issue with old files using absolute paths + if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { + fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; + } + fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; + + var thumbnail; + if (type === "image") { + thumbnail = ( + +
+ + ); + } else { + thumbnail = ( + +
+ + ); + } + + var containerClassName = "post-image__column"; + if (type !== "image") { + containerClassName += " custom-file"; + } + + // TODO fix the race condition here where the file size may arrive before the rest of the page is rendered + // 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) { + if ((_filename + "__size") in self.refs) { + self.refs[_filename + "__size"].getDOMNode().innerHTML = " " + utils.fileSizeToString(size); + } + } + }(this, filename)); + + return ( +
+ {thumbnail} +
+
{fileInfo.name}
+
+ {fileInfo.ext.toUpperCase()} + +
+
+
+ ); + } +}); diff --git a/web/react/components/file_attachment_list.jsx b/web/react/components/file_attachment_list.jsx new file mode 100644 index 000000000..0b52d6a70 --- /dev/null +++ b/web/react/components/file_attachment_list.jsx @@ -0,0 +1,47 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +var ViewImageModal = require('./view_image.jsx'); +var FileAttachment = require('./file_attachment.jsx'); +var Constants = require('../utils/constants.jsx'); + +module.exports = React.createClass({ + displayName: "FileAttachmentList", + propTypes: { + filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, + postId: React.PropTypes.string.isRequired, + channelId: React.PropTypes.string, + userId: React.PropTypes.string + }, + getInitialState: function() { + return {startImgId: 0}; + }, + render: function() { + var filenames = this.props.filenames; + + var postImageModalId = "view_image_modal_" + this.props.postId; + + var postFiles = []; + for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { + postFiles.push(); + } + + return ( +
+
+ {postFiles} +
+ +
+ ); + }, + handleImageClick: function(e) { + this.setState({startImgId: parseInt($(e.target.parentNode).attr('data-img-id'))}); + } +}); diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 29687b94e..d29784db9 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -1,63 +1,23 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. -var CreateComment = require( './create_comment.jsx' ); +var FileAttachmentList = require('./file_attachment_list.jsx'); var UserStore = require('../stores/user_store.jsx'); var utils = require('../utils/utils.jsx'); -var ViewImageModal = require('./view_image.jsx'); -var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ - handleImageClick: function(e) { - this.setState({startImgId: parseInt($(e.target.parentNode).attr('data-img-id'))}); - }, componentWillReceiveProps: function(nextProps) { var linkData = utils.extractLinks(nextProps.post.message); this.setState({ links: linkData["links"], message: linkData["text"] }); }, - componentDidMount: function() { - var filenames = this.props.post.filenames; - var self = this; - if (filenames) { - var re1 = new RegExp(' ', 'g'); - var re2 = new RegExp('\\(', 'g'); - var re3 = new RegExp('\\)', 'g'); - for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { - var fileInfo = utils.splitFileLocation(filenames[i]); - if (Object.keys(fileInfo).length === 0) continue; - - var type = utils.getFileType(fileInfo.ext); - - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - - if (type === "image") { - $('').attr('src', fileInfo.path+'_thumb.jpg').load(function(path, name){ return function() { - $(this).remove(); - if (name in self.refs) { - var imgDiv = self.refs[name].getDOMNode(); - $(imgDiv).removeClass('post__load'); - $(imgDiv).addClass('post__image'); - var url = path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); - $(imgDiv).css('background-image', 'url('+url+'_thumb.jpg)'); - } - }}(fileInfo.path, filenames[i])); - } - } - } - }, getInitialState: function() { var linkData = utils.extractLinks(this.props.post.message); - return { startImgId: 0, links: linkData["links"], message: linkData["text"] }; + return { links: linkData["links"], message: linkData["text"] }; }, render: function() { var post = this.props.post; var filenames = this.props.post.filenames; var parentPost = this.props.parentPost; - var postImageModalId = "view_image_modal_" + post.id; var inner = utils.textToJsx(this.state.message); var comment = ""; @@ -99,69 +59,8 @@ module.exports = React.createClass({ postClass += " post-comment"; } - var postFiles = []; - var images = []; - if (filenames) { - for (var i = 0; i < filenames.length; i++) { - var fileInfo = utils.splitFileLocation(filenames[i]); - if (Object.keys(fileInfo).length === 0) continue; - - var type = utils.getFileType(fileInfo.ext); - - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - - var thumbnail; - if (type === "image") { - thumbnail = ( - -
- - ); - } else { - thumbnail = ( - -
- - ); - } - - var containerClassName = "post-image__column"; - if (type !== "image") { - containerClassName += " custom-file"; - } - - postFiles.push( -
- {thumbnail} -
-
{fileInfo.name}
-
- {fileInfo.ext.toUpperCase()} - -
-
-
- ); - - // 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]); - } - } - } - var embed; - if (postFiles.length === 0 && this.state.links) { + if (filenames.length === 0 && this.state.links) { embed = utils.getEmbed(this.state.links[0]); } @@ -170,21 +69,13 @@ module.exports = React.createClass({ { comment }

{inner}

{ filenames && filenames.length > 0 ? -
- { postFiles } -
- : "" } - { embed } - - { images.length > 0 ? - + filenames={filenames} /> : "" } + { embed }
); } diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 8097a181e..861f03673 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -10,7 +10,7 @@ var utils = require('../utils/utils.jsx'); var SearchBox =require('./search_bar.jsx'); var CreateComment = require( './create_comment.jsx' ); var Constants = require('../utils/constants.jsx'); -var ViewImageModal = require('./view_image.jsx'); +var FileAttachmentList = require('./file_attachment_list.jsx'); var ActionTypes = Constants.ActionTypes; RhsHeaderPost = React.createClass({ @@ -55,17 +55,8 @@ RhsHeaderPost = React.createClass({ }); RootPost = React.createClass({ - handleImageClick: function(e) { - this.setState({startImgId: parseInt($(e.target.parentNode).attr('data-img-id'))}); - }, - getInitialState: function() { - return { startImgId: 0 }; - }, render: function() { - - var postImageModalId = "rhs_view_image_modal_" + this.props.post.id; var message = utils.textToJsx(this.props.post.message); - var filenames = this.props.post.filenames; var isOwner = UserStore.getCurrentId() == this.props.post.user_id; var timestamp = UserStore.getProfile(this.props.post.user_id).update_at; var channel = ChannelStore.get(this.props.post.channel_id); @@ -84,42 +75,6 @@ RootPost = React.createClass({ channelName = (channel.type === 'D') ? "Private Message" : channel.display_name; } - if (filenames) { - var postFiles = []; - var images = []; - var re1 = new RegExp(' ', 'g'); - var re2 = new RegExp('\\(', 'g'); - var re3 = new RegExp('\\)', 'g'); - for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { - var fileInfo = utils.splitFileLocation(filenames[i]); - var ftype = utils.getFileType(fileInfo.ext); - - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - - if (ftype === "image") { - var url = fileInfo.path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); - postFiles.push( -
-
-
- ); - images.push(filenames[i]); - } else { - postFiles.push( -
- -
- -
- ); - } - } - } - return (
{ channelName }
@@ -146,19 +101,12 @@ RootPost = React.createClass({

{message}

- { filenames.length > 0 ? -
- { postFiles } -
- : "" } - { images.length > 0 ? - + { this.props.post.filenames && this.props.post.filenames.length > 0 ? + : "" }
@@ -169,14 +117,7 @@ RootPost = React.createClass({ }); CommentPost = React.createClass({ - handleImageClick: function(e) { - this.setState({startImgId: parseInt($(e.target.parentNode).attr('data-img-id'))}); - }, - getInitialState: function() { - return { startImgId: 0 }; - }, render: function() { - var commentClass = "post"; var currentUserCss = ""; @@ -184,8 +125,6 @@ CommentPost = React.createClass({ currentUserCss = "current--user"; } - var postImageModalId = "rhs_comment_view_image_modal_" + this.props.post.id; - var filenames = this.props.post.filenames; var isOwner = UserStore.getCurrentId() == this.props.post.user_id; var type = "Post" @@ -193,43 +132,6 @@ CommentPost = React.createClass({ type = "Comment" } - if (filenames) { - var postFiles = []; - var images = []; - var re1 = new RegExp(' ', 'g'); - var re2 = new RegExp('\\(', 'g'); - var re3 = new RegExp('\\)', 'g'); - for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { - - var fileInfo = utils.splitFileLocation(filenames[i]); - var type = utils.getFileType(fileInfo.ext); - - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - - if (type === "image") { - var url = fileInfo.path.replace(re1, '%20').replace(re2, '%28').replace(re3, '%29'); - postFiles.push( -
-
-
- ); - images.push(filenames[i]); - } else { - postFiles.push( -
- -
- -
- ); - } - } - } - var message = utils.textToJsx(this.props.post.message); var timestamp = UserStore.getCurrentUser().update_at; @@ -256,19 +158,12 @@ CommentPost = React.createClass({

{message}

- { filenames.length > 0 ? -
- { postFiles } -
- : "" } - { images.length > 0 ? - + { this.props.post.filenames && this.props.post.filenames.length > 0 ? + : "" }
-- cgit v1.2.3-1-g7c22 From 00a17e34b365c1381370a8d0f0ba9437af4f10ef Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 23 Jul 2015 17:05:29 -0400 Subject: Cleaned up references to the current post in post_right.jsx --- web/react/components/post_right.jsx | 63 +++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'web/react') diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 861f03673..1d09842f3 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -56,18 +56,19 @@ RhsHeaderPost = React.createClass({ RootPost = React.createClass({ render: function() { - var message = utils.textToJsx(this.props.post.message); - var isOwner = UserStore.getCurrentId() == this.props.post.user_id; - var timestamp = UserStore.getProfile(this.props.post.user_id).update_at; - var channel = ChannelStore.get(this.props.post.channel_id); + var post = this.props.post; + var message = utils.textToJsx(post.message); + var isOwner = UserStore.getCurrentId() == post.user_id; + var timestamp = UserStore.getProfile(post.user_id).update_at; + var channel = ChannelStore.get(post.channel_id); var type = "Post"; - if (this.props.post.root_id.length > 0) { + if (post.root_id.length > 0) { type = "Comment"; } var currentUserCss = ""; - if (UserStore.getCurrentId() === this.props.post.user_id) { + if (UserStore.getCurrentId() === post.user_id) { currentUserCss = "current--user"; } @@ -79,20 +80,20 @@ RootPost = React.createClass({
{ channelName }
- +
    -
  • -
  • +
  • +
  • { isOwner ? : "" } @@ -101,12 +102,12 @@ RootPost = React.createClass({

{message}

- { this.props.post.filenames && this.props.post.filenames.length > 0 ? + { post.filenames && post.filenames.length > 0 ? + postId={post.id} + channelId={post.channel_id} + userId={post.user_id} + filenames={post.filenames} /> : "" }
@@ -118,39 +119,41 @@ RootPost = React.createClass({ CommentPost = React.createClass({ render: function() { + var post = this.props.post; + var commentClass = "post"; var currentUserCss = ""; - if (UserStore.getCurrentId() === this.props.post.user_id) { + if (UserStore.getCurrentId() === post.user_id) { currentUserCss = "current--user"; } - var isOwner = UserStore.getCurrentId() == this.props.post.user_id; + var isOwner = UserStore.getCurrentId() == post.user_id; var type = "Post" - if (this.props.post.root_id.length > 0) { + if (post.root_id.length > 0) { type = "Comment" } - var message = utils.textToJsx(this.props.post.message); + var message = utils.textToJsx(post.message); var timestamp = UserStore.getCurrentUser().update_at; return (
- +
    -
  • -
  • +
  • +
  • { isOwner ? : "" } @@ -158,12 +161,12 @@ CommentPost = React.createClass({

{message}

- { this.props.post.filenames && this.props.post.filenames.length > 0 ? + { post.filenames && post.filenames.length > 0 ? + postId={post.id} + channelId={post.channel_id} + userId={post.user_id} + filenames={post.filenames} /> : "" }
-- cgit v1.2.3-1-g7c22 From ca2b73eac375d7037c50e96330f449de2f2381bc Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 23 Jul 2015 18:28:31 -0400 Subject: Fix ViewImageModals created by RHS posts so that their ids are distinct from those in the main window --- web/react/components/file_attachment.jsx | 4 ++-- web/react/components/file_attachment_list.jsx | 9 ++++----- web/react/components/post_body.jsx | 6 +++--- web/react/components/post_right.jsx | 12 ++++++------ 4 files changed, 15 insertions(+), 16 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 4a81dd8f3..87922a615 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -8,7 +8,7 @@ module.exports = React.createClass({ propTypes: { filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, index: React.PropTypes.number.isRequired, - imageModalId: React.PropTypes.string.isRequired, + modalId: React.PropTypes.string.isRequired, handleImageClick: React.PropTypes.func }, componentDidMount: function() { @@ -66,7 +66,7 @@ module.exports = React.createClass({ if (type === "image") { thumbnail = ( + data-img-id={this.props.index} data-toggle="modal" data-target={"#" + this.props.modalId }>
); diff --git a/web/react/components/file_attachment_list.jsx b/web/react/components/file_attachment_list.jsx index 0b52d6a70..3da1e1482 100644 --- a/web/react/components/file_attachment_list.jsx +++ b/web/react/components/file_attachment_list.jsx @@ -9,7 +9,7 @@ module.exports = React.createClass({ displayName: "FileAttachmentList", propTypes: { filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, - postId: React.PropTypes.string.isRequired, + modalId: React.PropTypes.string.isRequired, channelId: React.PropTypes.string, userId: React.PropTypes.string }, @@ -18,12 +18,11 @@ module.exports = React.createClass({ }, render: function() { var filenames = this.props.filenames; - - var postImageModalId = "view_image_modal_" + this.props.postId; + var modalId = this.props.modalId; var postFiles = []; for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { - postFiles.push(); + postFiles.push(); } return ( @@ -34,7 +33,7 @@ module.exports = React.createClass({ diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index d29784db9..860c96d84 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -70,10 +70,10 @@ module.exports = React.createClass({

{inner}

{ filenames && filenames.length > 0 ? + userId={post.user_id} /> : "" } { embed }
diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 1d09842f3..ad8b54012 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -104,10 +104,10 @@ RootPost = React.createClass({

{message}

{ post.filenames && post.filenames.length > 0 ? + userId={post.user_id} /> : "" }
@@ -163,10 +163,10 @@ CommentPost = React.createClass({

{message}

{ post.filenames && post.filenames.length > 0 ? + userId={post.user_id} /> : "" }
-- cgit v1.2.3-1-g7c22 From 0f0a887205da3890671fd77ca4b7ece42de8b903 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 23 Jul 2015 18:29:53 -0400 Subject: Removed unused custom-file CSS class that was being applied to non-image file attachment previews --- web/react/components/file_attachment.jsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 87922a615..3f7deed97 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -78,11 +78,6 @@ module.exports = React.createClass({ ); } - var containerClassName = "post-image__column"; - if (type !== "image") { - containerClassName += " custom-file"; - } - // TODO fix the race condition here where the file size may arrive before the rest of the page is rendered // 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) { @@ -94,7 +89,7 @@ module.exports = React.createClass({ }(this, filename)); return ( -
+
{thumbnail}
{fileInfo.name}
-- cgit v1.2.3-1-g7c22 From 92c9ec71a051e076fd1dc3985a8a1225e5389a95 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 23 Jul 2015 18:56:35 -0400 Subject: Fixed race condition which could occur while requesting the file size for the file attachment previews --- web/react/components/file_attachment.jsx | 38 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 3f7deed97..ad3e2ffb8 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -11,6 +11,9 @@ module.exports = React.createClass({ modalId: React.PropTypes.string.isRequired, handleImageClick: React.PropTypes.func }, + getInitialState: function() { + return {fileSize: 0}; + }, componentDidMount: function() { var filename = this.props.filenames[this.props.index]; @@ -47,6 +50,22 @@ module.exports = React.createClass({ } } }, + shouldComponentUpdate: function(nextProps, nextState) { + // the only time this object should update is when it receives an updated file size which we can usually handle without re-rendering + if (nextState.fileSize != this.state.fileSize) { + if (this.refs.fileSize) { + // update the UI element to display the file size without re-rendering the whole component + this.refs.fileSize.getDOMNode().innerHTML = utils.fileSizeToString(nextState.fileSize); + + return false; + } else { + // we can't find the element that should hold the file size so we must not have rendered yet + return true; + } + } else { + return true; + } + }, render: function() { var filenames = this.props.filenames; var filename = filenames[this.props.index]; @@ -78,15 +97,14 @@ module.exports = React.createClass({ ); } - // TODO fix the race condition here where the file size may arrive before the rest of the page is rendered - // 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) { - if ((_filename + "__size") in self.refs) { - self.refs[_filename + "__size"].getDOMNode().innerHTML = " " + utils.fileSizeToString(size); - } - } - }(this, filename)); + if (!this.state.fileSize) { + var self = this; + + // asynchronously request the size of the file so that we can display it next to the thumbnail + utils.getFileSize(fileInfo.path + "." + fileInfo.ext, function(fileSize) { + self.setState({fileSize: fileSize}); + }); + } return (
@@ -95,7 +113,7 @@ module.exports = React.createClass({
{fileInfo.name}
{fileInfo.ext.toUpperCase()} - + {this.state.fileSize ? utils.fileSizeToString(this.state.fileSize) : ""}
-- cgit v1.2.3-1-g7c22 From 6d65071ecd1b024e0872c50749bde46b6c53b683 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Fri, 24 Jul 2015 11:16:22 -0400 Subject: Removed unused imgCount property from ViewImageModal --- web/react/components/file_attachment_list.jsx | 1 - web/react/components/view_image.jsx | 32 ++++++++++----------------- 2 files changed, 12 insertions(+), 21 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment_list.jsx b/web/react/components/file_attachment_list.jsx index 3da1e1482..5f2690fdf 100644 --- a/web/react/components/file_attachment_list.jsx +++ b/web/react/components/file_attachment_list.jsx @@ -35,7 +35,6 @@ module.exports = React.createClass({ userId={this.props.userId} modalId={modalId} startId={this.state.startImgId} - imgCount={0} filenames={filenames} />
); diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index 7b096c629..6ba76c0f8 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -31,18 +31,13 @@ module.exports = React.createClass({ return; }; - var src = ""; - if (this.props.imgCount > 0) { - src = this.props.filenames[id]; - } else { - var fileInfo = utils.splitFileLocation(this.props.filenames[id]); - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") !== -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - src = fileInfo['path'] + '_preview.jpg'; + var fileInfo = utils.splitFileLocation(this.props.filenames[id]); + // This is a temporary patch to fix issue with old files using absolute paths + if (fileInfo.path.indexOf("/api/v1/files/get") !== -1) { + fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; } + fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; + var src = fileInfo['path'] + '_preview.jpg'; var self = this; var img = new Image(); @@ -141,16 +136,13 @@ module.exports = React.createClass({ for (var id in this.state.images) { var info = utils.splitFileLocation(this.props.filenames[id]); var preview_filename = ""; - if (this.props.imgCount > 0) { - preview_filename = this.props.filenames[this.state.imgId]; - } else { - // This is a temporary patch to fix issue with old files using absolute paths - if (info.path.indexOf("/api/v1/files/get") !== -1) { - info.path = info.path.split("/api/v1/files/get")[1]; - } - info.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + info.path; - preview_filename = info['path'] + '_preview.jpg'; + + // This is a temporary patch to fix issue with old files using absolute paths + if (info.path.indexOf("/api/v1/files/get") !== -1) { + info.path = info.path.split("/api/v1/files/get")[1]; } + info.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + info.path; + preview_filename = info['path'] + '_preview.jpg'; var imgClass = "hidden"; if (this.state.loaded[id] && this.state.imgId == id) imgClass = ""; -- cgit v1.2.3-1-g7c22 From b8a69f767c768d3ca0cebc73553a2b37e68e9347 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Fri, 24 Jul 2015 17:04:02 -0400 Subject: Added preview images for non-image files --- web/react/components/view_image.jsx | 47 +++++++++++++++++++++++-------------- web/react/utils/utils.jsx | 13 ++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) (limited to 'web/react') diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index 6ba76c0f8..bd61bd9c9 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -31,17 +31,14 @@ module.exports = React.createClass({ return; }; - var fileInfo = utils.splitFileLocation(this.props.filenames[id]); - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") !== -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - var src = fileInfo['path'] + '_preview.jpg'; + var filename = this.props.filenames[id]; + + var fileInfo = utils.splitFileLocation(filename); + var fileType = utils.getFileType(fileInfo.ext); var self = this; var img = new Image(); - img.load(src, + img.load(this.getPreviewImagePath(filename), function(){ var progress = self.state.progress; progress[id] = img.completedPercentage; @@ -134,20 +131,17 @@ module.exports = React.createClass({ bgClass = "black-bg"; } else if (this.state.viewed) { for (var id in this.state.images) { - var info = utils.splitFileLocation(this.props.filenames[id]); - var preview_filename = ""; - - // This is a temporary patch to fix issue with old files using absolute paths - if (info.path.indexOf("/api/v1/files/get") !== -1) { - info.path = info.path.split("/api/v1/files/get")[1]; - } - info.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + info.path; - preview_filename = info['path'] + '_preview.jpg'; + var filename = this.props.filenames[id]; + var fileInfo = utils.splitFileLocation(filename); var imgClass = "hidden"; if (this.state.loaded[id] && this.state.imgId == id) imgClass = ""; - img[info['path']] = ; + img[fileInfo.path] = ( + + + + ); } } @@ -197,5 +191,22 @@ module.exports = React.createClass({
); + }, + getPreviewImagePath: function(filename) { + var fileInfo = utils.splitFileLocation(filename); + var fileType = utils.getFileType(fileInfo.ext); + + if (fileType === "image") { + // This is a temporary patch to fix issue with old files using absolute paths + if (fileInfo.path.indexOf("/api/v1/files/get") !== -1) { + fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; + } + fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; + + return fileInfo.path + '_preview.jpg'; + } else { + // only images have proper previews, so just use a placeholder icon for non-images + return utils.getPreviewImagePathForFileType(fileType); + } } }); diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index aa59201cb..e48ffed9a 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -533,6 +533,19 @@ module.exports.getFileType = function(ext) { return "other"; }; +module.exports.getPreviewImagePathForFileType = function(fileType) { + fileType = fileType.toLowerCase(); + + var icon; + if (fileType in Constants.ICON_FROM_TYPE) { + icon = Constants.ICON_FROM_TYPE[fileType]; + } else { + icon = Constants.ICON_FROM_TYPE["other"]; + } + + return "/static/images/icons/" + icon + ".png"; +}; + module.exports.getIconClassName = function(fileType) { fileType = fileType.toLowerCase(); -- cgit v1.2.3-1-g7c22 From 0e121a68de2d99ac17b27e41d92efae7721c6578 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Fri, 24 Jul 2015 17:24:11 -0400 Subject: Changed the thumbnail for non-image file attachments to open the ViewImageModal on click like it does for image attachments --- web/react/components/file_attachment.jsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index ad3e2ffb8..fd5adb8b4 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -83,18 +83,9 @@ module.exports = React.createClass({ var thumbnail; if (type === "image") { - thumbnail = ( - -
- - ); + thumbnail =
; } else { - thumbnail = ( - -
- - ); + thumbnail =
; } if (!this.state.fileSize) { @@ -108,7 +99,10 @@ module.exports = React.createClass({ return (
- {thumbnail} + + {thumbnail} +
{fileInfo.name}
-- cgit v1.2.3-1-g7c22 From f66cd5e9773a38cca635d33d91f0ef3b056d94a0 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 28 Jul 2015 11:30:22 -0400 Subject: Added utility function to get a file attachment's url --- web/react/components/file_attachment.jsx | 10 +--------- web/react/utils/utils.jsx | 13 +++++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index fd5adb8b4..e730af5f2 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -71,16 +71,8 @@ module.exports = React.createClass({ var filename = filenames[this.props.index]; var fileInfo = utils.splitFileLocation(filename); - if (Object.keys(fileInfo).length === 0) return null; - var type = utils.getFileType(fileInfo.ext); - // This is a temporary patch to fix issue with old files using absolute paths - if (fileInfo.path.indexOf("/api/v1/files/get") != -1) { - fileInfo.path = fileInfo.path.split("/api/v1/files/get")[1]; - } - fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; - var thumbnail; if (type === "image") { thumbnail =
; @@ -92,7 +84,7 @@ module.exports = React.createClass({ var self = this; // asynchronously request the size of the file so that we can display it next to the thumbnail - utils.getFileSize(fileInfo.path + "." + fileInfo.ext, function(fileSize) { + utils.getFileSize(utils.getFileUrl(filename), function(fileSize) { self.setState({fileSize: fileSize}); }); } diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index e48ffed9a..d1513dea9 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -894,3 +894,16 @@ module.exports.fileSizeToString = function(bytes) { return bytes + "B"; } }; + +// Converts a filename (like those attached to Post objects) to a url that can be used to retrieve attachments from the server. +module.exports.getFileUrl = function(filename) { + var url = filename; + + // This is a temporary patch to fix issue with old files using absolute paths + if (url.indexOf("/api/v1/files/get") != -1) { + url = filename.split("/api/v1/files/get")[1]; + } + url = module.exports.getWindowLocationOrigin() + "/api/v1/files/get" + url; + + return url; +}; -- cgit v1.2.3-1-g7c22 From 411f8cb9effef0310abbb39f9ae53adf6ecf8aaf Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 28 Jul 2015 11:53:05 -0400 Subject: Fixed FileAttachment component to not spam the server with requests when displaying a zero byte file --- web/react/components/file_attachment.jsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index e730af5f2..346819bdd 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -12,7 +12,7 @@ module.exports = React.createClass({ handleImageClick: React.PropTypes.func }, getInitialState: function() { - return {fileSize: 0}; + return {fileSize: -1}; }, componentDidMount: function() { var filename = this.props.filenames[this.props.index]; @@ -80,7 +80,7 @@ module.exports = React.createClass({ thumbnail =
; } - if (!this.state.fileSize) { + if (this.state.fileSize < 0) { var self = this; // asynchronously request the size of the file so that we can display it next to the thumbnail @@ -89,6 +89,11 @@ module.exports = React.createClass({ }); } + var fileSizeString = ""; + if (this.state.fileSize >= 0) { + fileSizeString = utils.fileSizeToString(this.state.fileSize); + } + return (
{fileInfo.ext.toUpperCase()} - {this.state.fileSize ? utils.fileSizeToString(this.state.fileSize) : ""} + {this.fileSizeString}
-- cgit v1.2.3-1-g7c22 From b0c64c73f929c9021196706fa1352ac4aa6f95a4 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 28 Jul 2015 12:02:29 -0400 Subject: Added check to make sure that FileAttachment is mounted before asynchronously setting state to avoid warning messages. --- web/react/components/file_attachment.jsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 346819bdd..385ff0e8d 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -5,6 +5,7 @@ var utils = require('../utils/utils.jsx'); module.exports = React.createClass({ displayName: "FileAttachment", + canSetState: false, propTypes: { filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, index: React.PropTypes.number.isRequired, @@ -15,6 +16,8 @@ module.exports = React.createClass({ return {fileSize: -1}; }, componentDidMount: function() { + this.canSetState = true; + var filename = this.props.filenames[this.props.index]; var self = this; @@ -50,6 +53,10 @@ module.exports = React.createClass({ } } }, + componentWillUnmount: function() { + // keep track of when this component is mounted so that we can asynchronously change state without worrying about whether or not we're mounted + this.canSetState = false; + }, shouldComponentUpdate: function(nextProps, nextState) { // the only time this object should update is when it receives an updated file size which we can usually handle without re-rendering if (nextState.fileSize != this.state.fileSize) { @@ -85,7 +92,9 @@ module.exports = React.createClass({ // asynchronously request the size of the file so that we can display it next to the thumbnail utils.getFileSize(utils.getFileUrl(filename), function(fileSize) { - self.setState({fileSize: fileSize}); + if (self.canSetState) { + self.setState({fileSize: fileSize}); + } }); } @@ -104,7 +113,7 @@ module.exports = React.createClass({
{fileInfo.name}
{fileInfo.ext.toUpperCase()} - {this.fileSizeString} + {fileSizeString}
-- cgit v1.2.3-1-g7c22 From af246bb44b7968b9f880d819e3aa04342846fccc Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 28 Jul 2015 16:41:57 -0400 Subject: Updated ViewImage modal dialog to include details about non-image files --- web/react/components/file_attachment.jsx | 2 +- web/react/components/view_image.jsx | 136 ++++++++++++++++++------------- web/react/utils/utils.jsx | 6 ++ 3 files changed, 87 insertions(+), 57 deletions(-) (limited to 'web/react') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 385ff0e8d..57a064ff4 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -110,7 +110,7 @@ module.exports = React.createClass({ {thumbnail}
-
{fileInfo.name}
+
{decodeURIComponent(utils.getFileName(filename))}
{fileInfo.ext.toUpperCase()} {fileSizeString} diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index bd61bd9c9..c7fb1b785 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -36,29 +36,36 @@ module.exports = React.createClass({ var fileInfo = utils.splitFileLocation(filename); var fileType = utils.getFileType(fileInfo.ext); - var self = this; - var img = new Image(); - img.load(this.getPreviewImagePath(filename), - function(){ - var progress = self.state.progress; - progress[id] = img.completedPercentage; - self.setState({ progress: progress }); - }); - img.onload = function(imgid) { - return function() { - var loaded = self.state.loaded; - loaded[imgid] = true; - self.setState({ loaded: loaded }); - $(self.refs.image.getDOMNode()).css("max-height",imgHeight); - }; - }(id); - var images = this.state.images; - images[id] = img; - this.setState({ images: images }); + if (fileType === "image") { + var self = this; + var img = new Image(); + img.load(this.getPreviewImagePath(filename), + function(){ + var progress = self.state.progress; + progress[id] = img.completedPercentage; + self.setState({ progress: progress }); + }); + img.onload = function(imgid) { + return function() { + var loaded = self.state.loaded; + loaded[imgid] = true; + self.setState({ loaded: loaded }); + $(self.refs.image.getDOMNode()).css("max-height",imgHeight); + }; + }(id); + var images = this.state.images; + images[id] = img; + this.setState({ images: images }); + } else { + // there's nothing to load for non-image files + var loaded = this.state.loaded; + loaded[id] = true; + this.setState({ loaded: loaded }); + } }, componentDidUpdate: function() { - if (this.refs.image) { - if (this.state.loaded[this.state.imgId]) { + if (this.state.loaded[this.state.imgId]) { + if (this.refs.imageWrap) { $(this.refs.imageWrap.getDOMNode()).removeClass("default"); } } @@ -104,55 +111,73 @@ module.exports = React.createClass({ loaded.push(false); progress.push(0); } - return { imgId: this.props.startId, viewed: false, loaded: loaded, progress: progress, images: {} }; + return { imgId: this.props.startId, viewed: false, loaded: loaded, progress: progress, images: {}, fileSizes: {} }; }, render: function() { if (this.props.filenames.length < 1 || this.props.filenames.length-1 < this.state.imgId) { return
; } - var fileInfo = utils.splitFileLocation(this.props.filenames[this.state.imgId]); + var filename = this.props.filenames[this.state.imgId]; + var fileUrl = utils.getFileUrl(filename); - var name = fileInfo['name'] + '.' + fileInfo['ext']; + var name = decodeURIComponent(utils.getFileName(filename)); - var loading = ""; + var content; var bgClass = ""; - var img = {}; - if (!this.state.loaded[this.state.imgId]) { + if (this.state.loaded[this.state.imgId]) { + var fileInfo = utils.splitFileLocation(filename); + var fileType = utils.getFileType(fileInfo.ext); + + if (fileType === "image") { + content = ( + + + + ); + } else { + // non-image files include a section providing details about the file + var infoString = "File type " + fileInfo.ext.toUpperCase(); + if (this.state.fileSizes[filename] && this.state.fileSizes[filename] >= 0) { + infoString += ", Size " + utils.fileSizeToString(this.state.fileSizes[filename]); + } + + content = ( +
+ + + + +
+
{name}
+
{infoString}
+
+
+ ); + + // asynchronously request the actual size of this file + if (!(filename in this.state.fileSizes)) { + var self = this; + + utils.getFileSize(utils.getFileUrl(filename), function(fileSize) { + var fileSizes = self.state.fileSizes; + fileSizes[filename] = fileSize; + self.setState(fileSizes); + }); + } + } + } else { var percentage = Math.floor(this.state.progress[this.state.imgId]); - loading = ( -
- + content = ( +
+ { percentage > 0 ? {"Previewing " + percentage + "%"} : ""}
); bgClass = "black-bg"; - } else if (this.state.viewed) { - for (var id in this.state.images) { - var filename = this.props.filenames[id]; - var fileInfo = utils.splitFileLocation(filename); - - var imgClass = "hidden"; - if (this.state.loaded[id] && this.state.imgId == id) imgClass = ""; - - img[fileInfo.path] = ( - - - - ); - } - } - - var imgFragment = React.addons.createFragment(img); - - // This is a temporary patch to fix issue with old files using absolute paths - var download_link = this.props.filenames[this.state.imgId]; - if (download_link.indexOf("/api/v1/files/get") !== -1) { - download_link = download_link.split("/api/v1/files/get")[1]; } - download_link = utils.getWindowLocationOrigin() + "/api/v1/files/get" + download_link; return (