correct message bus regression

implement automatically updating dates in list
This commit is contained in:
Sam 2013-06-05 09:32:03 +10:00
parent 93aa0a9f39
commit 5f85aaee1d
9 changed files with 200 additions and 29 deletions

View file

@ -58,19 +58,21 @@ unless ENV["USING_AUTOSPEC"]
end end
end end
def message_bus
module ::Guard
class AutoReload < ::Guard::Guard
require File.dirname(__FILE__) + '/config/environment'
def self.message_bus
MessageBus::Instance.new.tap do |bus| MessageBus::Instance.new.tap do |bus|
bus.site_id_lookup do bus.site_id_lookup do
# this is going to be dev the majority of the time, if you have multisite configured in dev stuff may be different # this is going to be dev the majority of the time, if you have multisite configured in dev stuff may be different
"default" "default"
end end
end end
end end
module ::Guard
class AutoReload < ::Guard::Guard
require File.dirname(__FILE__) + '/config/environment'
def run_on_change(paths) def run_on_change(paths)
paths.map! do |p| paths.map! do |p|
hash = nil hash = nil
@ -82,7 +84,7 @@ module ::Guard
p = p.sub /^app\/assets\/stylesheets/, "assets" p = p.sub /^app\/assets\/stylesheets/, "assets"
{name: p, hash: hash} {name: p, hash: hash}
end end
message_bus.publish "/file-change", paths self.class.message_bus.publish "/file-change", paths
end end
def run_all def run_all
@ -93,7 +95,7 @@ end
Thread.new do Thread.new do
Listen.to('tmp/') do |modified,added,removed| Listen.to('tmp/') do |modified,added,removed|
modified.each do |m| modified.each do |m|
message_bus.publish "/file-change", ["refresh"] if m =~ /refresh_browser/ Guard::AutoReload.message_bus.publish "/file-change", ["refresh"] if m =~ /refresh_browser/
end end
end end
end end

View file

@ -141,6 +141,10 @@ Discourse = Ember.Application.createWithMixins({
xhr.setRequestHeader('X-CSRF-Token', csrfToken); xhr.setRequestHeader('X-CSRF-Token', csrfToken);
} }
}); });
setInterval(function(){
Discourse.Formatter.updateRelativeAge($('.relative-date'));
},60 * 1000);
}, },
/** /**

View file

@ -0,0 +1,68 @@
Discourse.Formatter = (function(){
var updateRelativeAge, autoUpdatingRelativeAge, relativeAge;
updateRelativeAge = function(elems) {
elems.each(function(){
var $this = $(this);
$this.html(relativeAge(new Date($this.data('time')), $this.data('format')));
});
};
autoUpdatingRelativeAge = function(date,options) {
options = options || {};
var format = options.format || "tiny";
return "<span class='relative-date' data-time='" + date.getTime() + "' data-format='" + format + "'>" + relativeAge(date, options) + "</span>";
};
// mostly lifted from rails with a few amendments
relativeAge = function(date, options) {
options = options || {};
var format = options.format || "tiny";
var distance = Math.round((new Date() - date) / 1000);
var distance_in_minutes = Math.round(distance / 60.0);
var formatted;
var t = function(key,opts){
return Ember.String.i18n("dates." + format + "." + key, opts);
};
switch(true){
case(distance_in_minutes < 1):
formatted = t("less_than_x_minutes", {count: 1});
break;
case(distance_in_minutes >= 1 && distance_in_minutes <= 44):
formatted = t("x_minutes", {count: distance_in_minutes});
break;
case(distance_in_minutes >= 45 && distance_in_minutes <= 89):
formatted = t("about_x_hours", {count: 1});
break;
case(distance_in_minutes >= 90 && distance_in_minutes <= 1439):
formatted = t("about_x_hours", {count: Math.round(distance_in_minutes / 60.0)});
break;
case(distance_in_minutes >= 1440 && distance_in_minutes <= 2519):
formatted = t("x_days", {count: 1});
break;
case(distance_in_minutes >= 2520 && distance_in_minutes <= 129599):
formatted = t("x_days", {count: Math.round(distance_in_minutes / 1440.0)});
break;
case(distance_in_minutes >= 129600 && distance_in_minutes <= 525599):
formatted = t("x_months", {count: Math.round(distance_in_minutes / 43200.0)});
break;
default:
var months = Math.round(distance_in_minutes / 43200.0);
if (months < 24) {
formatted = t("x_months", {count: months});
} else {
formatted = t("over_x_years", {count: Math.round(months / 12.0)});
}
break;
}
return formatted;
};
return {relativeAge: relativeAge, autoUpdatingRelativeAge: autoUpdatingRelativeAge, updateRelativeAge: updateRelativeAge};
})();

View file

@ -173,11 +173,21 @@ Handlebars.registerHelper('avatar', function(user, options) {
@for Handlebars @for Handlebars
**/ **/
Handlebars.registerHelper('unboundDate', function(property, options) { Handlebars.registerHelper('unboundDate', function(property, options) {
var dt; var dt = new Date(Ember.Handlebars.get(this, property, options));
dt = new Date(Ember.Handlebars.get(this, property, options));
return dt.format("long"); return dt.format("long");
}); });
/**
Live refreshing age helper
@method unboundDate
@for Handlebars
**/
Handlebars.registerHelper('unboundAge', function(property, options) {
var dt = new Date(Ember.Handlebars.get(this, property, options));
return new Handlebars.SafeString(Discourse.Formatter.autoUpdatingRelativeAge(dt));
});
/** /**
Display a date related to an edit of a post Display a date related to an edit of a post

View file

@ -63,14 +63,14 @@
{{#if bumped}} {{#if bumped}}
<td class='num activity'> <td class='num activity'>
<a href="{{url}}" {{{bindAttr class=":age ageCold"}}} title='{{i18n first_post}}: {{{unboundDate created_at}}}' >{{{age}}}</a> <a href="{{url}}" {{{bindAttr class=":age ageCold"}}} title='{{i18n first_post}}: {{{unboundDate created_at}}}' >{{unboundAge created_at}}</a>
</td> </td>
<td class='num activity last'> <td class='num activity last'>
<a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{unboundDate bumped_at}}}'>{{{bumped_age}}}</a> <a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{unboundDate bumped_at}}}'>{{unboundAge bumped_at}}</a>
</td> </td>
{{else}} {{else}}
<td class='num activity'> <td class='num activity'>
<a href="{{url}}" class='age' title='{{i18n first_post}}: {{{unboundDate created_at}}}'>{{{age}}}</a> <a href="{{url}}" class='age' title='{{i18n first_post}}: {{{unboundDate created_at}}}'>{{unboundAge created_at}}</a>
</td> </td>
<td></td> <td></td>
{{/if}} {{/if}}

View file

@ -1,4 +1,3 @@
require_dependency 'age_words'
require_dependency 'pinned_check' require_dependency 'pinned_check'
class ListableTopicSerializer < BasicTopicSerializer class ListableTopicSerializer < BasicTopicSerializer
@ -10,8 +9,6 @@ class ListableTopicSerializer < BasicTopicSerializer
:last_posted_at, :last_posted_at,
:bumped, :bumped,
:bumped_at, :bumped_at,
:bumped_age,
:age,
:unseen, :unseen,
:last_read_post_number, :last_read_post_number,
:unread, :unread,
@ -23,20 +20,10 @@ class ListableTopicSerializer < BasicTopicSerializer
:closed, :closed,
:archived :archived
def age
AgeWords.age_words(Time.now - (object.created_at || Time.now))
end
def bumped def bumped
object.created_at < object.bumped_at object.created_at < object.bumped_at
end end
def bumped_age
return nil if object.bumped_at.blank?
AgeWords.age_words(Time.now - object.bumped_at)
end
alias include_bumped_age? :bumped
def seen def seen
object.user_data.present? object.user_data.present?
end end

View file

@ -7,6 +7,42 @@
en: en:
js: js:
dates:
tiny:
half_a_minute: "< 1m"
less_than_x_seconds:
one: "< 1s"
other: "< %{count}s"
x_seconds:
one: "1s"
other: "%{count}s"
less_than_x_minutes:
one: "< 1m"
other: "< %{count}m"
x_minutes:
one: "1m"
other: "%{count}m"
about_x_hours:
one: "1h"
other: "%{count}h"
x_days:
one: "1d"
other: "%{count}d"
about_x_months:
one: "1mon"
other: "%{count}mon"
x_months:
one: "1mon"
other: "%{count}mon"
about_x_years:
one: "1y"
other: "%{count}y"
over_x_years:
one: "> 1y"
other: "> %{count}y"
almost_x_years:
one: "1y"
other: "%{count}y"
share: share:
topic: 'share a link to this topic' topic: 'share a link to this topic'
post: 'share a link to this post' post: 'share a link to this post'

View file

@ -0,0 +1,63 @@
/*global expect:true describe:true it:true beforeEach:true afterEach:true spyOn:true */
describe("Discourse.Formatter", function() {
describe("relativeTime", function() {
it("can format dates", function() {
var mins_ago = function(mins){
return new Date((new Date()) - mins * 60 * 1000);
};
var formatMins = function(mins) {
return Discourse.Formatter.relativeAge(mins_ago(mins));
};
var formatHours = function(hours) {
return formatMins(hours * 60);
};
var formatDays = function(days) {
return formatHours(days * 24);
};
var formatMonths = function(months) {
return formatDays(months * 30);
};
expect(formatMins(0)).toBe("< 1m");
expect(formatMins(2)).toBe("2m");
expect(formatMins(60)).toBe("1h");
expect(formatHours(4)).toBe("4h");
expect(formatDays(1)).toBe("1d");
expect(formatDays(20)).toBe("20d");
expect(formatMonths(3)).toBe("3mon");
expect(formatMonths(23)).toBe("23mon");
expect(formatMonths(24)).toBe("> 2y");
});
});
describe("autoUpdatingRelativeAge", function(){
it("can format dates", function(){
var d = new Date();
var $elem = $(Discourse.Formatter.autoUpdatingRelativeAge(d));
expect($elem.data('format')).toBe("tiny");
expect($elem.data('time')).toBe(d.getTime());
});
});
describe("updateRelativeAge", function(){
it("can update relative dates", function(){
var d = new Date();
var $elem = $(Discourse.Formatter.autoUpdatingRelativeAge(d));
$elem.data('time', d.getTime() - 2 * 60 * 1000);
Discourse.Formatter.updateRelativeAge($elem);
expect($elem.html()).toBe("2m");
});
});
});

View file

@ -22,6 +22,7 @@
//= require ../../app/assets/javascripts/locales/i18n //= require ../../app/assets/javascripts/locales/i18n
//= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers //= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers
//= require ../../app/assets/javascripts/locales/en
//= require ../../app/assets/javascripts/discourse //= require ../../app/assets/javascripts/discourse
// Stuff we need to load first // Stuff we need to load first