mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-30 10:58:31 -05:00
Merge branch 'master' into vagrant-chef
This commit is contained in:
commit
9e198c3ac5
235 changed files with 3209 additions and 1173 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Before You Start
|
||||
|
||||
Anyone wishing to contribute to the **[Discourse/Discourse](https://github.com/discourse/discourse)** project **MUST read & sign the [Electronic Discourse Forums Contribution License Agreement](https://docs.google.com/a/discourse.org/spreadsheet/viewform?formkey=dGUwejFfbDhDYXR4bVFMRG1TUENqLWc6MQ)**. The Discourse team is legally prevented from accepting any pull requests from users who have not signed the CLA first.
|
||||
Anyone wishing to contribute to the **[Discourse/Discourse](https://github.com/discourse/discourse)** project **MUST read & sign the [Electronic Discourse Forums Contribution License Agreement](http://www.discourse.org/cla)**. The Discourse team is legally prevented from accepting any pull requests from users who have not signed the CLA first.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
|
@ -20,7 +20,7 @@ Anyone wishing to contribute to the **[Discourse/Discourse](https://github.com/d
|
|||
|
||||
## Requesting New Features
|
||||
|
||||
1. Do not submit a feature request on GitHub; all feature requests on GitHub will be closed. Instead, visit the Discourse development forums, and search for the "Feature Request" category, which will filter a list of outstanding requests. Review this list for similar feature requests. It's possible somebody has already asked for this feature or provided a pull request that we're still discussing.
|
||||
1. Do not submit a feature request on GitHub; all feature requests on GitHub will be closed. Instead, visit the **[Discourse development forums](http://meta.discourse.org/category/feature)**, and search for the "Feature" category, which will filter a list of outstanding requests. Review this list for similar feature requests. It's possible somebody has already asked for this feature or provided a pull request that we're still discussing.
|
||||
|
||||
2. Provide a clear and detailed explanation of the feature you want and why it's important to add. The feature must apply to a wide array of users of Discourse; for smaller, more targeted "one-off" features, you might consider writing a plugin for Discourse. You may also want to provide us with some advance documentation on the feature, which will help the community to better understand where it will fit.
|
||||
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -1,5 +1,6 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'slim' # required for sidekiq-web
|
||||
gem 'redis'
|
||||
gem 'redis-rails'
|
||||
gem 'hiredis'
|
||||
|
|
|
@ -344,7 +344,6 @@ GEM
|
|||
temple (0.4.1)
|
||||
terminal-notifier-guard (1.5.3)
|
||||
terminal-table (1.4.5)
|
||||
test-unit (2.5.4)
|
||||
therubyracer (0.11.3)
|
||||
libv8 (~> 3.11.8.12)
|
||||
ref
|
||||
|
@ -391,7 +390,6 @@ DEPENDENCIES
|
|||
guard-jasmine
|
||||
guard-rspec
|
||||
guard-spork
|
||||
haml
|
||||
has_ip_address
|
||||
hiredis
|
||||
hpricot
|
||||
|
@ -432,9 +430,8 @@ DEPENDENCIES
|
|||
simple_handlebars_rails!
|
||||
simplecov
|
||||
sinatra
|
||||
slim (<= 1.3.0)
|
||||
slim
|
||||
terminal-notifier-guard
|
||||
test-unit
|
||||
therubyracer
|
||||
thin
|
||||
turbo-sprockets-rails3
|
||||
|
|
|
@ -6,7 +6,7 @@ window.Discourse.AdminEmailLogsController = Ember.ArrayController.extend Discour
|
|||
|
||||
sendTestEmail: ->
|
||||
@set('sentTestEmail', false)
|
||||
$.ajax
|
||||
$.ajax
|
||||
url: '/admin/email_logs/test',
|
||||
type: 'POST'
|
||||
data:
|
||||
|
@ -14,4 +14,4 @@ window.Discourse.AdminEmailLogsController = Ember.ArrayController.extend Discour
|
|||
success: =>
|
||||
@set('sentTestEmail', true)
|
||||
false
|
||||
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ window.Discourse.AdminSiteSettingsController = Ember.ArrayController.extend Disc
|
|||
true
|
||||
).property('filter', 'content.@each', 'onlyOverridden')
|
||||
|
||||
|
||||
|
||||
resetDefault: (setting) ->
|
||||
setting.set('value', setting.get('default'))
|
||||
setting.save()
|
||||
|
||||
save: (setting) -> setting.save()
|
||||
|
||||
cancel: (setting) -> setting.resetValue()
|
||||
cancel: (setting) -> setting.resetValue()
|
||||
|
|
|
@ -12,8 +12,8 @@ window.Discourse.AdminUsersListController = Ember.ArrayController.extend Discour
|
|||
filterUsers: Discourse.debounce(->
|
||||
@refreshUsers()
|
||||
,250).observes('username')
|
||||
|
||||
orderChanged: (->
|
||||
|
||||
orderChanged: (->
|
||||
@refreshUsers()
|
||||
).observes('query')
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ window.Discourse.AdminUser = Discourse.Model.extend
|
|||
canBan: ( ->
|
||||
!@admin && !@moderator
|
||||
).property('admin','moderator')
|
||||
|
||||
|
||||
banDuration: (->
|
||||
banned_at = Date.create(@banned_at)
|
||||
banned_till = Date.create(@banned_till)
|
||||
|
||||
"#{banned_at.short()} - #{banned_till.short()}"
|
||||
|
||||
|
||||
).property('banned_till', 'banned_at')
|
||||
|
||||
ban: ->
|
||||
|
@ -64,7 +64,7 @@ window.Discourse.AdminUser = Discourse.Model.extend
|
|||
error = Em.String.i18n('admin.user.ban_failed', error: "http: #{e.status} - #{e.body}")
|
||||
bootbox.alert error
|
||||
return
|
||||
|
||||
|
||||
unban: ->
|
||||
$.ajax "/admin/users/#{@id}/unban",
|
||||
type: 'PUT'
|
||||
|
@ -75,7 +75,7 @@ window.Discourse.AdminUser = Discourse.Model.extend
|
|||
error = Em.String.i18n('admin.user.unban_failed', error: "http: #{e.status} - #{e.body}")
|
||||
bootbox.alert error
|
||||
return
|
||||
|
||||
|
||||
impersonate: ->
|
||||
$.ajax "/admin/impersonate"
|
||||
type: 'POST'
|
||||
|
|
|
@ -11,7 +11,7 @@ window.Discourse.EmailLog.reopenClass
|
|||
$.ajax
|
||||
url: "/admin/email_logs.json"
|
||||
data: {filter: filter}
|
||||
success: (logs) ->
|
||||
success: (logs) ->
|
||||
logs.each (log) -> result.pushObject(Discourse.EmailLog.create(log))
|
||||
result
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ window.Discourse.FlaggedPost = Discourse.Post.extend
|
|||
message: a.message
|
||||
r
|
||||
).property()
|
||||
|
||||
|
||||
lastFlagged: (->
|
||||
@post_actions[0].created_at
|
||||
).property()
|
||||
|
|
|
@ -45,7 +45,7 @@ window.Discourse.SiteCustomization = Discourse.Model.extend
|
|||
data:
|
||||
site_customization: data
|
||||
type: if @id then 'PUT' else 'POST'
|
||||
|
||||
|
||||
delete: ->
|
||||
return unless @id
|
||||
$.ajax
|
||||
|
|
|
@ -23,19 +23,19 @@ window.Discourse.SiteSetting = Discourse.Model.extend Discourse.Presence,
|
|||
|
||||
save: ->
|
||||
|
||||
# Update the setting
|
||||
# Update the setting
|
||||
$.ajax "/admin/site_settings/#{@get('setting')}",
|
||||
data:
|
||||
value: @get('value')
|
||||
type: 'PUT'
|
||||
success: => @set('originalValue', @get('value'))
|
||||
|
||||
|
||||
|
||||
window.Discourse.SiteSetting.reopenClass
|
||||
findAll: ->
|
||||
result = Em.A()
|
||||
findAll: ->
|
||||
result = Em.A()
|
||||
$.get "/admin/site_settings", (settings) ->
|
||||
settings.each (s) ->
|
||||
settings.each (s) ->
|
||||
s.originalValue = s.value
|
||||
result.pushObject(Discourse.SiteSetting.create(s))
|
||||
result
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminCustomizeRoute = Discourse.Route.extend
|
||||
model: -> Discourse.SiteCustomization.findAll()
|
||||
model: -> Discourse.SiteCustomization.findAll()
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminEmailLogsRoute = Discourse.Route.extend
|
||||
model: -> Discourse.EmailLog.findAll()
|
||||
model: -> Discourse.EmailLog.findAll()
|
||||
|
|
|
@ -3,4 +3,4 @@ Discourse.AdminFlagsActiveRoute = Discourse.Route.extend
|
|||
setupController: (controller, model) ->
|
||||
c = @controllerFor('adminFlags')
|
||||
c.set('content', model)
|
||||
c.set('query', 'active')
|
||||
c.set('query', 'active')
|
||||
|
|
|
@ -3,4 +3,4 @@ Discourse.AdminFlagsOldRoute = Discourse.Route.extend
|
|||
setupController: (controller, model) ->
|
||||
c = @controllerFor('adminFlags')
|
||||
c.set('content', model)
|
||||
c.set('query', 'old')
|
||||
c.set('query', 'old')
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminUserRoute = Discourse.Route.extend
|
||||
model: (params) -> Discourse.AdminUser.find(params.username)
|
||||
model: (params) -> Discourse.AdminUser.find(params.username)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminUsersListActiveRoute = Discourse.Route.extend
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('active')
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('active')
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminUsersListNewRoute = Discourse.Route.extend
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('new')
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('new')
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminUsersListNewRoute = Discourse.Route.extend
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('pending')
|
||||
setupController: (c) -> @controllerFor('adminUsersList').show('pending')
|
||||
|
|
|
@ -6,7 +6,7 @@ Discourse.AceEditorView = window.Discourse.View.extend
|
|||
if @editor && !@skipContentChangeEvent
|
||||
@editor.getSession().setValue(@get('content'))
|
||||
).observes('content')
|
||||
|
||||
|
||||
render: (buffer) ->
|
||||
buffer.push("<div class='ace'>")
|
||||
buffer.push(Handlebars.Utils.escapeExpression(@get('content'))) if @get('content')
|
||||
|
|
|
@ -10,7 +10,7 @@ Discourse.AdminCustomizeView = window.Discourse.View.extend
|
|||
headerActive: (->
|
||||
@get('selected') == 'header'
|
||||
).property('selected')
|
||||
|
||||
|
||||
stylesheetActive: (->
|
||||
@get('selected') == 'stylesheet'
|
||||
).property('selected')
|
||||
|
@ -26,7 +26,7 @@ Discourse.AdminCustomizeView = window.Discourse.View.extend
|
|||
Mousetrap.bindGlobal ['meta+s', 'ctrl+s'], =>
|
||||
@get('controller').save()
|
||||
return false
|
||||
|
||||
|
||||
willDestroyElement: ->
|
||||
Mousetrap.unbindGlobal('meta+s','ctrl+s')
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminDashboardView = window.Discourse.View.extend
|
||||
templateName: 'admin/templates/dashboard'
|
||||
templateName: 'admin/templates/dashboard'
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminEmailLogsView = window.Discourse.View.extend
|
||||
templateName: 'admin/templates/email_logs'
|
||||
templateName: 'admin/templates/email_logs'
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminSiteSettingsView = window.Discourse.View.extend
|
||||
templateName: 'admin/templates/site_settings'
|
||||
templateName: 'admin/templates/site_settings'
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminUserView = window.Discourse.View.extend
|
||||
templateName: 'admin/templates/user'
|
||||
templateName: 'admin/templates/user'
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Discourse.AdminView = window.Discourse.View.extend
|
||||
templateName: 'admin/templates/admin'
|
||||
templateName: 'admin/templates/admin'
|
||||
|
|
|
@ -23,7 +23,7 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
title += "#{@get('title')} - " if @get('title')
|
||||
title += Discourse.SiteSettings.title
|
||||
$('title').text(title)
|
||||
|
||||
|
||||
title = ("(*) " + title) if !@get('hasFocus') && @get('notify')
|
||||
|
||||
# chrome bug workaround see: http://stackoverflow.com/questions/2952384/changing-the-window-title-when-focussing-the-window-doesnt-work-in-chrome
|
||||
|
@ -43,12 +43,12 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
|
||||
bus.callbackInterval = Discourse.SiteSettings.anon_polling_interval
|
||||
bus.enableLongPolling = false
|
||||
|
||||
|
||||
user = @get('currentUser')
|
||||
if user
|
||||
bus.callbackInterval = Discourse.SiteSettings.polling_interval
|
||||
bus.enableLongPolling = true
|
||||
|
||||
|
||||
if user.admin
|
||||
bus.subscribe "/flagged_counts", (data) ->
|
||||
user.set('site_flagged_posts_count', data.total)
|
||||
|
@ -90,13 +90,13 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
|
||||
|
||||
# Be wary of looking up the router. In this case, we have links in our
|
||||
# HTML, say form compiled markdown posts, that need to be routed.
|
||||
router = Discourse.__container__.lookup('router:main')
|
||||
router.router.updateURL(path)
|
||||
# HTML, say form compiled markdown posts, that need to be routed.
|
||||
router = Discourse.__container__.lookup('router:main')
|
||||
router.router.updateURL(path)
|
||||
router.handleURL(path)
|
||||
|
||||
|
||||
# Scroll to the top if we're not replacing state
|
||||
|
||||
|
||||
|
||||
# The classes of buttons to show on a post
|
||||
postButtons: (->
|
||||
|
@ -171,7 +171,7 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
before: (data,owner, args) ->
|
||||
if owner
|
||||
window.probes.clear()
|
||||
|
||||
|
||||
after: (data, owner, args) ->
|
||||
if owner && data.time > 10
|
||||
f = (name,data) ->
|
||||
|
@ -187,7 +187,7 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
for n,v of window.probes
|
||||
continue if n == name || v.time < 1
|
||||
ary.push(k: n, v: v)
|
||||
|
||||
|
||||
ary.sortBy((item) -> if item.v && item.v.time then -item.v.time else 0).each (item)->
|
||||
console.log output if output = f("#{item.k}", item.v)
|
||||
console?.groupEnd?()
|
||||
|
@ -219,9 +219,9 @@ window.Discourse = Ember.Application.createWithMixins
|
|||
Discourse.MessageBus.start()
|
||||
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus)
|
||||
Discourse.insertProbes()
|
||||
|
||||
|
||||
# subscribe to any site customizations that are loaded
|
||||
|
||||
# subscribe to any site customizations that are loaded
|
||||
$('link.custom-css').each ->
|
||||
split = @href.split("/")
|
||||
id = split[split.length-1].split(".css")[0]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
me = @
|
||||
div = null
|
||||
|
||||
# input is handled differently
|
||||
# input is handled differently
|
||||
isInput = @[0].tagName == "INPUT"
|
||||
|
||||
inputSelectedItems = []
|
||||
|
@ -98,7 +98,7 @@
|
|||
|
||||
div.css(left: "-1000px")
|
||||
me.parent().append(div)
|
||||
|
||||
|
||||
mePos = me.position()
|
||||
|
||||
borderTop = parseInt(me.css('border-top-width')) || 0
|
||||
|
@ -143,11 +143,11 @@
|
|||
|
||||
$(@).keypress (e) ->
|
||||
|
||||
|
||||
|
||||
if !options.key
|
||||
return
|
||||
|
||||
# keep hunting backwards till you hit a
|
||||
|
||||
# keep hunting backwards till you hit a
|
||||
|
||||
if e.which == options.key.charCodeAt(0)
|
||||
caretPosition = Discourse.Utilities.caretPosition(me[0])
|
||||
|
@ -165,11 +165,11 @@
|
|||
return if e.which == 16
|
||||
|
||||
if completeStart == null && e.which == 8 && options.key #backspace
|
||||
|
||||
|
||||
c = Discourse.Utilities.caretPosition(me[0])
|
||||
next = me[0].value[c]
|
||||
nextIsGood = next == undefined || /\s/.test(next)
|
||||
|
||||
|
||||
c-=1
|
||||
initial = c
|
||||
|
||||
|
@ -186,7 +186,7 @@
|
|||
term = me[0].value.substring(c+1, initial)
|
||||
options.dataSource term, updateAutoComplete
|
||||
return true
|
||||
|
||||
|
||||
prevIsGood = /[a-zA-Z\.]/.test(prev)
|
||||
|
||||
|
||||
|
@ -250,6 +250,6 @@
|
|||
term += "," unless e.which == 8 # backspace
|
||||
options.dataSource term, updateAutoComplete
|
||||
return true
|
||||
|
||||
|
||||
|
||||
|
||||
)(jQuery)
|
||||
|
|
|
@ -17,7 +17,7 @@ Discourse.BBCode =
|
|||
withArgs:
|
||||
"url": (_, href, title) -> "<a href=\"#{href}\">#{title}</a>"
|
||||
"email": (_, address, title) -> "<a href=\"mailto:#{address}\">#{title}</a>"
|
||||
"color": (_, color, content) ->
|
||||
"color": (_, color, content) ->
|
||||
return content unless /^(\#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)|(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)$/.test(color)
|
||||
"<span style=\"color: #{color}\">#{content}</span>"
|
||||
|
||||
|
@ -28,10 +28,10 @@ Discourse.BBCode =
|
|||
"i": (_, content) -> "<i>#{content}</i>"
|
||||
"u": (_, content) -> "<u>#{content}</u>"
|
||||
"s": (_, content) -> "<s>#{content}</s>"
|
||||
"spoiler": (_, content) -> "<span style='background-color: #000'>#{content}</span>"
|
||||
"spoiler": (_, content) -> "<span style='background-color: #000'>#{content}</span>"
|
||||
|
||||
withArgs:
|
||||
"size": (_, size, content) -> "<span style=\"font-size: #{size}px\">#{content}</span>"
|
||||
"size": (_, size, content) -> "<span style=\"font-size: #{size}px\">#{content}</span>"
|
||||
|
||||
# For sane environments that support CSS
|
||||
default:
|
||||
|
@ -58,10 +58,10 @@ Discourse.BBCode =
|
|||
Object.keys Discourse.BBCode.replacers, (name, rules) ->
|
||||
parsed = result[name] = []
|
||||
|
||||
Object.keys Object.merge(Discourse.BBCode.replacers.base.withoutArgs, rules.withoutArgs), (tag, val) ->
|
||||
Object.keys Object.merge(Discourse.BBCode.replacers.base.withoutArgs, rules.withoutArgs), (tag, val) ->
|
||||
parsed.push(regexp: RegExp("\\[#{tag}\\]([\\s\\S]*?)\\[\\/#{tag}\\]", "igm"), fn: val)
|
||||
|
||||
Object.keys Object.merge(Discourse.BBCode.replacers.base.withArgs, rules.withArgs), (tag, val) ->
|
||||
Object.keys Object.merge(Discourse.BBCode.replacers.base.withArgs, rules.withArgs), (tag, val) ->
|
||||
parsed.push(regexp: RegExp("\\[#{tag}=?(.+?)\\\]([\\s\\S]*?)\\[\\/#{tag}\\]", "igm"), fn: val)
|
||||
|
||||
@parsed = result
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# caret position in textarea ... very hacky ... sorry
|
||||
(($) ->
|
||||
|
||||
|
||||
# http://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea
|
||||
getCaret = (el) ->
|
||||
if el.selectionStart
|
||||
|
@ -15,7 +15,7 @@
|
|||
rc.setEndPoint "EndToStart", re
|
||||
return rc.text.length
|
||||
0
|
||||
|
||||
|
||||
clone = null
|
||||
$.fn.caretPosition = (options) ->
|
||||
|
||||
|
@ -66,15 +66,15 @@
|
|||
before = pos - 1
|
||||
after = pos
|
||||
insertSpaceAfterBefore = false
|
||||
|
||||
# if before and after are \n insert a space
|
||||
|
||||
# if before and after are \n insert a space
|
||||
insertSpaceAfterBefore = true if val[before] is "\n" and val[after] is "\n"
|
||||
guard = (v) ->
|
||||
buf = v.replace(/</g,"<")
|
||||
buf = buf.replace(/>/g,">")
|
||||
buf = buf.replace(/[ ]/g, "​ ​")
|
||||
buf.replace(/\n/g,"<br />")
|
||||
|
||||
|
||||
|
||||
makeCursor = (pos, klass, color) ->
|
||||
l = val.substring(pos, pos + 1)
|
||||
|
@ -95,7 +95,7 @@
|
|||
pos.left = pos.left + letter.width() if letter.hasClass("before")
|
||||
pPos = p.offset()
|
||||
#clone.hide().remove()
|
||||
|
||||
|
||||
left: pos.left - pPos.left
|
||||
top: (pos.top - pPos.top) - clone.scrollTop()
|
||||
) jQuery
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# We use this object to keep track of click counts.
|
||||
# We use this object to keep track of click counts.
|
||||
window.Discourse.ClickTrack =
|
||||
|
||||
# Pass the event of the click here and we'll do the magic!
|
||||
|
@ -28,7 +28,7 @@ window.Discourse.ClickTrack =
|
|||
userId = $article.data('user-id') unless userId
|
||||
|
||||
ownLink = userId and (userId is Discourse.get('currentUser.id'))
|
||||
|
||||
|
||||
# Build a Redirect URL
|
||||
trackingUrl = "/clicks/track?url=" + encodeURIComponent(href)
|
||||
trackingUrl += "&post_id=" + encodeURI(postId) if postId and (not $a.data('ignore-post-id'))
|
||||
|
@ -44,9 +44,9 @@ window.Discourse.ClickTrack =
|
|||
# If they right clicked, change the destination href
|
||||
if e.which is 3
|
||||
destination = if Discourse.SiteSettings.track_external_right_clicks then trackingUrl else href
|
||||
$a.attr('href', destination)
|
||||
$a.attr('href', destination)
|
||||
return true
|
||||
|
||||
|
||||
# if they want to open in a new tab, do an AJAX request
|
||||
if (e.metaKey || e.ctrlKey || e.which is 2)
|
||||
$.get "/clicks/track", url: href, post_id: postId, topic_id: topicId, redirect: false
|
||||
|
|
|
@ -42,12 +42,12 @@
|
|||
mousePosition = (e) ->
|
||||
x: e.clientX + document.documentElement.scrollLeft
|
||||
y: e.clientY + document.documentElement.scrollTop
|
||||
|
||||
|
||||
$.fn.DivResizer = (opts) ->
|
||||
@each ->
|
||||
div = $(this)
|
||||
return if (div.hasClass("processed"))
|
||||
|
||||
|
||||
div.addClass("processed")
|
||||
staticOffset = null
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ class Discourse.Eyeline
|
|||
|
||||
return true unless markSeen
|
||||
|
||||
# If you hit the bottom we mark all the elements as seen. Otherwise, just the first one
|
||||
# If you hit the bottom we mark all the elements as seen. Otherwise, just the first one
|
||||
unless atBottom
|
||||
@trigger('saw', detail: $elem)
|
||||
@trigger('sawTop', detail: $elem) if i == 0
|
||||
@trigger('saw', detail: $elem)
|
||||
@trigger('sawTop', detail: $elem) if i == 0
|
||||
return false
|
||||
|
||||
@trigger('sawTop', detail: $elem) if i == 0
|
||||
|
@ -56,9 +56,9 @@ class Discourse.Eyeline
|
|||
# Call this when we know aren't loading any more elements. Mark the rest
|
||||
# as seen
|
||||
flushRest: ->
|
||||
$(@selector).each (i, elem) =>
|
||||
$(@selector).each (i, elem) =>
|
||||
$elem = $(elem)
|
||||
@trigger('saw', detail: $elem)
|
||||
@trigger('saw', detail: $elem)
|
||||
|
||||
|
||||
RSVP.EventTarget.mixin(Discourse.Eyeline.prototype)
|
||||
RSVP.EventTarget.mixin(Discourse.Eyeline.prototype)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
window.Discourse.KeyValueStore = (->
|
||||
initialized = false
|
||||
context = ""
|
||||
|
||||
|
||||
init: (ctx,messageBus) ->
|
||||
initialized = true
|
||||
context = ctx
|
||||
|
@ -17,7 +17,7 @@ window.Discourse.KeyValueStore = (->
|
|||
localStorage.removeItem(k) if k.substring(0, context.length) == context
|
||||
i--
|
||||
return true
|
||||
|
||||
|
||||
remove: (key)->
|
||||
localStorage.removeItem(context + key)
|
||||
|
||||
|
|
|
@ -45,11 +45,11 @@ window.Discourse.MessageBus = ( ->
|
|||
if callbacks.length == 0
|
||||
setTimeout poll, 500
|
||||
return
|
||||
|
||||
|
||||
data = {}
|
||||
callbacks.each (c)->
|
||||
data[c.channel] = if c.last_id == undefined then -1 else c.last_id
|
||||
|
||||
|
||||
gotData = false
|
||||
|
||||
@longPoll = $.ajax "/message-bus/#{clientId}/poll?#{if isHidden() || !@enableLongPolling then "dlp=t" else ""}",
|
||||
|
@ -98,7 +98,7 @@ window.Discourse.MessageBus = ( ->
|
|||
subscribe: (channel,func,lastId)->
|
||||
callbacks.push {channel:channel, func:func, last_id: lastId}
|
||||
@longPoll.abort() if @longPoll
|
||||
|
||||
|
||||
# Unsubscribe from a channel
|
||||
unsubscribe: (channel) ->
|
||||
# TODO proper globbing
|
||||
|
|
|
@ -9,7 +9,7 @@ window.Discourse.PagedownEditor = Ember.ContainerView.extend
|
|||
@pushObject Em.View.create(elementId: 'wmd-button-bar')
|
||||
@pushObject Em.TextArea.create(valueBinding: 'parentView.value', elementId: 'wmd-input')
|
||||
@pushObject Em.View.createWithMixins Discourse.Presence,
|
||||
elementId: 'wmd-preview',
|
||||
elementId: 'wmd-preview',
|
||||
classNameBindings: [':preview', 'hidden']
|
||||
|
||||
hidden: (->
|
||||
|
|
|
@ -76,7 +76,7 @@ window.Discourse.ScreenTrack = Ember.Object.extend
|
|||
if (highestSeenByTopic[topicId] || 0) < @highestSeen
|
||||
highestSeenByTopic[topicId] = @highestSeen
|
||||
|
||||
|
||||
|
||||
unless Object.isEmpty(newTimings)
|
||||
$.ajax '/topics/timings'
|
||||
data:
|
||||
|
@ -93,7 +93,7 @@ window.Discourse.ScreenTrack = Ember.Object.extend
|
|||
@lastFlush = 0
|
||||
|
||||
tick: ->
|
||||
|
||||
|
||||
# If the user hasn't scrolled the browser in a long time, stop tracking time read
|
||||
sinceScrolled = new Date().getTime() - @lastScrolled
|
||||
if sinceScrolled > @PAUSE_UNLESS_SCROLLED
|
||||
|
@ -116,7 +116,7 @@ window.Discourse.ScreenTrack = Ember.Object.extend
|
|||
|
||||
Object.keys @timings, (id) =>
|
||||
$element = $(id)
|
||||
|
||||
|
||||
if ($element.length == 1)
|
||||
elemTop = $element.offset().top
|
||||
elemBottom = elemTop + $element.height()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Helper object for syntax highlighting. Uses highlight.js which is loaded
|
||||
# Helper object for syntax highlighting. Uses highlight.js which is loaded
|
||||
# on demand.
|
||||
window.Discourse.SyntaxHighlighting =
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# CSS transitions are a PITA, often we need to queue some js after a transition, this helper ensures
|
||||
# CSS transitions are a PITA, often we need to queue some js after a transition, this helper ensures
|
||||
# it happens after the transition
|
||||
#
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ window.Discourse.UserSearch =
|
|||
limit = options.limit || 5
|
||||
|
||||
throw "missing callback" unless callback
|
||||
|
||||
#TODO site setting for allowed regex in username ?
|
||||
|
||||
#TODO site setting for allowed regex in username ?
|
||||
if term.match(/[^a-zA-Z0-9\_\.]/)
|
||||
callback([])
|
||||
return true
|
||||
|
|
|
@ -25,9 +25,9 @@ Discourse.Utilities =
|
|||
return "" unless username
|
||||
size = Discourse.Utilities.translateSize(size)
|
||||
rawSize = (size * (window.devicePixelRatio || 1)).toFixed()
|
||||
|
||||
|
||||
return template.replace(/\{size\}/g, rawSize) if template
|
||||
|
||||
|
||||
"/users/#{username.toLowerCase()}/avatar/#{rawSize}?__ws=#{encodeURIComponent(Discourse.BaseUrl || "")}"
|
||||
|
||||
avatarImg: (options)->
|
||||
|
@ -63,7 +63,7 @@ Discourse.Utilities =
|
|||
caretPosition: (el) ->
|
||||
|
||||
return el.selectionStart if el.selectionStart
|
||||
|
||||
|
||||
if document.selection
|
||||
el.focus()
|
||||
r = document.selection.createRange()
|
||||
|
@ -121,7 +121,7 @@ Discourse.Utilities =
|
|||
result = text.replace /^`{3}(?:(.*$)\n)?([\s\S]*?)^`{3}/gm, (wholeMatch,m1,m2) ->
|
||||
escaped = Handlebars.Utils.escapeExpression(m2)
|
||||
"<pre><code class='#{m1 || 'lang-auto'}'>#{escaped}</code></pre>"
|
||||
|
||||
|
||||
converter.hooks.chain "postConversion", (text) ->
|
||||
return "" unless text
|
||||
# don't to mention voodoo in pres
|
||||
|
|
|
@ -3,4 +3,4 @@ window.Discourse.ApplicationController = Ember.Controller.extend
|
|||
needs: ['modal']
|
||||
|
||||
showLogin: ->
|
||||
@get('controllers.modal')?.show(Discourse.LoginView.create())
|
||||
@get('controllers.modal')?.show(Discourse.LoginView.create())
|
||||
|
|
|
@ -24,18 +24,18 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
, (error) =>
|
||||
composer.set('disableDrafts', false)
|
||||
bootbox.alert error
|
||||
|
||||
|
||||
saveDraft: ->
|
||||
model = @get('content')
|
||||
model.saveDraft() if model
|
||||
|
||||
# Open the reply view
|
||||
#
|
||||
#
|
||||
# opts:
|
||||
# action - The action we're performing: edit, reply or createTopic
|
||||
# action - The action we're performing: edit, reply or createTopic
|
||||
# post - The post we're replying to, if present
|
||||
# topic - The topic we're replying to, if present
|
||||
# quote - If we're opening a reply from a quote, the quote we're making
|
||||
# quote - If we're opening a reply from a quote, the quote we're making
|
||||
#
|
||||
open: (opts={}) ->
|
||||
opts.promise = promise = opts.promise || new RSVP.Promise
|
||||
|
@ -51,7 +51,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
controller: @
|
||||
view.appendTo($('#main'))
|
||||
@set('view', view)
|
||||
# the next runloop is too soon, need to get the control rendered and then
|
||||
# the next runloop is too soon, need to get the control rendered and then
|
||||
# we need to change stuff, otherwise css animations don't kick in
|
||||
Em.run.next =>
|
||||
Em.run.next =>
|
||||
|
@ -87,7 +87,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
if opts.draft
|
||||
composer = Discourse.Composer.loadDraft(opts.draftKey, opts.draftSequence, opts.draft)
|
||||
composer?.set('topic', opts.topic)
|
||||
|
||||
|
||||
composer = composer || Discourse.Composer.open(opts)
|
||||
|
||||
@set('content', composer)
|
||||
|
@ -119,7 +119,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
else
|
||||
fail() if typeof fail == "function"
|
||||
else
|
||||
# it is possible there is some sort of crazy draft with no body ... just give up on it
|
||||
# it is possible there is some sort of crazy draft with no body ... just give up on it
|
||||
@destroyDraft()
|
||||
@close()
|
||||
success() if typeof success == "function"
|
||||
|
@ -133,7 +133,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
|
||||
shrink: ->
|
||||
if @get('content.reply') == @get('content.originalText') then @close() else @collapse()
|
||||
|
||||
|
||||
collapse: ->
|
||||
@saveDraft()
|
||||
@set('content.composeState', Discourse.Composer.DRAFT)
|
||||
|
@ -166,7 +166,7 @@ window.Discourse.ComposerController = Ember.Controller.extend Discourse.Presence
|
|||
# ESC key hit
|
||||
hitEsc: ->
|
||||
@shrink() if @get('content.composeState') == @OPEN
|
||||
|
||||
|
||||
|
||||
showOptions: ->
|
||||
@get('controllers.modal')?.show(Discourse.ArchetypeOptionsModalView.create(archetype: @get('content.archetype'), metaData: @get('content.metaData')))
|
||||
|
|
|
@ -1 +1 @@
|
|||
Discourse.Controller = Ember.Controller.extend(Discourse.Presence)
|
||||
Discourse.Controller = Ember.Controller.extend(Discourse.Presence)
|
||||
|
|
|
@ -4,4 +4,4 @@ Discourse.HeaderController = Ember.Controller.extend Discourse.Presence,
|
|||
|
||||
toggleStar: ->
|
||||
@get('topic')?.toggleStar()
|
||||
false
|
||||
false
|
||||
|
|
|
@ -14,7 +14,7 @@ Discourse.ListCategoriesController = Ember.ObjectController.extend Discourse.Pre
|
|||
editCategory: (category) ->
|
||||
@get('controllers.modal').show(Discourse.EditCategoryView.create(category: category))
|
||||
false
|
||||
|
||||
|
||||
canEdit: (->
|
||||
u = Discourse.get('currentUser')
|
||||
u && u.admin
|
||||
|
|
|
@ -9,7 +9,7 @@ Discourse.ListTopicsController = Ember.ObjectController.extend
|
|||
if previousChannel = @get('previousChannel')
|
||||
Discourse.MessageBus.unsubscribe "/#{previousChannel}"
|
||||
@set('previousChannel', null)
|
||||
|
||||
|
||||
filterMode = @get('controllers.list.filterMode')
|
||||
return unless filterMode
|
||||
|
||||
|
@ -19,7 +19,7 @@ Discourse.ListTopicsController = Ember.ObjectController.extend
|
|||
@set('previousChannel', channel)
|
||||
|
||||
).observes('controllers.list.filterMode')
|
||||
|
||||
|
||||
draftLoaded: (->
|
||||
draft = @get('content.draft')
|
||||
if(draft)
|
||||
|
|
|
@ -36,7 +36,7 @@ Discourse.PreferencesController = Ember.ObjectController.extend Discourse.Presen
|
|||
@get('content').save (result) =>
|
||||
@set('saving', false)
|
||||
if result
|
||||
@set('content.bio_cooked', Discourse.Utilities.cook(@get('content.bio_raw')))
|
||||
@set('content.bio_cooked', Discourse.Utilities.cook(@get('content.bio_raw')))
|
||||
@set('saved', true)
|
||||
else
|
||||
alert 'failed'
|
||||
|
@ -51,4 +51,4 @@ Discourse.PreferencesController = Ember.ObjectController.extend Discourse.Presen
|
|||
@set('passwordProgress','(generating email)')
|
||||
@get('content').changePassword (message)=>
|
||||
@set('changePasswordProgress', false)
|
||||
@set('passwordProgress', "(#{message})")
|
||||
@set('passwordProgress', "(#{message})")
|
||||
|
|
|
@ -29,7 +29,7 @@ Discourse.PreferencesEmailController = Ember.ObjectController.extend Discourse.P
|
|||
@set('saving', true)
|
||||
@get('content').changeEmail(@get('newEmail')).then =>
|
||||
@set('success', true)
|
||||
, =>
|
||||
, =>
|
||||
# Error
|
||||
@set('error', true)
|
||||
@set('saving', false)
|
||||
|
|
|
@ -34,7 +34,7 @@ Discourse.PreferencesUsernameController = Ember.ObjectController.extend Discours
|
|||
@set('saving', true)
|
||||
@get('content').changeUsername(@get('newUsername')).then =>
|
||||
window.location = "/users/#{@get('newUsername').toLowerCase()}/preferences"
|
||||
, =>
|
||||
, =>
|
||||
# Error
|
||||
@set('error', true)
|
||||
@set('saving', false)
|
||||
|
|
|
@ -20,7 +20,7 @@ Discourse.QuoteButtonController = Discourse.Controller.extend
|
|||
selectText: (e) ->
|
||||
return unless Discourse.get('currentUser')
|
||||
return unless @get('controllers.topic.content.can_create_post')
|
||||
|
||||
|
||||
selectedText = Discourse.Utilities.selectedText()
|
||||
return if @get('buffer') == selectedText
|
||||
return if @get('lastSelected') == selectedText
|
||||
|
@ -51,20 +51,20 @@ Discourse.QuoteButtonController = Discourse.Controller.extend
|
|||
post: post
|
||||
action: Discourse.Composer.REPLY
|
||||
draftKey: @get('post.topic.draft_key')
|
||||
|
||||
|
||||
# If the composer is associated with a different post, we don't change it.
|
||||
if composerPost = composerController.get('content.post')
|
||||
composerOpts.post = composerPost if (composerPost.get('id') != @get('post.id'))
|
||||
|
||||
buffer = @get('buffer')
|
||||
quotedText = Discourse.BBCode.buildQuoteBBCode(post, buffer)
|
||||
|
||||
|
||||
if composerController.wouldLoseChanges()
|
||||
composerController.appendText(quotedText)
|
||||
else
|
||||
composerController.open(composerOpts).then =>
|
||||
composerController.appendText(quotedText)
|
||||
|
||||
|
||||
@set('buffer', '')
|
||||
|
||||
false
|
||||
|
|
|
@ -8,7 +8,7 @@ Discourse.ShareController = Ember.Controller.extend
|
|||
@set('link', url)
|
||||
false
|
||||
|
||||
# Close the share controller
|
||||
# Close the share controller
|
||||
close: ->
|
||||
@set('link', '')
|
||||
false
|
||||
|
|
|
@ -9,13 +9,13 @@ Discourse.StaticController = Ember.Controller.extend
|
|||
$preloaded = $("noscript[data-path=\"#{path}\"]")
|
||||
if $preloaded.length
|
||||
text = $preloaded.text()# + ""
|
||||
text = text.replace(/\<header[\s\S]*\<\/header\>/, '')
|
||||
text = text.replace(/\<header[\s\S]*\<\/header\>/, '')
|
||||
@set('content', text)
|
||||
else
|
||||
else
|
||||
jQuery.ajax
|
||||
url: "#{path}.json"
|
||||
success: (result) =>
|
||||
@set('content', result)
|
||||
|
||||
|
||||
Discourse.StaticController.reopenClass(pages: ['faq', 'tos', 'privacy'])
|
||||
Discourse.StaticController.reopenClass(pages: ['faq', 'tos', 'privacy'])
|
||||
|
|
|
@ -3,4 +3,4 @@ Discourse.TopicAdminMenuController = Ember.ObjectController.extend
|
|||
visible: false
|
||||
|
||||
show: -> @set('visible', true)
|
||||
hide: -> @set('visible', false)
|
||||
hide: -> @set('visible', false)
|
||||
|
|
|
@ -49,7 +49,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
unless p.get('can_delete')
|
||||
canDelete = false
|
||||
return false
|
||||
|
||||
|
||||
canDelete
|
||||
).property('selectedPosts')
|
||||
|
||||
|
@ -58,7 +58,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
unless @get('multiSelect')
|
||||
if posts = @get('content.posts')
|
||||
posts.forEach (p) -> p.set('selected', false)
|
||||
|
||||
|
||||
).observes('multiSelect')
|
||||
|
||||
hideProgress: (->
|
||||
|
@ -95,7 +95,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
|
||||
replyAsNewTopic: (post) ->
|
||||
composerController = @get('controllers.composer')
|
||||
#TODO shut down topic draft cleanly if it exists ...
|
||||
#TODO shut down topic draft cleanly if it exists ...
|
||||
promise = composerController.open
|
||||
action: Discourse.Composer.CREATE_TOPIC
|
||||
draftKey: Discourse.Composer.REPLY_AS_NEW_TOPIC_KEY
|
||||
|
@ -103,7 +103,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
postUrl = "#{location.protocol}//#{location.host}#{post.get('url')}"
|
||||
postLink = "[#{@get('title')}](#{postUrl})"
|
||||
promise.then ->
|
||||
Discourse.Post.loadQuote(post.get('id')).then (q) ->
|
||||
Discourse.Post.loadQuote(post.get('id')).then (q) ->
|
||||
composerController.appendText("#{Em.String.i18n("post.continue_discussion", postLink: postLink)}\n\n#{q}")
|
||||
|
||||
# Topic related
|
||||
|
@ -145,14 +145,14 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
return unless topic
|
||||
posts = topic.get('posts')
|
||||
return unless posts
|
||||
posts.clear()
|
||||
|
||||
posts.clear()
|
||||
|
||||
@set('content.loaded', false)
|
||||
Discourse.Topic.find(@get('content.id'), @get('postFilters')).then (result) =>
|
||||
first = result.posts.first()
|
||||
@set('currentPost', first.post_number) if first
|
||||
$('#topic-progress .solid').data('progress', false)
|
||||
result.posts.each (p) =>
|
||||
result.posts.each (p) =>
|
||||
posts.pushObject(Discourse.Post.create(p, topic))
|
||||
@set('content.loaded', true)
|
||||
|
||||
|
@ -163,7 +163,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
|
||||
@get('content').delete =>
|
||||
@set('message', "The topic has been deleted")
|
||||
@set('loaded', false)
|
||||
@set('loaded', false)
|
||||
|
||||
toggleVisibility: ->
|
||||
@get('content').toggleStatus('visible')
|
||||
|
@ -226,7 +226,7 @@ Discourse.TopicController = Ember.ObjectController.extend Discourse.Presence,
|
|||
quoteController = @get('controllers.quoteButton')
|
||||
quotedText = Discourse.BBCode.buildQuoteBBCode(quoteController.get('post'), quoteController.get('buffer'))
|
||||
quoteController.set('buffer', '')
|
||||
|
||||
|
||||
if (composerController.get('content.topic.id') == post.get('topic.id') and composerController.get('content.action') == Discourse.Composer.REPLY)
|
||||
composerController.set('content.post', post)
|
||||
composerController.set('content.composeState', Discourse.Composer.OPEN)
|
||||
|
|
|
@ -2,4 +2,4 @@ Discourse.UserInvitedController = Ember.ObjectController.extend
|
|||
|
||||
rescind: (invite) ->
|
||||
invite.rescind()
|
||||
false
|
||||
false
|
||||
|
|
|
@ -2,7 +2,7 @@ Discourse.UserPrivateMessagesController = Ember.ObjectController.extend
|
|||
|
||||
editPreferences: ->
|
||||
Discourse.routeTo("/users/#{@get('content.username_lower')}/preferences")
|
||||
|
||||
|
||||
composePrivateMessage: ->
|
||||
composerController = Discourse.get('router.composerController')
|
||||
composerController.open
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
Handlebars.registerHelper 'breakUp', (property, options) ->
|
||||
prop = Ember.Handlebars.get(this, property, options)
|
||||
return "" unless prop
|
||||
|
||||
|
||||
tokens = prop.match(RegExp(".{1,14}",'g'))
|
||||
return prop if tokens.length == 1
|
||||
|
||||
result = ""
|
||||
result = ""
|
||||
tokens.each (token, index) ->
|
||||
result += token
|
||||
|
||||
if token.indexOf(' ') == -1 and (index < tokens.length - 1)
|
||||
result += "- "
|
||||
result += "- "
|
||||
|
||||
result
|
||||
|
||||
|
@ -28,9 +28,9 @@ Handlebars.registerHelper 'categoryLink', (property, options) ->
|
|||
|
||||
Handlebars.registerHelper 'titledLinkTo', (name, object) ->
|
||||
options = [].slice.call(arguments, -1)[0]
|
||||
|
||||
if options.hash.titleKey
|
||||
options.hash.title = Em.String.i18n(options.hash.titleKey)
|
||||
|
||||
if options.hash.titleKey
|
||||
options.hash.title = Em.String.i18n(options.hash.titleKey)
|
||||
|
||||
if arguments.length is 3
|
||||
Ember.Handlebars.helpers.linkTo.call(this, name, object, options)
|
||||
|
@ -43,7 +43,7 @@ Handlebars.registerHelper 'shortenUrl', (property, options) ->
|
|||
|
||||
# Remove trailing slash if it's a top level URL
|
||||
url = url.replace(/\/$/, '') if url.match(/\//g).length == 3
|
||||
|
||||
|
||||
url = url.replace(/^https?:\/\//, '')
|
||||
url = url.replace(/^www\./, '')
|
||||
url.truncate(80)
|
||||
|
@ -68,7 +68,7 @@ Handlebars.registerHelper 'avatar', (user, options) ->
|
|||
title: Em.get(user, 'title') || Em.get(user, 'description')
|
||||
avatarTemplate: Ember.get(user, 'avatar_template') || options.hash.avatarTemplate
|
||||
)
|
||||
|
||||
|
||||
Handlebars.registerHelper 'unboundDate', (property, options) ->
|
||||
dt = new Date(Ember.Handlebars.get(this, property, options))
|
||||
month = Date.SugarMethods.getLocale.method().months[12 + dt.getMonth()]
|
||||
|
@ -104,7 +104,7 @@ Handlebars.registerHelper 'date', (property, options) ->
|
|||
|
||||
val = Ember.Handlebars.get(this, property, options)
|
||||
return new Handlebars.SafeString("—") unless val
|
||||
|
||||
|
||||
dt = new Date(val)
|
||||
|
||||
fullReadable = dt.format("{d} {Mon}, {yyyy} {hh}:{mm}")
|
||||
|
@ -122,7 +122,7 @@ Handlebars.registerHelper 'date', (property, options) ->
|
|||
return "" unless humanized
|
||||
displayDate = humanized
|
||||
displayDate = displayDate.replace(' ago', '') unless leaveAgo
|
||||
|
||||
|
||||
new Handlebars.SafeString("<span class='date' title='#{fullReadable}'>#{displayDate}</span>")
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ window.Discourse.Presence = Em.Mixin.create
|
|||
when "string"
|
||||
return prop.trim().isBlank()
|
||||
when "object"
|
||||
return Object.isEmpty(prop)
|
||||
return Object.isEmpty(prop)
|
||||
false
|
||||
|
||||
present: (name) -> not @blank(name)
|
||||
|
||||
present: (name) -> not @blank(name)
|
||||
|
|
|
@ -29,7 +29,7 @@ window.Discourse.ActionSummary = Em.Object.extend Discourse.Presence,
|
|||
@set('can_undo', true)
|
||||
|
||||
#TODO: mark all other flag types as acted
|
||||
|
||||
|
||||
# Add ourselves to the users who liked it if present
|
||||
@users.pushObject(Discourse.get('currentUser')) if @present('users')
|
||||
|
||||
|
@ -45,7 +45,7 @@ window.Discourse.ActionSummary = Em.Object.extend Discourse.Presence,
|
|||
@removeAction()
|
||||
errors = jQuery.parseJSON(error.responseText).errors
|
||||
bootbox.alert(errors[0])
|
||||
|
||||
|
||||
|
||||
# Undo this action
|
||||
undo: ->
|
||||
|
@ -57,7 +57,7 @@ window.Discourse.ActionSummary = Em.Object.extend Discourse.Presence,
|
|||
type: 'DELETE'
|
||||
data:
|
||||
post_action_type_id: @get('id')
|
||||
|
||||
|
||||
clearFlags: ->
|
||||
$.ajax
|
||||
url: "/post_actions/clear_flags"
|
||||
|
|
|
@ -18,14 +18,14 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
val = (Discourse.KeyValueStore.get('composer.showPreview') or 'true')
|
||||
@set('showPreview', val is 'true')
|
||||
@set 'archetypeId', Discourse.get('site.default_archetype')
|
||||
|
||||
|
||||
archetypesBinding: 'Discourse.site.archetypes'
|
||||
|
||||
|
||||
creatingTopic: (-> @get('action') == CREATE_TOPIC ).property('action')
|
||||
creatingPrivateMessage: (-> @get('action') == PRIVATE_MESSAGE ).property('action')
|
||||
editingPost: (-> @get('action') == EDIT).property('action')
|
||||
viewOpen: (-> @get('composeState') == OPEN ).property('composeState')
|
||||
|
||||
|
||||
archetype: (->
|
||||
@get('archetypes').findProperty('id', @get('archetypeId'))
|
||||
).property('archetypeId')
|
||||
|
@ -44,7 +44,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
togglePreview: ->
|
||||
@toggleProperty('showPreview')
|
||||
Discourse.KeyValueStore.set(key: 'showPreview', value: @get('showPreview'))
|
||||
|
||||
|
||||
# Import a quote from the post
|
||||
importQuote: ->
|
||||
post = @get('post')
|
||||
|
@ -95,7 +95,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
).property('showPreview')
|
||||
|
||||
hidePreview: (-> not @get('showPreview') ).property('showPreview')
|
||||
|
||||
|
||||
# Whether to disable the post button
|
||||
cantSubmitPost: (->
|
||||
|
||||
|
@ -113,7 +113,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
|
||||
false
|
||||
).property('reply', 'title', 'creatingTopic', 'loading')
|
||||
|
||||
|
||||
# The text for the save button
|
||||
saveText: (->
|
||||
switch @get('action')
|
||||
|
@ -129,20 +129,20 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
return Em.empty(Em.keys(@get('metaData')))
|
||||
).property('metaData')
|
||||
|
||||
|
||||
|
||||
wouldLoseChanges: ()->
|
||||
@get('reply') != @get('originalText') # TODO title check as well
|
||||
|
||||
# Open a composer
|
||||
#
|
||||
#
|
||||
# opts:
|
||||
# action - The action we're performing: edit, reply or createTopic
|
||||
# action - The action we're performing: edit, reply or createTopic
|
||||
# post - The post we're replying to, if present
|
||||
# topic - The topic we're replying to, if present
|
||||
# quote - If we're opening a reply from a quote, the quote we're making
|
||||
# quote - If we're opening a reply from a quote, the quote we're making
|
||||
#
|
||||
open: (opts={}) ->
|
||||
|
||||
|
||||
@set('loading', false)
|
||||
|
||||
topicId = opts.topic.get('id') if opts.topic
|
||||
|
@ -151,7 +151,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
opts.tested = true
|
||||
@cancel(=> @open(opts))
|
||||
return
|
||||
|
||||
|
||||
@set 'draftKey', opts.draftKey
|
||||
@set 'draftSequence', opts.draftSequence
|
||||
throw 'draft key is required' unless opts.draftKey
|
||||
|
@ -177,7 +177,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
Discourse.Post.load opts.postId, (result) =>
|
||||
@set('post', result)
|
||||
@set('loading', false)
|
||||
|
||||
|
||||
# If we are editing a post, load it.
|
||||
if opts.action == EDIT and opts.post
|
||||
@set 'title', @get('topic.title')
|
||||
|
@ -186,7 +186,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
@set 'reply', result.get('raw')
|
||||
@set('originalText', @get('reply'))
|
||||
@set('loading', false)
|
||||
|
||||
|
||||
if opts.title
|
||||
@set('title', opts.title)
|
||||
if opts.draft
|
||||
|
@ -196,7 +196,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
|
||||
false
|
||||
|
||||
|
||||
|
||||
save: (opts)->
|
||||
if @get('editingPost')
|
||||
@editPost(opts)
|
||||
|
@ -230,7 +230,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
postNumber = post.get('post_number')
|
||||
posts.each (p,i)->
|
||||
idx = i if p.get('post_number') == postNumber
|
||||
|
||||
|
||||
if idx > -1
|
||||
savedPost.set('topic', @get('topic'))
|
||||
posts.replace(idx, 1, [savedPost])
|
||||
|
@ -244,7 +244,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
@set('composeState', OPEN)
|
||||
|
||||
promise
|
||||
|
||||
|
||||
|
||||
# Create a new Post
|
||||
createPost: (opts)->
|
||||
|
@ -274,9 +274,9 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
|
||||
addedToStream = false
|
||||
|
||||
# If we're in a topic, we can append the post instantly.
|
||||
# If we're in a topic, we can append the post instantly.
|
||||
if topic
|
||||
# Increase the reply count
|
||||
# Increase the reply count
|
||||
if post
|
||||
post.set('reply_count', (post.get('reply_count') || 0) + 1)
|
||||
|
||||
|
@ -299,17 +299,17 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
|
||||
# If we're near the end of the topic, load new posts
|
||||
lastPost = topic.posts.last()
|
||||
|
||||
|
||||
if lastPost
|
||||
diff = topic.get('highest_post_number') - lastPost.get('post_number')
|
||||
|
||||
# If the new post is within a threshold of the end of the topic,
|
||||
# If the new post is within a threshold of the end of the topic,
|
||||
# add it and scroll there instead of adding the link.
|
||||
if diff < 5
|
||||
createdPost.set('scrollToAfterInsert', createdPost.get('post_number'))
|
||||
topic.pushPosts([createdPost])
|
||||
addedToStream = true
|
||||
|
||||
|
||||
# Save callback
|
||||
createdPost.save (result) =>
|
||||
addedPost = false
|
||||
|
@ -323,7 +323,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
# We created a new topic, let's show it.
|
||||
@set('composeState', CLOSED)
|
||||
saving = false
|
||||
|
||||
|
||||
@set('reply', '')
|
||||
@set('createdPost', createdPost)
|
||||
|
||||
|
@ -354,7 +354,7 @@ window.Discourse.Composer = Discourse.Model.extend
|
|||
archetypeId: @get('archetypeId')
|
||||
metaData: @get('metaData')
|
||||
usernames: @get('targetUsernames')
|
||||
|
||||
|
||||
@set('draftStatus', Em.String.i18n('composer.saving_draft_tip'))
|
||||
Discourse.Draft.save(@get('draftKey'), @get('draftSequence'), data)
|
||||
.then(
|
||||
|
@ -417,6 +417,6 @@ Discourse.Composer.reopenClass
|
|||
EDIT: EDIT
|
||||
|
||||
# Draft key
|
||||
REPLY_AS_NEW_TOPIC_KEY: REPLY_AS_NEW_TOPIC_KEY
|
||||
REPLY_AS_NEW_TOPIC_KEY: REPLY_AS_NEW_TOPIC_KEY
|
||||
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ Discourse.Draft.reopenClass
|
|||
success: (data) =>
|
||||
promise.resolve(data)
|
||||
promise
|
||||
|
||||
|
||||
getLocal: (key, current) ->
|
||||
return current
|
||||
|
||||
# disabling for now to see if it helps with siracusa issue.
|
||||
|
||||
# disabling for now to see if it helps with siracusa issue.
|
||||
|
||||
local = Discourse.KeyValueStore.get("draft_#{key}")
|
||||
if !current || (local && local.length > current.length)
|
||||
|
@ -46,6 +46,6 @@ Discourse.Draft.reopenClass
|
|||
# Discourse.KeyValueStore.set(key: "draft_#{key}", value: data)
|
||||
promise.reject()
|
||||
promise
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
window.Discourse.InviteList = Discourse.Model.extend Discourse.Presence,
|
||||
|
||||
empty: (->
|
||||
|
||||
empty: (->
|
||||
return @blank('pending') and @blank('redeemed')
|
||||
).property('pending.@each', 'redeemed.@each')
|
||||
|
||||
window.Discourse.InviteList.reopenClass
|
||||
window.Discourse.InviteList.reopenClass
|
||||
|
||||
findInvitedBy: (user) ->
|
||||
promise = new RSVP.Promise()
|
||||
|
@ -16,4 +16,4 @@ window.Discourse.InviteList.reopenClass
|
|||
invitedList.redeemed = (invitedList.redeemed.map (i) -> Discourse.Invite.create(i)) if invitedList.redeemed
|
||||
invitedList.user = user
|
||||
promise.resolve(Discourse.InviteList.create(invitedList))
|
||||
promise
|
||||
promise
|
||||
|
|
|
@ -5,7 +5,7 @@ Discourse.Mention = (->
|
|||
cache = (name, valid) ->
|
||||
localCache[name] = valid
|
||||
return
|
||||
|
||||
|
||||
lookupCache = (name) ->
|
||||
localCache[name]
|
||||
|
||||
|
@ -19,7 +19,7 @@ Discourse.Mention = (->
|
|||
cache(name,r.valid)
|
||||
callback(r.valid)
|
||||
return true
|
||||
|
||||
|
||||
load = (e) ->
|
||||
$elem = $(e)
|
||||
return if $elem.data('mention-tested')
|
||||
|
@ -38,4 +38,4 @@ Discourse.Mention = (->
|
|||
lookup: lookup
|
||||
lookupCache: lookupCache
|
||||
)()
|
||||
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ window.Discourse.Model = Ember.Object.extend
|
|||
col = @get(k)
|
||||
v.each (obj) -> col.pushObject(builder.create(obj))
|
||||
else
|
||||
@set(k, v)
|
||||
@set(k, v)
|
||||
|
||||
|
||||
|
||||
window.Discourse.Model.reopenClass
|
||||
|
||||
# Given an array of values, return them in a hash
|
||||
|
@ -33,4 +33,4 @@ window.Discourse.Model.reopenClass
|
|||
collection.each (c) ->
|
||||
obj = klass.create(c)
|
||||
retval[c.id] = obj
|
||||
retval
|
||||
retval
|
||||
|
|
|
@ -27,11 +27,11 @@ Discourse.NavItem.reopenClass
|
|||
countSummary = opts["countSummary"]
|
||||
loggedOn = opts["loggedOn"]
|
||||
hasCategories = opts["hasCategories"]
|
||||
|
||||
|
||||
split = text.split(",")
|
||||
name = split[0]
|
||||
|
||||
testName = name.split("/")[0] # to handle category ...
|
||||
testName = name.split("/")[0] # to handle category ...
|
||||
|
||||
return null if !loggedOn && !validAnon.contains(testName)
|
||||
return null if !hasCategories && testName == "categories"
|
||||
|
|
|
@ -20,7 +20,7 @@ window.Discourse.Notification = Discourse.Model.extend Discourse.Presence,
|
|||
|
||||
|
||||
window.Discourse.Notification.reopenClass
|
||||
|
||||
|
||||
create: (obj) ->
|
||||
result = @_super(obj)
|
||||
result.set('data', Em.Object.create(obj.data)) if obj.data
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Discourse.Onebox = (->
|
||||
# for now it only stores in a var, in future we can change it so it uses localStorage,
|
||||
# for now it only stores in a var, in future we can change it so it uses localStorage,
|
||||
# trouble with localStorage is that expire semantics need some thinking
|
||||
|
||||
#cacheKey = "__onebox__"
|
||||
|
@ -9,9 +9,9 @@ Discourse.Onebox = (->
|
|||
localCache[url] = contents
|
||||
|
||||
#if localStorage && localStorage.setItem
|
||||
# localStorage.setItme
|
||||
# localStorage.setItme
|
||||
null
|
||||
|
||||
|
||||
lookupCache = (url) ->
|
||||
localCache[url]
|
||||
|
||||
|
@ -25,7 +25,7 @@ Discourse.Onebox = (->
|
|||
cache(url,html)
|
||||
callback(html)
|
||||
return true
|
||||
|
||||
|
||||
load = (e, refresh=false) ->
|
||||
|
||||
url = e.href
|
||||
|
@ -45,4 +45,4 @@ Discourse.Onebox = (->
|
|||
lookup: lookup
|
||||
lookupCache: lookupCache
|
||||
)()
|
||||
|
||||
|
||||
|
|
|
@ -52,14 +52,14 @@ Discourse.Topic = Discourse.Model.extend Discourse.Presence,
|
|||
).observes('posts.@each','posts')
|
||||
|
||||
# The amount of new posts to display. It might be different than what the server
|
||||
# tells us if we are still asynchronously flushing our "recently read" data.
|
||||
# tells us if we are still asynchronously flushing our "recently read" data.
|
||||
# So take what the browser has seen into consideration.
|
||||
displayNewPosts: (->
|
||||
|
||||
if highestSeen = Discourse.get('highestSeenByTopic')[@get('id')]
|
||||
delta = highestSeen - @get('last_read_post_number')
|
||||
if delta > 0
|
||||
result = (@get('new_posts') - delta)
|
||||
result = (@get('new_posts') - delta)
|
||||
result = 0 if result < 0
|
||||
return result
|
||||
|
||||
|
@ -78,9 +78,9 @@ Discourse.Topic = Discourse.Model.extend Discourse.Presence,
|
|||
ageCold: (->
|
||||
return unless lastPost = @get('last_posted_at')
|
||||
return unless createdAt = @get('created_at')
|
||||
|
||||
|
||||
daysSinceEpoch = (dt) ->
|
||||
# 1000 * 60 * 60 * 24 = days since epoch
|
||||
# 1000 * 60 * 60 * 24 = days since epoch
|
||||
dt.getTime() / 86400000
|
||||
|
||||
# Show heat on age
|
||||
|
@ -169,12 +169,12 @@ Discourse.Topic = Discourse.Model.extend Discourse.Presence,
|
|||
bestOf: opts.bestOf
|
||||
trackVisit: opts.trackVisit
|
||||
.then (result) =>
|
||||
|
||||
|
||||
# If loading the topic succeeded...
|
||||
# Update the slug if different
|
||||
@set('slug', result.slug) if result.slug
|
||||
|
||||
# If we want to scroll to a post that doesn't exist, just pop them to the closest
|
||||
# If we want to scroll to a post that doesn't exist, just pop them to the closest
|
||||
# one instead. This is likely happening due to a deleted post.
|
||||
opts.nearPost = parseInt(opts.nearPost)
|
||||
closestPostNumber = 0
|
||||
|
@ -189,7 +189,7 @@ Discourse.Topic = Discourse.Model.extend Discourse.Presence,
|
|||
|
||||
|
||||
@get('participants').clear() if @get('participants')
|
||||
|
||||
|
||||
@set('suggested_topics', Em.A()) if result.suggested_topics
|
||||
@mergeAttributes result, suggested_topics: Discourse.Topic
|
||||
@set('posts', Em.A())
|
||||
|
@ -237,7 +237,7 @@ Discourse.Topic = Discourse.Model.extend Discourse.Presence,
|
|||
url: "/t/#{@get('id')}/notifications"
|
||||
type: 'POST'
|
||||
data: {notification_level: v}
|
||||
|
||||
|
||||
# use to add post to topics protecting from dupes
|
||||
pushPosts: (newPosts)->
|
||||
map = {}
|
||||
|
@ -257,13 +257,13 @@ window.Discourse.Topic.reopenClass
|
|||
MUTE: 0
|
||||
|
||||
# Load a topic, but accepts a set of filters
|
||||
#
|
||||
#
|
||||
# options:
|
||||
# onLoad - the callback after the topic is loaded
|
||||
find: (topicId, opts) ->
|
||||
url = "/t/#{topicId}"
|
||||
url += "/#{opts.nearPost}" if opts.nearPost
|
||||
|
||||
|
||||
data = {}
|
||||
data.posts_after = opts.postsAfter if opts.postsAfter
|
||||
data.posts_before = opts.postsBefore if opts.postsBefore
|
||||
|
@ -276,7 +276,7 @@ window.Discourse.Topic.reopenClass
|
|||
|
||||
# Add the best of filter if we have it
|
||||
data.best_of = true if opts.bestOf == true
|
||||
|
||||
|
||||
# Check the preload store. If not, load it via JSON
|
||||
promise = new RSVP.Promise()
|
||||
PreloadStore.get("topic_#{topicId}", -> jQuery.getJSON url + ".json", data).then (result) ->
|
||||
|
@ -286,7 +286,7 @@ window.Discourse.Topic.reopenClass
|
|||
, (result) -> promise.reject(result)
|
||||
|
||||
promise
|
||||
|
||||
|
||||
# Create a topic from posts
|
||||
movePosts: (topicId, title, postIds) ->
|
||||
$.ajax "/t/#{topicId}/move-posts",
|
||||
|
|
|
@ -2,7 +2,7 @@ window.Discourse.TopicList = Discourse.Model.extend
|
|||
|
||||
emptyListTip: (->
|
||||
return null unless @get('loaded')
|
||||
|
||||
|
||||
t = @get('topics')
|
||||
return null if t && t.length > 0
|
||||
|
||||
|
@ -32,7 +32,7 @@ window.Discourse.TopicList = Discourse.Model.extend
|
|||
|
||||
insert: (json) ->
|
||||
newTopic = Discourse.TopicList.decodeTopic(json)
|
||||
|
||||
|
||||
# New Topics are always unseen
|
||||
newTopic.set('unseen', true)
|
||||
|
||||
|
@ -75,7 +75,7 @@ window.Discourse.TopicList.reopenClass
|
|||
url = "/#{filter}.json"
|
||||
if menuItem.filters && menuItem.filters.length > 0
|
||||
url += "?exclude_category=" + menuItem.filters[0].substring(1)
|
||||
|
||||
|
||||
if list = Discourse.get('transient.topicsList')
|
||||
if (list.get('filter') is filter) and window.location.pathname.indexOf('more') > 0
|
||||
promise = new RSVP.Promise()
|
||||
|
|
|
@ -26,11 +26,11 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
username_lower:(->
|
||||
@get('username').toLowerCase()
|
||||
).property('username')
|
||||
|
||||
|
||||
trustLevel: (->
|
||||
Discourse.get('site.trust_levels').findProperty('id', @get('trust_level'))
|
||||
).property('trust_level')
|
||||
|
||||
|
||||
changeUsername: (newUsername) ->
|
||||
$.ajax
|
||||
url: "/users/#{@get('username_lower')}/preferences/username"
|
||||
|
@ -41,7 +41,7 @@ window.Discourse.User = Discourse.Model.extend Discourse.Presence,
|
|||
$.ajax
|
||||
url: "/users/#{@get('username_lower')}/preferences/email"
|
||||
type: 'PUT'
|
||||
data: {email: email}
|
||||
data: {email: email}
|
||||
|
||||
copy: (deep) ->
|
||||
Discourse.User.create(@getProperties(Ember.keys(@)))
|
||||
|
@ -164,7 +164,7 @@ window.Discourse.User.reopenClass
|
|||
if s.action_type == k
|
||||
g[k] = s
|
||||
s.count = c
|
||||
|
||||
|
||||
g[s.action_type] = s unless found
|
||||
|
||||
stats.map((s)->
|
||||
|
|
|
@ -2,4 +2,4 @@ window.Discourse.ApplicationRoute = Discourse.Route.extend
|
|||
setupController: (controller) ->
|
||||
Discourse.set('site', Discourse.Site.create(PreloadStore.getStatic('site')))
|
||||
currentUser = PreloadStore.getStatic('currentUser')
|
||||
Discourse.set('currentUser', Discourse.User.create(currentUser)) if currentUser
|
||||
Discourse.set('currentUser', Discourse.User.create(currentUser)) if currentUser
|
||||
|
|
|
@ -6,7 +6,7 @@ Discourse.buildRoutes ->
|
|||
@route 'bestOf', path: '/best_of'
|
||||
|
||||
# Generate static page routes
|
||||
router = @
|
||||
router = @
|
||||
Discourse.StaticController.pages.forEach (p) -> router.route(p, path: "/#{p}")
|
||||
|
||||
@route 'faq', path: '/faq'
|
||||
|
@ -24,10 +24,10 @@ Discourse.buildRoutes ->
|
|||
router.route 'categories', path: '/categories'
|
||||
router.route 'category', path: '/category/:slug/more'
|
||||
router.route 'category', path: '/category/:slug'
|
||||
|
||||
|
||||
@resource 'user', path: '/users/:username', ->
|
||||
@route 'activity', path: '/'
|
||||
|
||||
|
||||
@resource 'preferences', path: '/preferences', ->
|
||||
@route 'username', path: '/username'
|
||||
@route 'email', path: '/email'
|
||||
|
|
|
@ -18,8 +18,8 @@ window.Discourse.Route = Em.Route.extend
|
|||
# Hide any searches
|
||||
if search = router.get('searchController')
|
||||
search.close()
|
||||
|
||||
# get rid of "save as draft stuff"
|
||||
|
||||
# get rid of "save as draft stuff"
|
||||
composerController = Discourse.get('router.composerController')
|
||||
composerController.closeIfCollapsed() if composerController
|
||||
|
||||
|
|
|
@ -19,5 +19,5 @@ window.Discourse.FilteredListRoute = Discourse.Route.extend
|
|||
|
||||
Discourse.ListController.filters.each (filter) ->
|
||||
window.Discourse["List#{filter.capitalize()}Route"] = Discourse.FilteredListRoute.extend(filter: filter)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -10,4 +10,4 @@ window.Discourse.ListCategoriesRoute = Discourse.Route.extend
|
|||
@render 'listCategories', into: 'list', outlet: 'listView', controller: 'listCategories'
|
||||
listController.set('canCreateCategory', categoryList.get('can_create_category'))
|
||||
listController.set('category', null)
|
||||
@controllerFor('listCategories').set('content', categoryList)
|
||||
@controllerFor('listCategories').set('content', categoryList)
|
||||
|
|
|
@ -7,4 +7,4 @@ window.Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend
|
|||
listController.load("category/#{model.slug}").then (topicList) =>
|
||||
listController.set('canCreateTopic', topicList.get('can_create_topic'))
|
||||
listController.set('category', Discourse.Category.create(name: model.slug))
|
||||
@controllerFor('listTopics').set('content', topicList)
|
||||
@controllerFor('listTopics').set('content', topicList)
|
||||
|
|
|
@ -2,4 +2,4 @@ window.Discourse.PreferencesEmailRoute = Discourse.Route.extend
|
|||
renderTemplate: ->
|
||||
@render into: 'user', outlet: 'userOutlet'
|
||||
setupController: (controller) ->
|
||||
controller.set('content', @controllerFor('user').get('content'))
|
||||
controller.set('content', @controllerFor('user').get('content'))
|
||||
|
|
|
@ -3,4 +3,4 @@ window.Discourse.PreferencesRoute = Discourse.Route.extend
|
|||
@render 'preferences', into: 'user', outlet: 'userOutlet', controller: 'preferences'
|
||||
|
||||
setupController: (controller) ->
|
||||
controller.set('content', @controllerFor('user').get('content'))
|
||||
controller.set('content', @controllerFor('user').get('content'))
|
||||
|
|
|
@ -4,4 +4,4 @@ window.Discourse.PreferencesUsernameRoute = Discourse.Route.extend
|
|||
setupController: (controller) ->
|
||||
user = @controllerFor('user').get('content')
|
||||
controller.set('content', user)
|
||||
controller.set('newUsername', user.get('username'))
|
||||
controller.set('newUsername', user.get('username'))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Discourse.StaticController.pages.forEach (page) ->
|
||||
window.Discourse["#{page.capitalize()}Route"] = Discourse.Route.extend
|
||||
renderTemplate: -> @render 'static'
|
||||
setupController: -> @controllerFor('static').loadPath("/#{page}")
|
||||
renderTemplate: -> @render 'static'
|
||||
setupController: -> @controllerFor('static').loadPath("/#{page}")
|
||||
|
|
|
@ -4,4 +4,4 @@ window.Discourse.TopicFromParamsRoute = Discourse.Route.extend
|
|||
params.trackVisit = true
|
||||
topicController = @controllerFor('topic')
|
||||
topicController.cancelFilter()
|
||||
@modelFor('topic').loadPosts(params)
|
||||
@modelFor('topic').loadPosts(params)
|
||||
|
|
|
@ -18,4 +18,4 @@ window.Discourse.TopicRoute = Discourse.Route.extend
|
|||
setupController: (controller, model) ->
|
||||
controller.set('showExtraHeaderInfo', false)
|
||||
headerController = @controllerFor('header')
|
||||
headerController?.set('topic', model)
|
||||
headerController?.set('topic', model)
|
||||
|
|
|
@ -5,4 +5,4 @@ window.Discourse.UserActivityRoute = Discourse.Route.extend
|
|||
setupController: (controller) ->
|
||||
userController = @controllerFor('user')
|
||||
userController.set('filter', null) # clear filter
|
||||
controller.set('content', userController.get('content'))
|
||||
controller.set('content', userController.get('content'))
|
||||
|
|
|
@ -4,4 +4,4 @@ window.Discourse.UserInvitedRoute = Discourse.Route.extend
|
|||
|
||||
setupController: (controller) ->
|
||||
Discourse.InviteList.findInvitedBy(@controllerFor('user').get('content')).then (invited) =>
|
||||
controller.set('content', invited)
|
||||
controller.set('content', invited)
|
||||
|
|
|
@ -5,7 +5,7 @@ window.Discourse.UserPrivateMessagesRoute = Discourse.Route.extend
|
|||
user = @controllerFor('user').get('content')
|
||||
controller.set('content', user)
|
||||
user.filterStream(13)
|
||||
|
||||
|
||||
Discourse.Draft.get('new_private_message').then (data)=>
|
||||
if data.draft
|
||||
@controllerFor('composer').open
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
window.Discourse.UserRoute = Discourse.Route.extend
|
||||
model: (params) -> Discourse.User.find(params.username)
|
||||
serialize: (params) -> username: Em.get(params, 'username').toLowerCase()
|
||||
serialize: (params) -> username: Em.get(params, 'username').toLowerCase()
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
window.Discourse.ArchetypeOptionsModalView = window.Discourse.ModalBodyView.extend
|
||||
templateName: 'modal/archetype_options'
|
||||
title: Em.String.i18n('topic.options')
|
||||
title: Em.String.i18n('topic.options')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Discourse.AutoSizedTextView = Ember.View.extend
|
||||
render: (buffer)->
|
||||
null
|
||||
|
||||
|
||||
didInsertElement: (e) ->
|
||||
me = @$()
|
||||
me.text(@get('content'))
|
||||
|
@ -13,6 +13,6 @@ Discourse.AutoSizedTextView = Ember.View.extend
|
|||
lh -=1
|
||||
me.css("font-size", "#{fontSize}px")
|
||||
me.css("line-height", "#{lh}px")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,4 +5,4 @@ window.Discourse.ComboboxViewCategory = Discourse.ComboboxView.extend
|
|||
|
||||
template: (text, templateData) ->
|
||||
return text unless templateData.color
|
||||
"<span class='badge-category' style='background-color: ##{templateData.color}'>#{text}</span>"
|
||||
"<span class='badge-category' style='background-color: ##{templateData.color}'>#{text}</span>"
|
||||
|
|
|
@ -54,7 +54,7 @@ window.Discourse.ComposerView = window.Discourse.View.extend
|
|||
|
||||
willDestroyElement: ->
|
||||
$('body').off 'keydown.composer'
|
||||
|
||||
|
||||
resize: (->
|
||||
# this still needs to wait on animations, need a clean way to do that
|
||||
Em.run.next null, =>
|
||||
|
@ -91,13 +91,13 @@ window.Discourse.ComposerView = window.Discourse.View.extend
|
|||
|
||||
initEditor: ->
|
||||
|
||||
# not quite right, need a callback to pass in, meaning this gets called once,
|
||||
# not quite right, need a callback to pass in, meaning this gets called once,
|
||||
# but if you start replying to another topic it will get the avatars wrong
|
||||
@wmdInput = $wmdInput = $('#wmd-input')
|
||||
return if $wmdInput.length == 0 || $wmdInput.data('init') == true
|
||||
|
||||
|
||||
Discourse.ComposerView.trigger("initWmdEditor")
|
||||
|
||||
|
||||
template = Handlebars.compile("<div class='autocomplete'>
|
||||
<ul>
|
||||
{{#each options}}
|
||||
|
@ -152,7 +152,7 @@ window.Discourse.ComposerView = window.Discourse.View.extend
|
|||
@editor.hooks.onPreviewRefresh = => @afterRender()
|
||||
@editor.run()
|
||||
@set('editor', @editor)
|
||||
|
||||
|
||||
@loadingChanged()
|
||||
|
||||
saveDraft = Discourse.debounce((=> @get('controller').saveDraft()),2000)
|
||||
|
@ -165,7 +165,7 @@ window.Discourse.ComposerView = window.Discourse.View.extend
|
|||
saveDraft()
|
||||
return true
|
||||
|
||||
# In case it's still bound somehow
|
||||
# In case it's still bound somehow
|
||||
$uploadTarget.fileupload('destroy')
|
||||
|
||||
# Add the upload action
|
||||
|
@ -200,13 +200,13 @@ window.Discourse.ComposerView = window.Discourse.View.extend
|
|||
@set('loadingImage', false)
|
||||
|
||||
|
||||
# I hate to use Em.run.later, but I don't think there's a way of waiting for a CSS transition
|
||||
# I hate to use Em.run.later, but I don't think there's a way of waiting for a CSS transition
|
||||
# to finish.
|
||||
Em.run.later($, (=>
|
||||
replyTitle = $('#reply-title')
|
||||
|
||||
@resize()
|
||||
|
||||
|
||||
if replyTitle.length
|
||||
replyTitle.putCursorAtEnd()
|
||||
else
|
||||
|
@ -242,7 +242,7 @@ Discourse.NotifyingTextArea = Ember.TextArea.extend
|
|||
placeholder: (->
|
||||
Em.String.i18n(@get('placeholderKey'))
|
||||
).property('placeholderKey')
|
||||
|
||||
|
||||
didInsertElement: ->
|
||||
@get('parent').childDidInsertElement(@)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ window.Discourse.ExcerptCategoryView = Ember.View.extend
|
|||
cat = @get('category')
|
||||
|
||||
cat.set('id', cat.get('slug'))
|
||||
@get('controller.controllers.modal')?.showView(Discourse.EditCategoryView.create(category: cat))
|
||||
@get('controller.controllers.modal')?.showView(Discourse.EditCategoryView.create(category: cat))
|
||||
false
|
||||
|
||||
deleteCategory: ->
|
||||
|
@ -16,8 +16,8 @@ window.Discourse.ExcerptCategoryView = Ember.View.extend
|
|||
bootbox.confirm Em.String.i18n("category.delete_confirm"), (result) =>
|
||||
if result
|
||||
@get('category').delete ->
|
||||
Discourse.get('appController').reloadSession -> Discourse.get('router').route("/categories")
|
||||
|
||||
Discourse.get('appController').reloadSession -> Discourse.get('router').route("/categories")
|
||||
|
||||
false
|
||||
|
||||
didInsertElement: ->
|
||||
|
|
|
@ -6,7 +6,7 @@ window.Discourse.ExcerptUserView = Ember.View.extend
|
|||
url = post.get("url")
|
||||
username = post.get("username")
|
||||
Discourse.router.route('/users/' + Discourse.currentUser.username.toLowerCase() + "/private-messages")
|
||||
|
||||
|
||||
# TODO figure out a way for it to open the composer cleanly AFTER the navigation happens.
|
||||
composerController = Discourse.get('router.composerController')
|
||||
composerController.open
|
||||
|
|
|
@ -91,7 +91,7 @@ window.Discourse.ExcerptView = Ember.ContainerView.extend
|
|||
|
||||
didInsertElement: ->
|
||||
|
||||
# lets disable this puppy for now, it looks unprofessional
|
||||
# lets disable this puppy for now, it looks unprofessional
|
||||
return
|
||||
|
||||
# We don't do hovering on touch devices
|
||||
|
@ -120,7 +120,7 @@ window.Discourse.ExcerptView = Ember.ContainerView.extend
|
|||
topPosY = (pos.top - height) - margin
|
||||
bottomPosY = (pos.top + margin)
|
||||
|
||||
|
||||
|
||||
# Switch to right if there's no room on top
|
||||
if positionText == 'top'
|
||||
positionText = 'bottom' if topPosY < 10
|
||||
|
@ -140,7 +140,7 @@ window.Discourse.ExcerptView = Ember.ContainerView.extend
|
|||
if (pos.left || 0) <= 0 && (pos.top || 0) <= 0
|
||||
# somehow, sometimes, we are trying to position stuff in weird spots, just skip it
|
||||
return
|
||||
|
||||
|
||||
@set('position', positionText)
|
||||
@set('desiredLocation', pos)
|
||||
@set('size', $target.data('excerpt-size'))
|
||||
|
@ -150,5 +150,5 @@ window.Discourse.ExcerptView = Ember.ContainerView.extend
|
|||
$('#main').on 'mouseleave', '.excerptable', (e) =>
|
||||
Em.run.cancel(@openTimer)
|
||||
@closeSoon()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
window.Discourse.FeaturedTopicsView = Ember.View.extend
|
||||
templateName: 'featured_topics'
|
||||
classNames: ['category-list-item']
|
||||
classNames: ['category-list-item']
|
||||
|
||||
init: ->
|
||||
@._super()
|
||||
@set('context', @get('content'))
|
||||
@set('context', @get('content'))
|
||||
|
|
|
@ -9,13 +9,13 @@ window.Discourse.FlagView = Ember.View.extend
|
|||
@set('isCustomFlag', action.is_custom_flag)
|
||||
Em.run.next -> $("#radio_#{action.name_key}").prop('checked', 'true')
|
||||
false
|
||||
|
||||
|
||||
createFlag: ->
|
||||
actionType = Discourse.get("site").postActionTypeById(@get('postActionTypeId'))
|
||||
@get("post.actionByName.#{actionType.get('name_key')}")?.act(message: @get('customFlagMessage'))
|
||||
$('#discourse-modal').modal('hide')
|
||||
false
|
||||
|
||||
|
||||
customPlaceholder: (->
|
||||
Em.String.i18n("flagging.custom_placeholder")
|
||||
).property()
|
||||
|
|
|
@ -7,7 +7,7 @@ window.Discourse.HeaderView = Ember.View.extend
|
|||
currentUserBinding: 'Discourse.currentUser'
|
||||
categoriesBinding: 'site.categories'
|
||||
topicBinding: 'Discourse.router.topicController.content'
|
||||
|
||||
|
||||
showDropdown: ($target) ->
|
||||
elementId = $target.data('dropdown') || $target.data('notifications')
|
||||
$dropdown = $("##{elementId}")
|
||||
|
@ -31,7 +31,7 @@ window.Discourse.HeaderView = Ember.View.extend
|
|||
$html.on 'click.d-dropdown touchstart.d-dropdown', (e) =>
|
||||
return true if $(e.target).closest('.d-dropdown').length > 0
|
||||
hideDropdown()
|
||||
|
||||
|
||||
$html.data('hide-dropdown', hideDropdown)
|
||||
|
||||
false
|
||||
|
@ -65,7 +65,7 @@ window.Discourse.HeaderView = Ember.View.extend
|
|||
if @dockedHeader
|
||||
$('body').removeClass('docked')
|
||||
@dockedHeader = false
|
||||
|
||||
|
||||
|
||||
willDestroyElement: ->
|
||||
$(window).unbind 'scroll.discourse-dock'
|
||||
|
@ -75,7 +75,7 @@ window.Discourse.HeaderView = Ember.View.extend
|
|||
didInsertElement: ->
|
||||
@.$('a[data-dropdown]').on 'click touchstart', (e) => @showDropdown($(e.currentTarget))
|
||||
@.$('a.unread-private-messages, a.unread-notifications, a[data-notifications]').on 'click touchstart', (e) => @showNotifications(e)
|
||||
|
||||
|
||||
$(window).bind 'scroll.discourse-dock', => @examineDockHeader()
|
||||
$(document).bind 'touchmove.discourse-dock', => @examineDockHeader()
|
||||
@examineDockHeader()
|
||||
|
@ -86,7 +86,7 @@ window.Discourse.HeaderView = Ember.View.extend
|
|||
# Hide dropdowns
|
||||
if e.which == 27
|
||||
@.$('li').removeClass('active')
|
||||
@.$('.d-dropdown').fadeOut('fast')
|
||||
@.$('.d-dropdown').fadeOut('fast')
|
||||
|
||||
if @get('editingTopic')
|
||||
@finishedEdit() if e.which == 13
|
||||
|
|
|
@ -25,9 +25,9 @@ window.Discourse.HistoryView = Ember.View.extend
|
|||
|
||||
@get('originalPost').loadVersions (result) =>
|
||||
@set('loading', false)
|
||||
|
||||
|
||||
@set('versionLeft', result.first())
|
||||
@set('versionRight', result.last())
|
||||
@set('versions', result)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@ window.Discourse.ImageSelectorView = Ember.View.extend
|
|||
templateName: 'image_selector'
|
||||
classNames: ['image-selector']
|
||||
title: 'Insert Image'
|
||||
|
||||
|
||||
init: ->
|
||||
@._super()
|
||||
@set('localSelected', true)
|
||||
|
||||
selectLocal: ->
|
||||
@set('localSelected', true)
|
||||
|
||||
|
||||
selectRemote: ->
|
||||
@set('localSelected', false)
|
||||
|
||||
|
@ -26,6 +26,6 @@ window.Discourse.ImageSelectorView = Ember.View.extend
|
|||
add: ->
|
||||
@get('composer').addMarkdown("![image](#{$('#fileurl-input').val()})")
|
||||
$('#discourse-modal').modal('hide')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -17,4 +17,4 @@ Discourse.InputTipView = Ember.View.extend Discourse.Presence,
|
|||
render: (buffer) ->
|
||||
if reason = @get('validation.reason')
|
||||
icon = if @get('good') then 'icon-ok' else 'icon-remove'
|
||||
buffer.push "<i class=\"icon #{icon}\"></i> #{reason}"
|
||||
buffer.push "<i class=\"icon #{icon}\"></i> #{reason}"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue