Skip to content

Commit b945719

Browse files
committed
First stab at new user education - configurable messages that pop up on a user's first
few posts/topics.
1 parent 898efea commit b945719

15 files changed

Lines changed: 879 additions & 688 deletions

File tree

app/assets/javascripts/admin/translations.js.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//= depend_on 'en.yml'
1+
//= depend_on 'client.en.yml'
22

33
<% SimplesIdeias::I18n.assert_usable_configuration! %>
44
<% admin = SimplesIdeias::I18n.translation_segments['app/assets/javascripts/i18n/admin.en.js']

app/assets/javascripts/discourse/components/div_resizer.js.coffee

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@
3131
lastMousePos = thisMousePos
3232
size = Math.min(size, $(window).height())
3333
size = Math.max(min, size)
34-
div.height size + "px"
34+
35+
sizePx = size + "px"
36+
opts.onDrag?(sizePx)
37+
div.height(sizePx)
3538
endDrag e,opts if size < min
3639
false
3740
endDrag = (e,opts) ->
3841
$(document).unbind("mousemove", wrappedPerformDrag).unbind "mouseup", wrappedEndDrag
3942
div.removeClass('clear-transitions')
4043
div.focus()
41-
opts.resize() if opts.resize
44+
opts.resize?()
4245
div = null
4346
mousePosition = (e) ->
4447
x: e.clientX + document.documentElement.scrollLeft

app/assets/javascripts/discourse/controllers/composer_controller.js.coffee

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
22

33
needs: ['modal', 'topic']
44

5+
hasReply: false
6+
57
togglePreview: ->
68
@get('content').togglePreview()
79

@@ -20,11 +22,19 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
2022
.then (opts) =>
2123
opts = opts || {}
2224
@close()
25+
Discourse.set('currentUser.post_count', Discourse.get('currentUser.post_count') + 1)
2326
Discourse.routeTo(opts.post.get('url'))
2427
, (error) =>
2528
composer.set('disableDrafts', false)
2629
bootbox.alert error
2730

31+
checkReplyLength: ->
32+
if @present('content.reply')
33+
@set('hasReply', true)
34+
else
35+
@set('hasReply', false)
36+
37+
2838
saveDraft: ->
2939
model = @get('content')
3040
model.saveDraft() if model
@@ -40,6 +50,8 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
4050
open: (opts={}) ->
4151
opts.promise = promise = opts.promise || new RSVP.Promise
4252

53+
@set('hasReply', false)
54+
4355
unless opts.draftKey
4456
alert("composer was opened without a draft key")
4557
throw "composer opened without a proper draft key"
@@ -164,7 +176,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
164176

165177
# ESC key hit
166178
hitEsc: ->
167-
@shrink() if @get('content.composeState') == @OPEN
179+
@shrink() if @get('content.composeState') is Discourse.Composer.OPEN
168180

169181

170182
showOptions: ->

app/assets/javascripts/discourse/templates/composer.js.handlebars

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
<div class='contents'>
44

5+
<div id='new-user-education' {{bindAttr class="view.newUserEducationVisible"}}>
6+
<a href='#' {{action closeEducation target="view"}} class='close'>{{i18n ok}}</a>
7+
8+
{{{view.educationContents}}}
9+
</div>
10+
511
<div class='control'>
612
<a href='#' class='toggler' {{action toggle bubbles=false}} title='toggle'></a>
713

app/assets/javascripts/discourse/translations.js.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//= depend_on 'en.yml'
1+
//= depend_on 'client.en.yml'
22

33
<% SimplesIdeias::I18n.assert_usable_configuration! %>
44
var I18n = I18n || {};

app/assets/javascripts/discourse/views/composer_view.js.coffee

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ window.Discourse.ComposerView = window.Discourse.View.extend
1010
'content.showPreview',
1111
'content.hidePreview']
1212

13+
educationClosed: null
14+
1315
composeState: (->
1416
state = @get('content.composeState')
1517
unless state
@@ -49,28 +51,58 @@ window.Discourse.ComposerView = window.Discourse.View.extend
4951
if $wmdPreview.length > 0
5052
$wmdPreview.scrollTop($wmdPreview[0].scrollHeight)
5153

52-
5354
).observes('content.reply', 'content.hidePreview')
5455

