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 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 web/react/components/file_attachment.jsx (limited to 'web/react/components/file_attachment.jsx') 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()} + +
+
+
+ ); + } +}); -- 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 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'web/react/components/file_attachment.jsx') 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 }>
); -- 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/components/file_attachment.jsx') 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/components/file_attachment.jsx') 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 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/components/file_attachment.jsx') 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 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'web/react/components/file_attachment.jsx') 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}); }); } -- 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/components/file_attachment.jsx') 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/components/file_attachment.jsx') 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react/components/file_attachment.jsx') 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} -- cgit v1.2.3-1-g7c22 From de01a7e6797a0d5c73bccc709639ff4ba328b744 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 28 Jul 2015 18:37:21 -0400 Subject: Cleaned up ViewImageModal and FileAttachment and added some extra comments --- web/react/components/file_attachment.jsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'web/react/components/file_attachment.jsx') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 57a064ff4..3cd791887 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -7,9 +7,13 @@ module.exports = React.createClass({ displayName: "FileAttachment", canSetState: false, propTypes: { + // a list of file pathes displayed by the parent FileAttachmentList filenames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired, + // the index of this attachment preview in the parent FileAttachmentList index: React.PropTypes.number.isRequired, + // the identifier of the modal dialog used to preview files modalId: React.PropTypes.string.isRequired, + // handler for when the thumbnail is clicked handleImageClick: React.PropTypes.func }, getInitialState: function() { @@ -20,12 +24,8 @@ module.exports = React.createClass({ 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 @@ -35,6 +35,7 @@ module.exports = React.createClass({ fileInfo.path = utils.getWindowLocationOrigin() + "/api/v1/files/get" + fileInfo.path; if (type === "image") { + var self = this; $('').attr('src', fileInfo.path+'_thumb.jpg').load(function(path, name){ return function() { $(this).remove(); if (name in self.refs) { @@ -87,6 +88,7 @@ module.exports = React.createClass({ thumbnail =
; } + var fileSizeString = ""; if (this.state.fileSize < 0) { var self = this; @@ -96,10 +98,7 @@ module.exports = React.createClass({ self.setState({fileSize: fileSize}); } }); - } - - var fileSizeString = ""; - if (this.state.fileSize >= 0) { + } else { fileSizeString = utils.fileSizeToString(this.state.fileSize); } -- cgit v1.2.3-1-g7c22 From dad78514234029791ff02c9a0efd2cbacdac5280 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 31 Jul 2015 09:52:18 -0400 Subject: center small thumbnails and top left larger thumbnails --- web/react/components/file_attachment.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'web/react/components/file_attachment.jsx') diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx index 3cd791887..b7ea5734f 100644 --- a/web/react/components/file_attachment.jsx +++ b/web/react/components/file_attachment.jsx @@ -2,6 +2,7 @@ // See License.txt for license information. var utils = require('../utils/utils.jsx'); +var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ displayName: "FileAttachment", @@ -44,6 +45,16 @@ module.exports = React.createClass({ $(imgDiv).removeClass('post__load'); $(imgDiv).addClass('post__image'); + var width = this.width || $(this).width(); + var height = this.height || $(this).height(); + + if (width < Constants.THUMBNAIL_WIDTH + && height < Constants.THUMBNAIL_HEIGHT) { + $(imgDiv).addClass('small'); + } else { + $(imgDiv).addClass('normal'); + } + var re1 = new RegExp(' ', 'g'); var re2 = new RegExp('\\(', 'g'); var re3 = new RegExp('\\)', 'g'); -- cgit v1.2.3-1-g7c22