mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 09:36:19 -05:00
correct message bus regression
implement automatically updating dates in list
This commit is contained in:
parent
93aa0a9f39
commit
5f85aaee1d
9 changed files with 200 additions and 29 deletions
22
Guardfile
22
Guardfile
|
@ -58,19 +58,21 @@ unless ENV["USING_AUTOSPEC"]
|
|||
end
|
||||
end
|
||||
|
||||
def message_bus
|
||||
MessageBus::Instance.new.tap do |bus|
|
||||
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
|
||||
"default"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ::Guard
|
||||
class AutoReload < ::Guard::Guard
|
||||
|
||||
require File.dirname(__FILE__) + '/config/environment'
|
||||
|
||||
def self.message_bus
|
||||
MessageBus::Instance.new.tap do |bus|
|
||||
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
|
||||
"default"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_on_change(paths)
|
||||
paths.map! do |p|
|
||||
hash = nil
|
||||
|
@ -82,7 +84,7 @@ module ::Guard
|
|||
p = p.sub /^app\/assets\/stylesheets/, "assets"
|
||||
{name: p, hash: hash}
|
||||
end
|
||||
message_bus.publish "/file-change", paths
|
||||
self.class.message_bus.publish "/file-change", paths
|
||||
end
|
||||
|
||||
def run_all
|
||||
|
@ -93,7 +95,7 @@ end
|
|||
Thread.new do
|
||||
Listen.to('tmp/') do |modified,added,removed|
|
||||
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
|
||||
|
|
|
@ -141,6 +141,10 @@ Discourse = Ember.Application.createWithMixins({
|
|||
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(function(){
|
||||
Discourse.Formatter.updateRelativeAge($('.relative-date'));
|
||||
},60 * 1000);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
68
app/assets/javascripts/discourse/components/formatter.js
Normal file
68
app/assets/javascripts/discourse/components/formatter.js
Normal 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};
|
||||
})();
|
|
@ -173,11 +173,21 @@ Handlebars.registerHelper('avatar', function(user, options) {
|
|||
@for Handlebars
|
||||
**/
|
||||
Handlebars.registerHelper('unboundDate', function(property, options) {
|
||||
var dt;
|
||||
dt = new Date(Ember.Handlebars.get(this, property, options));
|
||||
var dt = new Date(Ember.Handlebars.get(this, property, options));
|
||||
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
|
||||
|
||||
|
@ -285,7 +295,7 @@ Handlebars.registerHelper('date', function(property, options) {
|
|||
}
|
||||
displayDate = humanized;
|
||||
if (!leaveAgo) {
|
||||
displayDate = (dt.millisecondsAgo()).duration();
|
||||
displayDate = (dt.millisecondsAgo()).duration();
|
||||
}
|
||||
}
|
||||
return new Handlebars.SafeString("<span class='date' title='" + fullReadable + "'>" + displayDate + "</span>");
|
||||
|
|
|
@ -63,14 +63,14 @@
|
|||
|
||||
{{#if bumped}}
|
||||
<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 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>
|
||||
{{else}}
|
||||
<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>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
require_dependency 'age_words'
|
||||
require_dependency 'pinned_check'
|
||||
|
||||
class ListableTopicSerializer < BasicTopicSerializer
|
||||
|
@ -10,8 +9,6 @@ class ListableTopicSerializer < BasicTopicSerializer
|
|||
:last_posted_at,
|
||||
:bumped,
|
||||
:bumped_at,
|
||||
:bumped_age,
|
||||
:age,
|
||||
:unseen,
|
||||
:last_read_post_number,
|
||||
:unread,
|
||||
|
@ -23,20 +20,10 @@ class ListableTopicSerializer < BasicTopicSerializer
|
|||
:closed,
|
||||
:archived
|
||||
|
||||
def age
|
||||
AgeWords.age_words(Time.now - (object.created_at || Time.now))
|
||||
end
|
||||
|
||||
def bumped
|
||||
object.created_at < object.bumped_at
|
||||
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
|
||||
object.user_data.present?
|
||||
end
|
||||
|
|
|
@ -7,6 +7,42 @@
|
|||
|
||||
en:
|
||||
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:
|
||||
topic: 'share a link to this topic'
|
||||
post: 'share a link to this post'
|
||||
|
|
63
spec/javascripts/components/formatter_spec.js
Normal file
63
spec/javascripts/components/formatter_spec.js
Normal 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");
|
||||
|
||||
});
|
||||
});
|
||||
});
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
//= require ../../app/assets/javascripts/locales/i18n
|
||||
//= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers
|
||||
//= require ../../app/assets/javascripts/locales/en
|
||||
//= require ../../app/assets/javascripts/discourse
|
||||
|
||||
// Stuff we need to load first
|
||||
|
|
Loading…
Reference in a new issue