diff --git a/cycledash/comments.py b/cycledash/comments.py index 930a962..95a9393 100644 --- a/cycledash/comments.py +++ b/cycledash/comments.py @@ -4,6 +4,7 @@ from flask import jsonify, request from functools import wraps, partial from sqlalchemy import exc, select, func, desc +from pytz import utc from common.helpers import tables, CRUDError from cycledash import db @@ -253,7 +254,10 @@ def convert_col_name(name, user_comments): def date_as_int(dt): """Get dt represented as microseconds since 1970. jsonify will strip out microseconds, so we use this simpler format.""" - delta = dt - datetime.fromtimestamp(0) + # Since dt is a "timezoned" date, the other variable must also be + # Otherwise, we'd get: + # TypeError: can't subtract offset-naive and offset-aware datetimes + delta = dt - datetime.fromtimestamp(0, tz=utc) return int(delta.total_seconds() * (10**6)) diff --git a/cycledash/static/js/comments/components/comment.js b/cycledash/static/js/comments/components/comment.js index 6656ac2..772abee 100644 --- a/cycledash/static/js/comments/components/comment.js +++ b/cycledash/static/js/comments/components/comment.js @@ -55,10 +55,10 @@ var Comment = React.createClass({ return `/runs/${c.vcf_id}/examine?query=${c.contig}:${c.position}-${1+c.position}`; }, render: function() { - // Add the offset to get local time - var timezoneOffset = new Date().getTimezoneOffset() * 60 * 1000; - var comment = this.props.comment, - relativeDate = moment(new Date(comment.created)).add(timezoneOffset).fromNow(); + var comment = this.props.comment; + // moment uses the local timezone by default (converting the + // value, which starts in UTC, to that timezone) + var relativeDate = moment(comment.created).fromNow(); var authorName = comment.author_name ? comment.author_name.slice(0, 15) : 'Anonymous'; return ( diff --git a/cycledash/static/js/examine/components/CommentBox.js b/cycledash/static/js/examine/components/CommentBox.js index e2bd968..8445192 100644 --- a/cycledash/static/js/examine/components/CommentBox.js +++ b/cycledash/static/js/examine/components/CommentBox.js @@ -68,11 +68,8 @@ var CommentBox = React.createClass({ getHandleSaveForCreate: function() { var handleSetComment = this.props.handleSetComment; var record = this.props.record; - var timezoneOffset = this.getTimezoneOffsetMillis(); return function(commentText, authorName) { // Subtract the offset to get GMT (to match what's in the DB) - var createdDate = new Date(new Date().getTime() - - timezoneOffset); var newComment = _.extend( _.pick( record, @@ -85,9 +82,9 @@ var CommentBox = React.createClass({ 'author_name': authorName, // Note: this is a temporary date that does not get persisted // to the DB. Instead, the DB creates its own date, but this - // date is used for distinguishing between comments in the - // meantime. - 'created_date': createdDate}); + // date string is used for distinguishing between comments in + // the meantime. (UTC, because DB dates are UTC.) + 'created_date': moment.utc().format()}); handleSetComment(newComment, record); }; }, @@ -100,23 +97,19 @@ var CommentBox = React.createClass({ store.set(this.LOCAL_STORAGE_AUTHOR_KEY, authorName); } }, - getTimezoneOffsetMillis: function() { - var timezoneOffset = new Date().getTimezoneOffset(); - return timezoneOffset * 60 * 1000; - }, render: function() { var comments = this.props.record.comments; - var timezoneOffset = this.getTimezoneOffsetMillis(); var commentNodes = _.sortBy(comments, comment => { return new Date(comment.created_date).getTime(); }).map(comment => { - // Add the offset to get local time - var createdTimestampMillis = new Date(comment.created_date). - getTime() + timezoneOffset; - var rowKey = utils.getRowKey(this.props.record); + // moment uses the local timezone by default (converting the + // value, which starts in UTC, to that timezone) + var createdString = moment(comment.created_date).fromNow(); // Prevent react key collisions + var rowKey = utils.getRowKey(this.props.record); var reactKey = _.has(comment, 'id') ? - rowKey + comment.id : rowKey + String(createdTimestampMillis); + rowKey + comment.id : + rowKey + String(comment.created_date.getTime()); return ; }); diff --git a/schema.sql b/schema.sql index 103a5e8..2fc89de 100644 --- a/schema.sql +++ b/schema.sql @@ -45,8 +45,8 @@ CREATE TABLE user_comments ( alternates TEXT, comment_text TEXT NOT NULL, author_name TEXT, - created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - last_modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + created TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + last_modified TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE task_states ( diff --git a/tests/data.sql b/tests/data.sql index 9ed2c1f..75da1e0 100644 --- a/tests/data.sql +++ b/tests/data.sql @@ -109,12 +109,12 @@ SELECT pg_catalog.setval('task_states_id_seq', 2, true); -- COPY user_comments (id, vcf_id, sample_name, contig, "position", reference, alternates, comment_text, author_name, created, last_modified) FROM stdin; -1 1 NORMAL 20 61795 G T This is a comment on the second row! \N 2015-03-24 15:29:09.615967 2015-03-11 23:33:33.951753 -2 1 NORMAL 20 65900 G A *This* is a comment with [Markdown](http://daringfireball.net/projects/markdown/syntax). \N 2015-03-24 15:29:09.615967 2015-03-11 23:34:18.19118 -3 1 TUMOR 20 61795 G T *This* is a comment on the first variant with [Markdown](http://daringfireball.net/projects/markdown/syntax).\n \N 2015-03-24 15:29:09.615967 2015-03-12 15:30:20.570952 -4 1 NORMAL 20 61795 G T This is another comment on the second row! \N 2015-03-24 17:40:44.984191 2015-03-24 17:40:44.984191 -6 1 TUMOR 20 61795 G T This is a comment without Markdown by Bob! Bob 2015-03-24 17:46:40.962213 2015-03-24 17:46:40.962213 -5 1 TUMOR 20 61795 G T This is a comment without Markdown! \N 2015-03-24 17:43:23.497883 2015-03-24 17:43:23.497883 +1 1 NORMAL 20 61795 G T This is a comment on the second row! \N 2015-03-24 15:29:09.615967+00 2015-03-11 23:33:33.951753+00 +2 1 NORMAL 20 65900 G A *This* is a comment with [Markdown](http://daringfireball.net/projects/markdown/syntax). \N 2015-03-24 15:29:09.615967+00 2015-03-11 23:34:18.19118+00 +3 1 TUMOR 20 61795 G T *This* is a comment on the first variant with [Markdown](http://daringfireball.net/projects/markdown/syntax).\n \N 2015-03-24 15:29:09.615967+00 2015-03-12 15:30:20.570952+00 +4 1 NORMAL 20 61795 G T This is another comment on the second row! \N 2015-03-24 17:40:44.984191+00 2015-03-24 17:40:44.984191+00 +6 1 TUMOR 20 61795 G T This is a comment without Markdown by Bob! Bob 2015-03-24 17:46:40.962213+00 2015-03-24 17:46:40.962213+00 +5 1 TUMOR 20 61795 G T This is a comment without Markdown! \N 2015-03-24 17:43:23.497883+00 2015-03-24 17:43:23.497883+00 \. diff --git a/tests/pdifftests/images/examine_comments-edit.png b/tests/pdifftests/images/examine_comments-edit.png index ca81f04..94d4ec4 100644 Binary files a/tests/pdifftests/images/examine_comments-edit.png and b/tests/pdifftests/images/examine_comments-edit.png differ diff --git a/tests/pdifftests/images/examine_comments-view.png b/tests/pdifftests/images/examine_comments-view.png index 7bca9de..3b23330 100644 Binary files a/tests/pdifftests/images/examine_comments-view.png and b/tests/pdifftests/images/examine_comments-view.png differ diff --git a/tests/pdifftests/images/examine_sorted.png b/tests/pdifftests/images/examine_sorted.png index 9ee58d0..c7b75c9 100644 Binary files a/tests/pdifftests/images/examine_sorted.png and b/tests/pdifftests/images/examine_sorted.png differ diff --git a/tests/pdifftests/images/examine_tooltip.png b/tests/pdifftests/images/examine_tooltip.png index 7f44195..c62abfe 100644 Binary files a/tests/pdifftests/images/examine_tooltip.png and b/tests/pdifftests/images/examine_tooltip.png differ diff --git a/tests/pdifftests/images/runs_bams.png b/tests/pdifftests/images/runs_bams.png index 785220f..00087f7 100644 Binary files a/tests/pdifftests/images/runs_bams.png and b/tests/pdifftests/images/runs_bams.png differ diff --git a/tests/pdifftests/images/runs_info.png b/tests/pdifftests/images/runs_info.png index 7d418e6..09fdc5a 100644 Binary files a/tests/pdifftests/images/runs_info.png and b/tests/pdifftests/images/runs_info.png differ diff --git a/tests/pdifftests/images/runs_page.png b/tests/pdifftests/images/runs_page.png index ace2c72..6e431ad 100644 Binary files a/tests/pdifftests/images/runs_page.png and b/tests/pdifftests/images/runs_page.png differ diff --git a/tests/pdifftests/images/website_comments.png b/tests/pdifftests/images/website_comments.png index 5941010..36af141 100644 Binary files a/tests/pdifftests/images/website_comments.png and b/tests/pdifftests/images/website_comments.png differ