mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-02-25 07:54:11 -05:00
Show estimated reading time near summarize button.
This commit is contained in:
parent
561961eff6
commit
6853f37bee
10 changed files with 78 additions and 3 deletions
|
@ -160,6 +160,15 @@ Discourse.Topic = Discourse.Model.extend({
|
||||||
return I18n.t(this.get('favoriteTooltipKey'));
|
return I18n.t(this.get('favoriteTooltipKey'));
|
||||||
}.property('favoriteTooltipKey'),
|
}.property('favoriteTooltipKey'),
|
||||||
|
|
||||||
|
estimatedReadingTime: function() {
|
||||||
|
var wordCount = this.get('word_count');
|
||||||
|
if (!wordCount) return;
|
||||||
|
|
||||||
|
// Avg for 250 words per minute.
|
||||||
|
var minutes = Math.floor(wordCount / 250.0);
|
||||||
|
return minutes;
|
||||||
|
}.property('word_count'),
|
||||||
|
|
||||||
toggleStar: function() {
|
toggleStar: function() {
|
||||||
var topic = this;
|
var topic = this;
|
||||||
topic.toggleProperty('starred');
|
topic.toggleProperty('starred');
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
<p>{{{i18n summary.enabled_description}}}</p>
|
<p>{{{i18n summary.enabled_description}}}</p>
|
||||||
<button class='btn' {{action toggleSummary}}>{{i18n summary.disable}}</button>
|
<button class='btn' {{action toggleSummary}}>{{i18n summary.disable}}</button>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>{{{i18n summary.description count="topic.posts_count"}}}</p>
|
{{#if topic.estimatedReadingTime}}
|
||||||
|
<p>{{{i18n summary.description_time count="topic.posts_count" readingTime="topic.estimatedReadingTime"}}}</p>
|
||||||
|
{{else}}
|
||||||
|
<p>{{{i18n summary.description count="topic.posts_count"}}}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<button class='btn' {{action toggleSummary}}>{{i18n summary.enable}}</button>
|
<button class='btn' {{action toggleSummary}}>{{i18n summary.enable}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -22,6 +22,7 @@ class TopicViewSerializer < ApplicationSerializer
|
||||||
:archetype,
|
:archetype,
|
||||||
:slug,
|
:slug,
|
||||||
:category_id,
|
:category_id,
|
||||||
|
:word_count,
|
||||||
:deleted_at]
|
:deleted_at]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -384,6 +384,7 @@ en:
|
||||||
summary:
|
summary:
|
||||||
enabled_description: "You're viewing a summary of this topic. To see all posts again, click below."
|
enabled_description: "You're viewing a summary of this topic. To see all posts again, click below."
|
||||||
description: "There are <b>{{count}}</b> replies. Save reading time by displaying only the most relevant replies?"
|
description: "There are <b>{{count}}</b> replies. Save reading time by displaying only the most relevant replies?"
|
||||||
|
description_time: "There are <b>{{count}}</b> replies with an estimated read time of <b>{{readingTime}} minutes</b>. Save reading time by displaying only the most relevant replies?"
|
||||||
enable: 'Summarize This Topic'
|
enable: 'Summarize This Topic'
|
||||||
disable: 'Show All Posts'
|
disable: 'Show All Posts'
|
||||||
|
|
||||||
|
|
11
db/migrate/20131210163702_add_word_count_to_posts.rb
Normal file
11
db/migrate/20131210163702_add_word_count_to_posts.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class AddWordCountToPosts < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column :posts, :word_count, :integer
|
||||||
|
add_column :topics, :word_count, :integer
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :posts, :word_count, :integer
|
||||||
|
remove_column :topics, :word_count, :integer
|
||||||
|
end
|
||||||
|
end
|
20
db/migrate/20131210181901_migrate_word_counts.rb
Normal file
20
db/migrate/20131210181901_migrate_word_counts.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class MigrateWordCounts < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
|
||||||
|
disable_ddl_transaction
|
||||||
|
|
||||||
|
post_ids = execute("SELECT id FROM posts WHERE word_count IS NULL LIMIT 500").map {|r| r['id'].to_i }
|
||||||
|
while post_ids.length > 0
|
||||||
|
execute "UPDATE posts SET word_count = array_length(regexp_split_to_array(raw, ' '),1) WHERE id IN (#{post_ids.join(',')})"
|
||||||
|
post_ids = execute("SELECT id FROM posts WHERE word_count IS NULL LIMIT 500").map {|r| r['id'].to_i }
|
||||||
|
end
|
||||||
|
|
||||||
|
topic_ids = execute("SELECT id FROM topics WHERE word_count IS NULL LIMIT 500").map {|r| r['id'].to_i }
|
||||||
|
while topic_ids.length > 0
|
||||||
|
execute "UPDATE topics SET word_count = (SELECT SUM(COALESCE(posts.word_count, 0)) FROM posts WHERE posts.topic_id = topics.id) WHERE topics.id IN (#{topic_ids.join(',')})"
|
||||||
|
topic_ids = execute("SELECT id FROM topics WHERE word_count IS NULL LIMIT 500").map {|r| r['id'].to_i }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -96,6 +96,7 @@ class PostCreator
|
||||||
post.reply_to_user_id ||= Post.select(:user_id).where(topic_id: post.topic_id, post_number: post.reply_to_post_number).first.try(:user_id)
|
post.reply_to_user_id ||= Post.select(:user_id).where(topic_id: post.topic_id, post_number: post.reply_to_post_number).first.try(:user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post.word_count = post.raw.scan(/\w+/).size
|
||||||
post.post_number ||= Topic.next_post_number(post.topic_id, post.reply_to_post_number.present?)
|
post.post_number ||= Topic.next_post_number(post.topic_id, post.reply_to_post_number.present?)
|
||||||
|
|
||||||
cooking_options = post.cooking_options || {}
|
cooking_options = post.cooking_options || {}
|
||||||
|
@ -198,6 +199,7 @@ class PostCreator
|
||||||
# Update attributes on the topic - featured users and last posted.
|
# Update attributes on the topic - featured users and last posted.
|
||||||
attrs = {last_posted_at: @post.created_at, last_post_user_id: @post.user_id}
|
attrs = {last_posted_at: @post.created_at, last_post_user_id: @post.user_id}
|
||||||
attrs[:bumped_at] = @post.created_at unless @post.no_bump
|
attrs[:bumped_at] = @post.created_at unless @post.no_bump
|
||||||
|
attrs[:word_count] = (@topic.word_count || 0) + @post.word_count
|
||||||
@topic.update_attributes(attrs)
|
@topic.update_attributes(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class PostRevisor
|
||||||
revise_post
|
revise_post
|
||||||
update_category_description
|
update_category_description
|
||||||
post_process_post
|
post_process_post
|
||||||
|
update_topic_word_counts
|
||||||
@post.advance_draft_sequence
|
@post.advance_draft_sequence
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -66,8 +67,15 @@ class PostRevisor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_topic_word_counts
|
||||||
|
Topic.exec_sql("UPDATE topics SET word_count = (SELECT SUM(COALESCE(posts.word_count, 0))
|
||||||
|
FROM posts WHERE posts.topic_id = :topic_id)
|
||||||
|
WHERE topics.id = :topic_id", topic_id: @post.topic_id)
|
||||||
|
end
|
||||||
|
|
||||||
def update_post
|
def update_post
|
||||||
@post.raw = @new_raw
|
@post.raw = @new_raw
|
||||||
|
@post.word_count = @new_raw.scan(/\w+/).size
|
||||||
@post.updated_by = @user
|
@post.updated_by = @user
|
||||||
@post.last_editor_id = @user.id
|
@post.last_editor_id = @user.id
|
||||||
@post.edit_reason = @opts[:edit_reason] if @opts[:edit_reason]
|
@post.edit_reason = @opts[:edit_reason] if @opts[:edit_reason]
|
||||||
|
|
|
@ -394,5 +394,17 @@ describe PostCreator do
|
||||||
creator.errors.should be_nil
|
creator.errors.should be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "word_count" do
|
||||||
|
it "has a word count" do
|
||||||
|
creator = PostCreator.new(user, title: 'some inspired poetry for a rainy day', raw: 'mary had a little lamb, little lamb, little lamb. mary had a little lamb')
|
||||||
|
post = creator.create
|
||||||
|
post.word_count.should == 14
|
||||||
|
|
||||||
|
post.topic.reload
|
||||||
|
post.topic.word_count.should == 14
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -222,14 +222,14 @@ describe PostRevisor do
|
||||||
|
|
||||||
describe 'with a new body' do
|
describe 'with a new body' do
|
||||||
let(:changed_by) { Fabricate(:coding_horror) }
|
let(:changed_by) { Fabricate(:coding_horror) }
|
||||||
let!(:result) { subject.revise!(changed_by, 'updated body') }
|
let!(:result) { subject.revise!(changed_by, "lets update the body") }
|
||||||
|
|
||||||
it 'returns true' do
|
it 'returns true' do
|
||||||
result.should be_true
|
result.should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the body' do
|
it 'updates the body' do
|
||||||
post.raw.should == 'updated body'
|
post.raw.should == "lets update the body"
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the invalidate oneboxes attribute' do
|
it 'sets the invalidate oneboxes attribute' do
|
||||||
|
@ -252,6 +252,12 @@ describe PostRevisor do
|
||||||
post.versions.first.user.should be_present
|
post.versions.first.user.should be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "updates the word count" do
|
||||||
|
post.word_count.should == 4
|
||||||
|
post.topic.reload
|
||||||
|
post.topic.word_count.should == 4
|
||||||
|
end
|
||||||
|
|
||||||
context 'second poster posts again quickly' do
|
context 'second poster posts again quickly' do
|
||||||
before do
|
before do
|
||||||
SiteSetting.expects(:ninja_edit_window).returns(1.minute.to_i)
|
SiteSetting.expects(:ninja_edit_window).returns(1.minute.to_i)
|
||||||
|
|
Loading…
Reference in a new issue