55-
willDestroyElement: ->
56-
$('body').off 'keydown.composer'
56+
closeEducation: ->
57+
@set('educationClosed', true)
58+
false
59+
60+
fetchNewUserEducation: (->
61+
62+
if (Discourse.get('currentUser.post_count') >= Discourse.SiteSettings.educate_until_posts)
63+
@set('educationClosed', true)
64+
return
65+
66+
return unless @get('controller.hasReply')
67+
68+
@set('educationClosed', false)
69+
70+
# If visible update the text
71+
educationKey = if @get('content.creatingTopic') then 'new-topic' else 'new-reply'
72+
$.get("/education/#{educationKey}").then (result) => @set('educationContents', result)
73+
74+
).observes('controller.hasReply', 'content.creatingTopic', 'Discourse.currentUser.post_count')
75+
76+
newUserEducationVisible: (->
77+
return 'collapsed' unless @get('educationContents')
78+
return 'collapsed' unless @get('content.composeState') is Discourse.Composer.OPEN
79+
return 'collapsed' unless @present('content.reply')
80+
return 'collapsed' if @get('educationClosed')
81+
82+
return 'visible'
83+
).property('content.composeState', 'content.reply', 'educationClosed', 'educationContents')
84+
85+
moveNewUserEducation: (sizePx) ->
86+
$('#new-user-education').css('bottom', sizePx)
5787

5888
resize: (->
5989
# this still needs to wait on animations, need a clean way to do that
6090
Em.run.next null, =>
6191
replyControl = $('#reply-control')
6292
h = replyControl.height() || 0
63-
$('.topic-area').css('padding-bottom', "#{h}px")
93+
sizePx = "#{h}px"
94+
$('.topic-area').css('padding-bottom', sizePx)
95+
$('#new-user-education').css('bottom', sizePx)
6496
).observes('content.composeState')
6597

66-
didInsertElement: ->
67-
68-
# Delegate ESC to the composer
69-
$('body').on 'keydown.composer', (e) =>
70-
@get('controller').hitEsc() if e.which == 27
98+
keyUp: (e) ->
99+
controller = @get('controller')
100+
controller.checkReplyLength()
101+
controller.hitEsc() if e.which == 27
71102

103+
didInsertElement: ->
72104
replyControl = $('#reply-control')
73-
replyControl.DivResizer(resize: @resize)
105+
replyControl.DivResizer(resize: @resize, onDrag: @moveNewUserEducation)
74106
Discourse.TransitionHelper.after(replyControl, @resize)
75107

76108
click: ->

app/assets/stylesheets/application/compose.css.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,34 @@
33
@import "foundation/variables";
44
@import "foundation/mixins";
55

6+
7+
#new-user-education {
8+
9+
&.collapsed {
10+
max-height: 0;
11+
visibility: hidden;
12+
}
13+
14+
&.visible {
15+
max-height: 1000px;
16+
visibility: visible;
17+
}
18+
19+
p {
20+
margin: 0 0 10px 0;
21+
}
22+
23+
a.close {
24+
float: right;
25+
}
26+
27+
background-color: lighten($yellow, 40%);
28+
border: 1px solid $yellow;
29+
padding: 10px;
30+
width: 600px;
31+
position: absolute;
32+
}
33+
634
#reply-control {
735
.toggle-preview, .saving-draft {
836
position: absolute;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class EducationController < ApplicationController
2+
3+
before_filter :ensure_logged_in
4+
5+
def show
6+
raise Discourse::InvalidAccess.new unless params[:id] =~ /^[a-z0-9\-\_]+$/
7+
raise Discourse::NotFound.new unless I18n.t(:education).include?(params[:id].to_sym)
8+
9+
education_posts_text = I18n.t('education.until_posts', count: SiteSetting.educate_until_posts)
10+
11+
markdown_content = MultisiteI18n.t("education.#{params[:id]}",
12+
site_name: SiteSetting.title,
13+
education_posts_text: education_posts_text)
14+
render text: PrettyText.cook(markdown_content)
15+
end
16+
17+
end

app/controllers/posts_controller.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ def replies
116116
render_serialized(post.replies, PostSerializer)
117117
end
118118

119+
# Returns the "you're creating a post education"
120+
def education_text
121+
122+
end
119123

120124
def bookmark
121125
post = find_post_from_params

app/models/site_setting.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ class SiteSetting < ActiveRecord::Base
138138

139139
setting(:new_user_period_days, 2)
140140

141+
client_setting(:educate_until_posts, 2)
142+
141143
def self.call_discourse_hub?
142144
self.enforce_global_nicknames? and self.discourse_org_access_key.present?
143145
end

0 commit comments

Comments
 (0)