UX: Squash activity columns together. Show a cold map on the difference
between the last post and original post dates. Fix some missing classes in the mobile templates and topic map.
This commit is contained in:
parent
658cdd2c9e
commit
6f3db0e386
|
@ -0,0 +1,45 @@
|
||||||
|
import { daysSinceEpoch } from "discourse/helpers/cold-age-class";
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: 'td',
|
||||||
|
classNameBindings: [':activity', 'coldness'],
|
||||||
|
attributeBindings: ['title'],
|
||||||
|
|
||||||
|
// returns createdAt if there's no bumped date
|
||||||
|
bumpedAt: function() {
|
||||||
|
var bumpedAt = this.get('topic.bumped_at');
|
||||||
|
if (bumpedAt) {
|
||||||
|
return new Date(bumpedAt);
|
||||||
|
} else {
|
||||||
|
return this.get('createdAt');
|
||||||
|
}
|
||||||
|
}.property('topic.bumped_at', 'createdAt'),
|
||||||
|
|
||||||
|
createdAt: function() {
|
||||||
|
return new Date(this.get('topic.created_at'));
|
||||||
|
}.property('topic.created_at'),
|
||||||
|
|
||||||
|
coldness: function() {
|
||||||
|
var bumpedAt = this.get('bumpedAt'),
|
||||||
|
createdAt = this.get('createdAt');
|
||||||
|
|
||||||
|
if (!bumpedAt) { return; }
|
||||||
|
var delta = daysSinceEpoch(bumpedAt) - daysSinceEpoch(createdAt);
|
||||||
|
|
||||||
|
if (delta > 120) { return 'coldmap-high'; }
|
||||||
|
if (delta > 60) { return 'coldmap-med'; }
|
||||||
|
if (delta > 14) { return 'coldmap-low'; }
|
||||||
|
}.property('bumpedAt', 'createdAt'),
|
||||||
|
|
||||||
|
title: function() {
|
||||||
|
// return {{i18n last_post}}: {{{raw-date topic.bumped_at}}}
|
||||||
|
return I18n.t('first_post') + ": " + Discourse.Formatter.longDate(this.get('createdAt')) + "\n" +
|
||||||
|
I18n.t('last_post') + ": " + Discourse.Formatter.longDate(this.get('bumpedAt'));
|
||||||
|
}.property('bumpedAt', 'createdAt'),
|
||||||
|
|
||||||
|
render: function(buffer) {
|
||||||
|
buffer.push('<a href="' + this.get('topic.lastPostUrl') + '">');
|
||||||
|
buffer.push(Discourse.Formatter.autoUpdatingRelativeAge(this.get('bumpedAt')));
|
||||||
|
buffer.push("</a>");
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,33 +1,5 @@
|
||||||
// helper function for dates
|
|
||||||
function daysSinceEpoch(dt) {
|
|
||||||
// 1000 * 60 * 60 * 24 = days since epoch
|
|
||||||
return dt.getTime() / 86400000;
|
|
||||||
}
|
|
||||||
|
|
||||||
var safe = Handlebars.SafeString;
|
var safe = Handlebars.SafeString;
|
||||||
|
|
||||||
/**
|
|
||||||
Converts a date to a coldmap class
|
|
||||||
|
|
||||||
@method cold-age-class
|
|
||||||
@for Handlebars
|
|
||||||
**/
|
|
||||||
Handlebars.registerHelper('cold-age-class', function(property, options) {
|
|
||||||
var dt = Em.Handlebars.get(this, property, options);
|
|
||||||
|
|
||||||
if (!dt) { return 'age'; }
|
|
||||||
|
|
||||||
// Show heat on age
|
|
||||||
var nowDays = daysSinceEpoch(new Date()),
|
|
||||||
epochDays = daysSinceEpoch(new Date(dt));
|
|
||||||
if (nowDays - epochDays > 60) return 'age coldmap-high';
|
|
||||||
if (nowDays - epochDays > 30) return 'age coldmap-med';
|
|
||||||
if (nowDays - epochDays > 14) return 'age coldmap-low';
|
|
||||||
|
|
||||||
return 'age';
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Truncates long strings
|
Truncates long strings
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
export function daysSinceEpoch(dt) {
|
||||||
|
// 1000 * 60 * 60 * 24 = days since epoch
|
||||||
|
return dt.getTime() / 86400000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts a date to a coldmap class
|
||||||
|
**/
|
||||||
|
function coldAgeClass(property, options) {
|
||||||
|
var dt = Em.Handlebars.get(this, property, options);
|
||||||
|
|
||||||
|
if (!dt) { return 'age'; }
|
||||||
|
|
||||||
|
// Show heat on age
|
||||||
|
var nowDays = daysSinceEpoch(new Date()),
|
||||||
|
epochDays = daysSinceEpoch(new Date(dt));
|
||||||
|
if (nowDays - epochDays > 60) return 'age coldmap-high';
|
||||||
|
if (nowDays - epochDays > 30) return 'age coldmap-med';
|
||||||
|
if (nowDays - epochDays > 14) return 'age coldmap-low';
|
||||||
|
|
||||||
|
return 'age';
|
||||||
|
}
|
||||||
|
|
||||||
|
Handlebars.registerHelper('cold-age-class', coldAgeClass);
|
||||||
|
export default coldAgeClass;
|
|
@ -1,11 +1,3 @@
|
||||||
/**
|
|
||||||
A data model representing a Topic
|
|
||||||
|
|
||||||
@class Topic
|
|
||||||
@extends Discourse.Model
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.Topic = Discourse.Model.extend({
|
Discourse.Topic = Discourse.Model.extend({
|
||||||
|
|
||||||
postStream: function() {
|
postStream: function() {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<th class="posters">{{i18n users}}</th>
|
<th class="posters">{{i18n users}}</th>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<th class="num views">{{i18n views}}</th>
|
<th class="num views">{{i18n views}}</th>
|
||||||
<th class="num activity" colspan="2">{{i18n activity}}</th>
|
<th class="num activity">{{i18n activity}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
@ -55,19 +55,7 @@
|
||||||
{{number topic.views numberKey="views_long"}}
|
{{number topic.views numberKey="views_long"}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{#if topic.bumped}}
|
{{activity-column topic=topic class="num"}}
|
||||||
<td class='num activity'>
|
|
||||||
<a href="{{unbound topic.url}}" class='{{cold-age-class created_at}}' title='{{i18n first_post}}: {{{raw-date topic.created_at}}}' >{{age topic.created_at}}</a>
|
|
||||||
</td>
|
|
||||||
<td class='num activity last'>
|
|
||||||
<a href="{{unbound topic.lastPostUrl}}" class='{{cold-age-class bumped_at}}' title='{{i18n last_post}}: {{{raw-date topic.bumped_at}}}'>{{age topic.bumped_at}}</a>
|
|
||||||
</td>
|
|
||||||
{{else}}
|
|
||||||
<td class='num activity'>
|
|
||||||
<a href="{{unbound topic.url}}" class='age' title='{{i18n first_post}}: {{{raw-date topic.created_at}}}'>{{age topic.created_at}}</a>
|
|
||||||
</td>
|
|
||||||
<td class="activity"></td>
|
|
||||||
{{/if}}
|
|
||||||
</tr>
|
</tr>
|
||||||
{{/grouped-each}}
|
{{/grouped-each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{{number topic.posts_count}}
|
{{number topic.posts_count class=topic.likesHeat}}
|
||||||
<h4>{{i18n posts_lowercase}}</h4>
|
<h4>{{i18n posts_lowercase}}</h4>
|
||||||
</li>
|
</li>
|
||||||
<li class='secondary'>
|
<li class='secondary'>
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
{{#sortable-heading sortBy="views" number=true action="changeSort" order=order ascending=ascending}}
|
{{#sortable-heading sortBy="views" number=true action="changeSort" order=order ascending=ascending}}
|
||||||
{{i18n views}}
|
{{i18n views}}
|
||||||
{{/sortable-heading}}
|
{{/sortable-heading}}
|
||||||
{{#sortable-heading sortBy="activity" number=true colspan="2" action="changeSort" order=order ascending=ascending}}
|
{{#sortable-heading sortBy="activity" number=true action="changeSort" order=order ascending=ascending}}
|
||||||
{{i18n activity}}
|
{{i18n activity}}
|
||||||
{{/sortable-heading}}
|
{{/sortable-heading}}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -50,16 +50,4 @@
|
||||||
|
|
||||||
<td {{bind-attr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td>
|
<td {{bind-attr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td>
|
||||||
|
|
||||||
{{#if bumped}}
|
{{activity-column topic=model class="num"}}
|
||||||
<td class='num activity'>
|
|
||||||
<a href="{{url}}" class="{{cold-age-class created_at}}" title='{{i18n first_post}}: {{{raw-date created_at}}}' >{{age created_at}}</a>
|
|
||||||
</td>
|
|
||||||
<td class='num activity last'>
|
|
||||||
<a href="{{lastPostUrl}}" class="{{cold-age-class bumped_at}}" title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{age bumped_at}}</a>
|
|
||||||
</td>
|
|
||||||
{{else}}
|
|
||||||
<td class='num activity'>
|
|
||||||
<a href="{{url}}" class="{{cold-age-class created_at}}" title='{{i18n first_post}}: {{{raw-date created_at}}}'>{{age created_at}}</a>
|
|
||||||
</td>
|
|
||||||
<td class='activity'></td>
|
|
||||||
{{/if}}
|
|
||||||
|
|
|
@ -31,17 +31,9 @@
|
||||||
<div class="topic-item-stats clearfix">
|
<div class="topic-item-stats clearfix">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<div class='num posts'>
|
<div class='num posts'>
|
||||||
<a href="{{lastUnreadUrl}}">{{number posts_count numberKey="posts_long"}}</a>
|
<a href="{{lastUnreadUrl}}" {{bind-attr class="likesHeat"}}>{{number posts_count numberKey="posts_long"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{#if bumped}}
|
{{activity-column topic=topic tagName="div" class="num activity last"}}
|
||||||
<div class='num activity last'>
|
|
||||||
<a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{age bumped_at}}</a>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class='num activity last'>
|
|
||||||
<a href="{{url}}" class='age' title='{{i18n first_post}}: {{{raw-date created_at}}}'>{{age created_at}}</a>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
{{#unless controller.hideCategory}}
|
{{#unless controller.hideCategory}}
|
||||||
<div class='category'>
|
<div class='category'>
|
||||||
|
|
|
@ -33,19 +33,12 @@
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<div class='num posts'><a href="{{lastUnreadUrl}}">{{number posts_count numberKey="posts_long"}}</a></div>
|
<div class='num posts'><a href="{{lastUnreadUrl}}" {{bind-attr class="likesHeat"}}>{{number posts_count numberKey="posts_long"}}</a></div>
|
||||||
|
|
||||||
{{#if bumped}}
|
|
||||||
<div class='num activity last'>
|
<div class='num activity last'>
|
||||||
<a href="{{lastPostUrl}}" title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{last_poster_username}}</a>
|
<a href="{{lastPostUrl}}" title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{last_poster_username}}</a>
|
||||||
<a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{age bumped_at}}</a>
|
{{activity-column topic=this tagName="span" class="age"}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
|
||||||
<div class='num activity last'>
|
|
||||||
<a href="{{url}}" title='{{i18n last_post}}: {{{raw-date bumped_at}}}'>{{last_poster_username}}</a>
|
|
||||||
<a href="{{url}}" class='age' title='{{i18n first_post}}: {{{raw-date created_at}}}'>{{age created_at}}</a>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
//= require ./discourse/routes/build-topic-route
|
//= require ./discourse/routes/build-topic-route
|
||||||
//= require ./discourse/routes/discourse_restricted_user_route
|
//= require ./discourse/routes/discourse_restricted_user_route
|
||||||
//= require ./discourse/components/text-field
|
//= require ./discourse/components/text-field
|
||||||
|
//= require ./discourse/helpers/cold-age-class
|
||||||
|
|
||||||
//= require ./discourse/dialects/dialect
|
//= require ./discourse/dialects/dialect
|
||||||
//= require_tree ./discourse/dialects
|
//= require_tree ./discourse/dialects
|
||||||
|
|
Loading…
Reference in New Issue