diff --git a/.travis.yml b/.travis.yml index ad89a9befe..dc5a82fc36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ rvm: - 2.0.0 - 2.1 - 2.2 - - 2.3.0 + - 2.3.1 services: - redis-server diff --git a/Gemfile.lock b/Gemfile.lock index be5294173a..2c5e54606d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -65,7 +65,7 @@ GEM byebug (8.2.1) certified (1.0.0) coderay (1.1.0) - concurrent-ruby (1.0.1) + concurrent-ruby (1.0.2) connection_pool (2.2.0) crass (1.0.2) daemons (1.2.3) @@ -92,7 +92,7 @@ GEM railties (>= 3.1) ember-source (1.12.2) erubis (2.7.0) - eventmachine (1.0.8) + eventmachine (1.2.0.1) excon (0.45.4) execjs (2.6.0) exifr (1.2.4) @@ -149,7 +149,7 @@ GEM thor (~> 0.15) libv8 (3.16.14.13) listen (0.7.3) - logster (1.2.2) + logster (1.2.3) loofah (2.0.3) nokogiri (>= 1.5.9) lru_redux (1.1.0) @@ -282,7 +282,7 @@ GEM ffi (>= 1.0.6) msgpack (>= 0.4.3) trollop (>= 1.16.2) - redis (3.2.2) + redis (3.3.0) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) ref (2.0.0) @@ -344,7 +344,7 @@ GEM shoulda-context (1.2.1) shoulda-matchers (2.8.0) activesupport (>= 3.0.0) - sidekiq (4.0.2) + sidekiq (4.1.2) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) redis (~> 3.2, >= 3.2.1) @@ -501,4 +501,4 @@ DEPENDENCIES unicorn BUNDLED WITH - 1.11.2 + 1.12.3 diff --git a/README.md b/README.md index 9b1ae9bf6b..f74dcb0be4 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Discourse is built for the *next* 10 years of the Internet, so our requirements | -------- | ------- | ----------- | | Safari 6.1+| iPad 2+ | iOS 7+ | | Google Chrome 23+ | Android 4.3+ | Android 4.3+ | -| Internet Explorer 10+ | Windows 8 | Windows Phone 8 | +| Internet Explorer 11+ | Windows 8 | Windows Phone 8 | | Firefox 16+ | | ## Built With diff --git a/app/assets/javascripts/admin/controllers/admin-reports.js.es6 b/app/assets/javascripts/admin/controllers/admin-reports.js.es6 index 61b46740ac..1d4dac7e64 100644 --- a/app/assets/javascripts/admin/controllers/admin-reports.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-reports.js.es6 @@ -28,7 +28,7 @@ export default Ember.Controller.extend({ @computed('model.type') showCategoryOptions(modelType) { - return !modelType.match(/_private_messages$/); + return !modelType.match(/_private_messages$/) && !modelType.match(/^page_view_/); }, @computed('model.type') diff --git a/app/assets/javascripts/admin/models/admin-user.js.es6 b/app/assets/javascripts/admin/models/admin-user.js.es6 index 5c0660fedd..b5767f781a 100644 --- a/app/assets/javascripts/admin/models/admin-user.js.es6 +++ b/app/assets/javascripts/admin/models/admin-user.js.es6 @@ -1,3 +1,4 @@ +import computed from 'ember-addons/ember-computed-decorators'; import { propertyNotEqual } from 'discourse/lib/computed'; import { popupAjaxError } from 'discourse/lib/ajax-error'; import ApiKey from 'admin/models/api-key'; @@ -6,11 +7,42 @@ import TL3Requirements from 'admin/models/tl3-requirements'; const AdminUser = Discourse.User.extend({ - customGroups: Em.computed.filter("groups", (g) => !g.automatic && Group.create(g)), - automaticGroups: Em.computed.filter("groups", (g) => g.automatic && Group.create(g)), + customGroups: Ember.computed.filter("groups", g => !g.automatic && Group.create(g)), + automaticGroups: Ember.computed.filter("groups", g => g.automatic && Group.create(g)), canViewProfile: Ember.computed.or("active", "staged"), + @computed("bounce_score", "reset_bounce_score_after") + bounceScore(bounce_score, reset_bounce_score_after) { + if (bounce_score > 0) { + return `${bounce_score} - ${moment(reset_bounce_score_after).format('LL')}`; + } else { + return bounce_score; + } + }, + + @computed("bounce_score") + bounceScoreExplanation(bounce_score) { + if (bounce_score === 0) { + return I18n.t("admin.user.bounce_score_explanation.none"); + } else if (bounce_score < Discourse.SiteSettings.bounce_score_threshold) { + return I18n.t("admin.user.bounce_score_explanation.some"); + } else { + return I18n.t("admin.user.bounce_score_explanation.threshold_reached"); + } + }, + + canResetBounceScore: Ember.computed.gt("bounce_score", 0), + + resetBounceScore() { + return Discourse.ajax(`/admin/users/${this.get("id")}/reset_bounce_score`, { + type: 'POST' + }).then(() => this.setProperties({ + "bounce_score": 0, + "reset_bounce_score_after": null + })); + }, + generateApiKey() { const self = this; return Discourse.ajax("/admin/users/" + this.get('id') + "/generate_api_key", { diff --git a/app/assets/javascripts/admin/templates/api.hbs b/app/assets/javascripts/admin/templates/api.hbs index c37c468db3..0f2e65b89c 100644 --- a/app/assets/javascripts/admin/templates/api.hbs +++ b/app/assets/javascripts/admin/templates/api.hbs @@ -5,7 +5,7 @@ {{i18n 'admin.api.user'}}   - {{#each k in model}} + {{#each model as |k|}} {{k.key}} diff --git a/app/assets/javascripts/admin/templates/backups_index.hbs b/app/assets/javascripts/admin/templates/backups_index.hbs index 09bf83bc63..d326aede6a 100644 --- a/app/assets/javascripts/admin/templates/backups_index.hbs +++ b/app/assets/javascripts/admin/templates/backups_index.hbs @@ -13,7 +13,7 @@ - {{#each backup in model}} + {{#each model as |backup|}} {{backup.filename}} {{human-size backup.size}} diff --git a/app/assets/javascripts/admin/templates/badges.hbs b/app/assets/javascripts/admin/templates/badges.hbs index c128c6fb93..3ca7f91294 100644 --- a/app/assets/javascripts/admin/templates/badges.hbs +++ b/app/assets/javascripts/admin/templates/badges.hbs @@ -3,7 +3,7 @@

{{i18n 'admin.badges.title'}}

- {{#each to in email.to_addresses}} + {{#each email.to_addresses as |to|}}

{{unbound to}}

{{/each}} - {{#each cc in email.cc_addresses}} + {{#each email.cc_addresses as |cc|}}

{{unbound cc}}

{{/each}} diff --git a/app/assets/javascripts/admin/templates/email-sent.hbs b/app/assets/javascripts/admin/templates/email-sent.hbs index 56765cfadf..4854a4e94f 100644 --- a/app/assets/javascripts/admin/templates/email-sent.hbs +++ b/app/assets/javascripts/admin/templates/email-sent.hbs @@ -18,7 +18,7 @@ {{text-field value=filter.reply_key placeholderKey="admin.email.logs.filters.reply_key_placeholder"}} - {{#each l in model}} + {{#each model as |l|}} {{format-date l.created_at}} diff --git a/app/assets/javascripts/admin/templates/email-skipped.hbs b/app/assets/javascripts/admin/templates/email-skipped.hbs index 9c21c428cd..b03e6179be 100644 --- a/app/assets/javascripts/admin/templates/email-skipped.hbs +++ b/app/assets/javascripts/admin/templates/email-skipped.hbs @@ -18,7 +18,7 @@ {{text-field value=filter.skipped_reason placeholderKey="admin.email.logs.filters.skipped_reason_placeholder"}} - {{#each l in model}} + {{#each model as |l|}} {{format-date l.created_at}} diff --git a/app/assets/javascripts/admin/templates/email_index.hbs b/app/assets/javascripts/admin/templates/email_index.hbs index 8837ac619e..cd3696739d 100644 --- a/app/assets/javascripts/admin/templates/email_index.hbs +++ b/app/assets/javascripts/admin/templates/email_index.hbs @@ -4,7 +4,7 @@ {{delivery_method}} - {{#each s in model.settings}} + {{#each model.settings as |s|}} {{s.name}} {{s.value}} diff --git a/app/assets/javascripts/admin/templates/emojis.hbs b/app/assets/javascripts/admin/templates/emojis.hbs index e89ec2af1e..146baba74b 100644 --- a/app/assets/javascripts/admin/templates/emojis.hbs +++ b/app/assets/javascripts/admin/templates/emojis.hbs @@ -16,7 +16,7 @@ - {{#each e in controller}} + {{#each controller as |e|}} :{{e.name}}: diff --git a/app/assets/javascripts/admin/templates/flags-list.hbs b/app/assets/javascripts/admin/templates/flags-list.hbs index 9b404b9929..dbbec2a233 100644 --- a/app/assets/javascripts/admin/templates/flags-list.hbs +++ b/app/assets/javascripts/admin/templates/flags-list.hbs @@ -42,7 +42,7 @@ - {{#each flagger in flaggedPost.flaggers}} + {{#each flaggedPost.flaggers as |flagger|}}
{{#link-to 'adminUser' flagger.user}} @@ -67,7 +67,7 @@ {{#if adminOldFlagsView}} - {{#each flagger in flaggedPost.flaggers}} + {{#each flaggedPost.flaggers as |flagger|}} {{/if}} - {{#each c in flaggedPost.conversations}} + {{#each flaggedPost.conversations as |c|}} - {{#each plugin in controller}} + {{#each controller as |plugin|}} - {{#each row in model.dataReversed}} + {{#each model.dataReversed as |row|}} - {{#each user in model}} + {{#each model as |user|}} {{#if controller.showApproval}} + + + + + + + +{{#if showTimeRead}} + +{{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/flag-action-type.hbs b/app/assets/javascripts/discourse/templates/components/flag-action-type.hbs new file mode 100644 index 0000000000..f33def0818 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/flag-action-type.hbs @@ -0,0 +1,27 @@ +{{#if isNotifyUser}} +

{{formattedName}}

+
+ + {{#if showMessageInput}} + {{textarea name="message" class="flag-message" placeholder=customPlaceholder value=message}} +
{{customMessageLength}}
+ {{/if}} +
+ {{#if staffFlagsAvailable}} +
+

{{i18n 'flagging.notify_staff'}}

+ {{/if}} +{{else}} +
+ + {{#if showMessageInput}} + {{textarea name="message" class="flag-message" placeholder=customPlaceholder value=message}} +
{{customMessageLength}}
+ {{/if}} +
+{{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs b/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs index f58685e5c1..35d5afd0bb 100644 --- a/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs +++ b/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs @@ -60,7 +60,7 @@ - {{#each a in other_accounts}} + {{#each other_accounts as |a|}} diff --git a/app/assets/javascripts/discourse/templates/components/login-buttons.hbs b/app/assets/javascripts/discourse/templates/components/login-buttons.hbs index d6efea1866..baf18eec36 100644 --- a/app/assets/javascripts/discourse/templates/components/login-buttons.hbs +++ b/app/assets/javascripts/discourse/templates/components/login-buttons.hbs @@ -1,3 +1,3 @@ -{{#each b in buttons}} +{{#each buttons as |b|}} {{/each}} diff --git a/app/assets/javascripts/discourse/templates/components/period-chooser.hbs b/app/assets/javascripts/discourse/templates/components/period-chooser.hbs index 75e9dd6487..6559d03d52 100644 --- a/app/assets/javascripts/discourse/templates/components/period-chooser.hbs +++ b/app/assets/javascripts/discourse/templates/components/period-chooser.hbs @@ -3,7 +3,7 @@
diff --git a/app/assets/javascripts/discourse/templates/components/queued-post.hbs b/app/assets/javascripts/discourse/templates/components/queued-post.hbs new file mode 100644 index 0000000000..6ddd37b864 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/queued-post.hbs @@ -0,0 +1,79 @@ +
+
+ {{#user-link user=post.user}} + {{avatar post.user imageSize="large"}} + {{/user-link}} +
+
+
+ + {{#user-link user=post.user}} + {{post.user.username}} + {{/user-link}} + {{#if post.user.blocked}} + + {{/if}} + +
+ +
+ + + {{i18n "queue.topic"}} + {{#if post.topic}} + {{topic-link post.topic}} + {{else}} + {{post.post_options.title}} + {{/if}} + {{category-badge post.category}} + + +
+ {{#if editing}} + {{d-editor value=buffered.raw}} + {{else}} + {{{cook-text post.raw}}} + {{/if}} +
+ +
+ {{#if editing}} + {{d-button action="confirmEdit" + label="queue.confirm" + disabled=post.isSaving + class="btn-primary confirm"}} + {{d-button action="cancelEdit" + label="queue.cancel" + icon="times" + disabled=post.isSaving + class="btn-danger cancel"}} + {{else}} + {{d-button action="approve" + disabled=post.isSaving + label="queue.approve" + icon="check" + class="btn-primary approve"}} + {{d-button action="reject" + disabled=post.isSaving + label="queue.reject" + icon="times" + class="btn-danger reject"}} + {{#if post.can_delete_user}} + {{d-button action="deleteUser" + disabled=post.isSaving + label="queue.delete_user" + icon="trash" + class="btn-danger delete-user"}} + {{/if}} + {{d-button action="edit" + disabled=post.isSaving + label="queue.edit" + icon="pencil" + class="edit"}} + {{/if}} +
+
+
+
diff --git a/app/assets/javascripts/discourse/templates/components/tag-drop.hbs b/app/assets/javascripts/discourse/templates/components/tag-drop.hbs index 46e4f66046..f1ca7f3e6f 100644 --- a/app/assets/javascripts/discourse/templates/components/tag-drop.hbs +++ b/app/assets/javascripts/discourse/templates/components/tag-drop.hbs @@ -10,7 +10,7 @@
{{#if renderTags}} - {{#each t in tags}} + {{#each tags as |t|}}
{{tag-drop-link tagId=t category=currentCategory}}
@@ -18,4 +18,4 @@ {{/if}}
{{/if}} -{{/if}} \ No newline at end of file +{{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/top-period-buttons.hbs b/app/assets/javascripts/discourse/templates/components/top-period-buttons.hbs index 169d69432e..92c73d3884 100644 --- a/app/assets/javascripts/discourse/templates/components/top-period-buttons.hbs +++ b/app/assets/javascripts/discourse/templates/components/top-period-buttons.hbs @@ -1,4 +1,4 @@ -{{#each p in periods}} +{{#each periods as |p|}} {{#d-button action="changePeriod" actionParam=p}} {{period-title p}} {{/d-button}} diff --git a/app/assets/javascripts/discourse/templates/components/topic-category.hbs b/app/assets/javascripts/discourse/templates/components/topic-category.hbs index cf70e3e8a8..c311422560 100644 --- a/app/assets/javascripts/discourse/templates/components/topic-category.hbs +++ b/app/assets/javascripts/discourse/templates/components/topic-category.hbs @@ -4,7 +4,7 @@ {{bound-category-link topic.category hideParent=true}} {{#if siteSettings.tagging_enabled}}
- {{#each t in topic.tags}} + {{#each topic.tags as |t|}} {{discourse-tag t}} {{/each}}
diff --git a/app/assets/javascripts/discourse/templates/components/topic-list.hbs b/app/assets/javascripts/discourse/templates/components/topic-list.hbs index 6f9aa64370..ebc2e1bf5a 100644 --- a/app/assets/javascripts/discourse/templates/components/topic-list.hbs +++ b/app/assets/javascripts/discourse/templates/components/topic-list.hbs @@ -15,5 +15,17 @@ {{/unless}}
- {{each topic in topics itemView="topic-list-item"}} + {{#each topics as |topic|}} + {{topic-list-item topic=topic + bulkSelectEnabled=bulkSelectEnabled + showTopicPostBadges=showTopicPostBadges + hideCategory=hideCategory + showPosters=showPosters + showParticipants=showParticipants + showLikes=showLikes + showOpLikes=showOpLikes + expandGloballyPinned=expandGloballyPinned + expandAllPinned=expandAllPinned + selected=selected}} + {{/each}} diff --git a/app/assets/javascripts/discourse/templates/discovery/categories.hbs b/app/assets/javascripts/discourse/templates/discovery/categories.hbs index 7d26d35ba2..bbb75015dc 100644 --- a/app/assets/javascripts/discourse/templates/discovery/categories.hbs +++ b/app/assets/javascripts/discourse/templates/discovery/categories.hbs @@ -9,7 +9,7 @@ - {{#each c in model.categories}} + {{#each model.categories as |c|}}
{{#link-to 'adminUser' flagger.disposedBy}} @@ -101,7 +101,7 @@
diff --git a/app/assets/javascripts/admin/templates/groups_type.hbs b/app/assets/javascripts/admin/templates/groups_type.hbs index 780814b82c..4486b87805 100644 --- a/app/assets/javascripts/admin/templates/groups_type.hbs +++ b/app/assets/javascripts/admin/templates/groups_type.hbs @@ -2,7 +2,7 @@

{{i18n 'admin.groups.edit'}}

    - {{#each group in controller}} + {{#each controller as |group|}}
  • {{#link-to "adminGroup" group.type group.name}}{{group.name}} {{#if group.userCountDisplay}} diff --git a/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs b/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs index e244d5b0ef..14a475f5c5 100644 --- a/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs +++ b/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs @@ -34,7 +34,7 @@ {{i18n 'admin.badges.preview.sample'}}

      - {{#each html in processed_sample}} + {{#each processed_sample as |html|}}
    • {{{html}}}
    • {{/each}}
    diff --git a/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.hbs b/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.hbs index f2a6581bbe..5ca9f9cc39 100644 --- a/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.hbs +++ b/app/assets/javascripts/admin/templates/modal/admin_edit_badge_groupings.hbs @@ -1,7 +1,7 @@
{{#if plugin.url}} diff --git a/app/assets/javascripts/admin/templates/plugins.hbs b/app/assets/javascripts/admin/templates/plugins.hbs index 96ed1fc7d0..ac1ca1a83c 100644 --- a/app/assets/javascripts/admin/templates/plugins.hbs +++ b/app/assets/javascripts/admin/templates/plugins.hbs @@ -2,7 +2,7 @@ diff --git a/app/assets/javascripts/admin/templates/reports.hbs b/app/assets/javascripts/admin/templates/reports.hbs index 12303f27ef..048ff284bd 100644 --- a/app/assets/javascripts/admin/templates/reports.hbs +++ b/app/assets/javascripts/admin/templates/reports.hbs @@ -37,7 +37,7 @@ {{model.yaxis}}
{{row.x}} diff --git a/app/assets/javascripts/admin/templates/site-settings.hbs b/app/assets/javascripts/admin/templates/site-settings.hbs index d7e157a929..b9a96c90cb 100644 --- a/app/assets/javascripts/admin/templates/site-settings.hbs +++ b/app/assets/javascripts/admin/templates/site-settings.hbs @@ -14,7 +14,7 @@
 
diff --git a/app/assets/javascripts/discourse/components/directory-item.js.es6 b/app/assets/javascripts/discourse/components/directory-item.js.es6 new file mode 100644 index 0000000000..df32734571 --- /dev/null +++ b/app/assets/javascripts/discourse/components/directory-item.js.es6 @@ -0,0 +1,7 @@ +import { propertyEqual } from 'discourse/lib/computed'; + +export default Ember.Component.extend({ + tagName: 'tr', + classNameBindings: ['me'], + me: propertyEqual('item.user.id', 'currentUser.id') +}); diff --git a/app/assets/javascripts/discourse/components/flag-action-type.js.es6 b/app/assets/javascripts/discourse/components/flag-action-type.js.es6 new file mode 100644 index 0000000000..031831219c --- /dev/null +++ b/app/assets/javascripts/discourse/components/flag-action-type.js.es6 @@ -0,0 +1,54 @@ +import { MAX_MESSAGE_LENGTH } from 'discourse/models/post-action-type'; +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + + @computed('flag.name_key') + customPlaceholder(nameKey) { + return I18n.t("flagging.custom_placeholder_" + nameKey); + }, + + @computed('flag.name', 'flag.name_key', 'flag.is_custom_flag', 'username') + formattedName(name, nameKey, isCustomFlag, username) { + if (isCustomFlag) { + return name.replace("{{username}}", username); + } else { + return I18n.t("flagging.formatted_name." + nameKey); + } + }, + + @computed('flag', 'selectedFlag') + selected(flag, selectedFlag) { + return flag === selectedFlag; + }, + + showMessageInput: Em.computed.and('flag.is_custom_flag', 'selected'), + showDescription: Em.computed.not('showMessageInput'), + isNotifyUser: Em.computed.equal('flag.name_key', 'notify_user'), + + @computed('message.length') + customMessageLengthClasses(messageLength) { + return (messageLength < Discourse.SiteSettings.min_private_message_post_length) ? "too-short" : "ok"; + }, + + @computed('message.length') + customMessageLength(messageLength) { + const len = messageLength || 0; + const minLen = Discourse.SiteSettings.min_private_message_post_length; + if (len === 0) { + return I18n.t("flagging.custom_message.at_least", { n: minLen }); + } else if (len < minLen) { + return I18n.t("flagging.custom_message.more", { n: minLen - len }); + } else { + return I18n.t("flagging.custom_message.left", { + n: MAX_MESSAGE_LENGTH - len + }); + } + }, + + actions: { + changePostActionType(at) { + this.sendAction('changePostActionType', at); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/queued-post.js.es6 b/app/assets/javascripts/discourse/components/queued-post.js.es6 similarity index 71% rename from app/assets/javascripts/discourse/controllers/queued-post.js.es6 rename to app/assets/javascripts/discourse/components/queued-post.js.es6 index a285537491..28f5a90fdd 100644 --- a/app/assets/javascripts/discourse/controllers/queued-post.js.es6 +++ b/app/assets/javascripts/discourse/components/queued-post.js.es6 @@ -1,5 +1,5 @@ import { propertyEqual } from 'discourse/lib/computed'; -import BufferedContent from 'discourse/mixins/buffered-content'; +import { bufferedProperty } from 'discourse/mixins/buffered-content'; import { popupAjaxError } from 'discourse/lib/ajax-error'; function updateState(state, opts) { @@ -12,18 +12,14 @@ function updateState(state, opts) { if (opts.deleteUser) { args.delete_user = true; } post.update(args).then(() => { - this.get('controllers.queued-posts.model').removeObject(post); + this.sendAction('removePost', post); + // this.get('controllers.queued-posts.model').removeObject(post); }).catch(popupAjaxError); }; } -export default Ember.Controller.extend(BufferedContent, { - needs: ['queued-posts'], - post: Ember.computed.alias('model'), - currentlyEditing: Ember.computed.alias('controllers.queued-posts.editing'), - - editing: propertyEqual('model', 'currentlyEditing'), - +export default Ember.Component.extend(bufferedProperty('post'), { + editing: propertyEqual('post', 'currentlyEditing'), _confirmDelete: updateState('rejected', {deleteUser: true}), actions: { @@ -31,7 +27,7 @@ export default Ember.Controller.extend(BufferedContent, { reject: updateState('rejected'), deleteUser() { - bootbox.confirm(I18n.t('queue.delete_prompt', {username: this.get('model.user.username')}), (confirmed) => { + bootbox.confirm(I18n.t('queue.delete_prompt', {username: this.get('post.user.username')}), (confirmed) => { if (confirmed) { this._confirmDelete(); } }); }, @@ -39,7 +35,7 @@ export default Ember.Controller.extend(BufferedContent, { edit() { // This is stupid but pagedown cannot be on the screen twice or it will break this.set('currentlyEditing', null); - Ember.run.scheduleOnce('afterRender', () => this.set('currentlyEditing', this.get('model'))); + Ember.run.scheduleOnce('afterRender', () => this.set('currentlyEditing', this.get('post'))); }, confirmEdit() { diff --git a/app/assets/javascripts/discourse/views/topic-list-item.js.es6 b/app/assets/javascripts/discourse/components/topic-list-item.js.es6 similarity index 75% rename from app/assets/javascripts/discourse/views/topic-list-item.js.es6 rename to app/assets/javascripts/discourse/components/topic-list-item.js.es6 index a7a158bc3f..943a7b6622 100644 --- a/app/assets/javascripts/discourse/views/topic-list-item.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-list-item.js.es6 @@ -1,34 +1,19 @@ import StringBuffer from 'discourse/mixins/string-buffer'; -export default Ember.View.extend(StringBuffer, { - topic: Em.computed.alias("content"), - rerenderTriggers: ['controller.bulkSelectEnabled', 'topic.pinned'], +export default Ember.Component.extend(StringBuffer, { + rerenderTriggers: ['bulkSelectEnabled', 'topic.pinned'], tagName: 'tr', rawTemplate: 'list/topic-list-item.raw', - classNameBindings: ['controller.checked', - ':topic-list-item', - 'unboundClassNames', - 'selected'], + classNameBindings: [':topic-list-item', 'unboundClassNames'], attributeBindings: ['data-topic-id'], 'data-topic-id': Em.computed.alias('topic.id'), actions: { - select() { - this.set('controller.selectedRow', this); - }, - toggleBookmark() { - const self = this; - this.get('topic').toggleBookmark().finally(function() { - self.rerender(); - }); + this.get('topic').toggleBookmark().finally(() => this.rerender()); } }, - selected: function() { - return this.get('controller.selectedRow')===this; - }.property('controller.selectedRow'), - unboundClassNames: function() { let classes = []; const topic = this.get('topic'); @@ -51,7 +36,7 @@ export default Ember.View.extend(StringBuffer, { }.property(), titleColSpan: function() { - return (!this.get('controller.hideCategory') && + return (!this.get('hideCategory') && this.get('topic.isPinnedUncategorized') ? 2 : 1); }.property("topic.isPinnedUncategorized"), @@ -70,11 +55,11 @@ export default Ember.View.extend(StringBuffer, { return false; } - if (this.get('controller.expandGloballyPinned') && this.get('topic.pinned_globally')) { + if (this.get('expandGloballyPinned') && this.get('topic.pinned_globally')) { return true; } - if (this.get('controller.expandAllPinned')) { + if (this.get('expandAllPinned')) { return true; } @@ -96,7 +81,7 @@ export default Ember.View.extend(StringBuffer, { } if (target.hasClass('bulk-select')) { - const selected = this.get('controller.selected'); + const selected = this.get('selected'); const topic = this.get('topic'); if (target.is(':checked')) { diff --git a/app/assets/javascripts/discourse/components/user-notifications-large.js.es6 b/app/assets/javascripts/discourse/components/user-notifications-large.js.es6 index bfedea00f7..941c1aa322 100644 --- a/app/assets/javascripts/discourse/components/user-notifications-large.js.es6 +++ b/app/assets/javascripts/discourse/components/user-notifications-large.js.es6 @@ -9,7 +9,7 @@ export default MountWidget.extend({ this.args = { notifications: this.get('notifications') }; }, - @observes('notifications.length') + @observes('notifications.length', 'notifications.@each.read') _triggerRefresh() { this.queueRerender(); } diff --git a/app/assets/javascripts/discourse/controllers/directory-item.js.es6 b/app/assets/javascripts/discourse/controllers/directory-item.js.es6 deleted file mode 100644 index 2d09b3824f..0000000000 --- a/app/assets/javascripts/discourse/controllers/directory-item.js.es6 +++ /dev/null @@ -1,5 +0,0 @@ -import { propertyEqual } from 'discourse/lib/computed'; - -export default Ember.Controller.extend({ - me: propertyEqual('model.user.id', 'currentUser.id') -}); diff --git a/app/assets/javascripts/discourse/controllers/flag-action-type.js.es6 b/app/assets/javascripts/discourse/controllers/flag-action-type.js.es6 deleted file mode 100644 index d706a88e1c..0000000000 --- a/app/assets/javascripts/discourse/controllers/flag-action-type.js.es6 +++ /dev/null @@ -1,48 +0,0 @@ -import { MAX_MESSAGE_LENGTH } from 'discourse/models/post-action-type'; - -// Supports logic for flags in the modal -export default Ember.Controller.extend({ - needs: ['flag'], - - message: Em.computed.alias('controllers.flag.message'), - isWarning: Em.computed.alias('controllers.flag.isWarning'), - - customPlaceholder: function(){ - return I18n.t("flagging.custom_placeholder_" + this.get('model.name_key')); - }.property('model.name_key'), - - formattedName: function(){ - if (this.get("model.is_custom_flag")) { - return this.get('model.name').replace("{{username}}", this.get('controllers.flag.model.username')); - } else { - return I18n.t("flagging.formatted_name." + this.get('model.name_key')); - } - }.property('model.name', 'model.name_key', 'model.is_custom_flag'), - - selected: function() { - return this.get('model') === this.get('controllers.flag.selected'); - }.property('controllers.flag.selected'), - - showMessageInput: Em.computed.and('model.is_custom_flag', 'selected'), - showDescription: Em.computed.not('showMessageInput'), - isNotifyUser: Em.computed.equal('model.name_key', 'notify_user'), - - customMessageLengthClasses: function() { - return (this.get('message.length') < Discourse.SiteSettings.min_private_message_post_length) ? "too-short" : "ok"; - }.property('message.length'), - - customMessageLength: function() { - var len = this.get('message.length') || 0; - var minLen = Discourse.SiteSettings.min_private_message_post_length; - if (len === 0) { - return I18n.t("flagging.custom_message.at_least", { n: minLen }); - } else if (len < minLen) { - return I18n.t("flagging.custom_message.more", { n: minLen - len }); - } else { - return I18n.t("flagging.custom_message.left", { - n: MAX_MESSAGE_LENGTH - len - }); - } - }.property('message.length') - -}); diff --git a/app/assets/javascripts/discourse/ember/resolver.js.es6 b/app/assets/javascripts/discourse/ember/resolver.js.es6 index 8f41a2c507..99ecb42d2a 100644 --- a/app/assets/javascripts/discourse/ember/resolver.js.es6 +++ b/app/assets/javascripts/discourse/ember/resolver.js.es6 @@ -39,7 +39,6 @@ function parseName(fullName) { } export default Ember.DefaultResolver.extend({ - parseName: parseName, normalize(fullName) { diff --git a/app/assets/javascripts/discourse/initializers/mobile.js.es6 b/app/assets/javascripts/discourse/initializers/mobile.js.es6 index d4bffb3569..2ac54497b2 100644 --- a/app/assets/javascripts/discourse/initializers/mobile.js.es6 +++ b/app/assets/javascripts/discourse/initializers/mobile.js.es6 @@ -1,6 +1,6 @@ import Mobile from 'discourse/lib/mobile'; -// Initializes the `Mobile` helper object. +// Initializes the `Mobile` helper object. export default { name: 'mobile', after: 'inject-objects', @@ -16,4 +16,3 @@ export default { app.registry.resolver.__resolver__.mobileView = Mobile.mobileView; } }; - diff --git a/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js b/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js index e69c5421a3..23875153c8 100644 --- a/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js +++ b/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js @@ -40,7 +40,7 @@ }; }; - // #each .. in support + // #each .. in support (as format is transformed to this) RawHandlebars.registerHelper('each', function(localName,inKeyword,contextName,options){ var list = Em.get(this, contextName); var output = []; @@ -68,6 +68,21 @@ RawHandlebars.JavaScriptCompiler.prototype.compiler = RawHandlebars.JavaScriptCompiler; RawHandlebars.JavaScriptCompiler.prototype.namespace = "Discourse.EmberCompatHandlebars"; + function buildPath(blk, args) { + + var result = { type: "PathExpression", + data: false, + depth: blk.path.depth, + loc: blk.path.loc }; + + // Server side precompile doesn't have jquery.extend + Object.keys(args).forEach(function (a) { + result[a] = args[a]; + }); + + return result; + } + function replaceGet(ast) { var visitor = new Handlebars.Visitor(); visitor.mutating = true; @@ -75,19 +90,25 @@ visitor.MustacheStatement = function(mustache) { if (!(mustache.params.length || mustache.hash)) { mustache.params[0] = mustache.path; - mustache.path = { - type: "PathExpression", - data: false, - depth: mustache.path.depth, - parts: ["get"], - original: "get", - loc: mustache.path.loc, - strict: true, - falsy: true - }; + mustache.path = buildPath(mustache, { parts: ['get'], original: 'get', strict: true, falsy: true }); } return Handlebars.Visitor.prototype.MustacheStatement.call(this, mustache); }; + + // rewrite `each x as |y|` as each y in x` + // This allows us to use the same syntax in all templates + visitor.BlockStatement = function(block) { + if (block.path.original === 'each' && block.params.length === 1) { + var paramName = block.program.blockParams[0]; + block.params = [ buildPath(block, { original: paramName }), + { type: "CommentStatement", value: "in" }, + block.params[0] ]; + delete block.program.blockParams; + } + + return Handlebars.Visitor.prototype.BlockStatement.call(this, block); + }; + visitor.accept(ast); } diff --git a/app/assets/javascripts/discourse/lib/keyboard-shortcuts.js.es6 b/app/assets/javascripts/discourse/lib/keyboard-shortcuts.js.es6 index ef505ebe8e..f44bc3c40a 100644 --- a/app/assets/javascripts/discourse/lib/keyboard-shortcuts.js.es6 +++ b/app/assets/javascripts/discourse/lib/keyboard-shortcuts.js.es6 @@ -294,10 +294,6 @@ export default { $articles.removeClass('selected'); $article.addClass('selected'); - if ($article.is('.topic-list-item')) { - this.sendToTopicListItemView('select'); - } - if ($article.is('.topic-post')) { $('a.tabLoc', $article).focus(); } diff --git a/app/assets/javascripts/discourse/lib/mobile.js.es6 b/app/assets/javascripts/discourse/lib/mobile.js.es6 index 561a05458a..9fef722aa4 100644 --- a/app/assets/javascripts/discourse/lib/mobile.js.es6 +++ b/app/assets/javascripts/discourse/lib/mobile.js.es6 @@ -1,3 +1,5 @@ +let mobileForced = false; + // An object that is responsible for logic related to mobile devices. const Mobile = { isMobileDevice: false, @@ -5,8 +7,10 @@ const Mobile = { init() { const $html = $('html'); - this.isMobileDevice = $html.hasClass('mobile-device'); - this.mobileView = $html.hasClass('mobile-view'); + this.isMobileDevice = mobileForced || $html.hasClass('mobile-device'); + this.mobileView = mobileForced || $html.hasClass('mobile-view'); + + if (mobileForced) { return; } try{ if (window.location.search.match(/mobile_view=1/)){ @@ -27,8 +31,8 @@ const Mobile = { } }, - toggleMobileView: function() { - try{ + toggleMobileView() { + try { if (localStorage) { localStorage.mobileView = !this.mobileView; } @@ -38,11 +42,19 @@ const Mobile = { this.reloadPage(!this.mobileView); }, - reloadPage: function(mobile) { + reloadPage(mobile) { window.location.assign(window.location.pathname + '?mobile_view=' + (mobile ? '1' : '0')); } }; +export function forceMobile() { + mobileForced = true; +} + +export function resetMobile() { + mobileForced = false; +} + // Backwards compatibiltity, deprecated Object.defineProperty(Discourse, 'Mobile', { get: function() { diff --git a/app/assets/javascripts/discourse/lib/url.js.es6 b/app/assets/javascripts/discourse/lib/url.js.es6 index 50ef5e45f6..93e1ca7315 100644 --- a/app/assets/javascripts/discourse/lib/url.js.es6 +++ b/app/assets/javascripts/discourse/lib/url.js.es6 @@ -139,9 +139,7 @@ const DiscourseURL = Ember.Object.extend({ } } - rewrites.forEach(function(rw) { - path = path.replace(rw.regexp, rw.replacement); - }); + rewrites.forEach(rw => path = path.replace(rw.regexp, rw.replacement)); if (this.navigatedToPost(oldPath, path)) { return; } // Schedule a DOM cleanup event diff --git a/app/assets/javascripts/discourse/pre-initializers/dynamic-route-builders.js.es6 b/app/assets/javascripts/discourse/pre-initializers/dynamic-route-builders.js.es6 index 57da82cbc9..f627573e73 100644 --- a/app/assets/javascripts/discourse/pre-initializers/dynamic-route-builders.js.es6 +++ b/app/assets/javascripts/discourse/pre-initializers/dynamic-route-builders.js.es6 @@ -1,12 +1,13 @@ import buildCategoryRoute from 'discourse/routes/build-category-route'; import buildTopicRoute from 'discourse/routes/build-topic-route'; import DiscoverySortableController from 'discourse/controllers/discovery-sortable'; +import TagsShowRoute from 'discourse/routes/tags-show'; export default { after: 'inject-discourse-objects', name: 'dynamic-route-builders', - initialize(container, app) { + initialize(registry, app) { app.DiscoveryCategoryController = DiscoverySortableController.extend(); app.DiscoveryParentCategoryController = DiscoverySortableController.extend(); app.DiscoveryCategoryNoneController = DiscoverySortableController.extend(); @@ -58,5 +59,14 @@ export default { app[`DiscoveryTop${periodCapitalized}ParentCategoryRoute`] = buildCategoryRoute('top/' + period); app[`DiscoveryTop${periodCapitalized}CategoryNoneRoute`] = buildCategoryRoute('top/' + period, {no_subcategories: true}); }); + + app["TagsShowCategoryRoute"] = TagsShowRoute.extend(); + app["TagsShowParentCategoryRoute"] = TagsShowRoute.extend(); + + site.get('filters').forEach(function(filter) { + app["TagsShow" + filter.capitalize() + "Route"] = TagsShowRoute.extend({ filterMode: filter }); + app["TagsShowCategory" + filter.capitalize() + "Route"] = TagsShowRoute.extend({ filterMode: filter }); + app["TagsShowParentCategory" + filter.capitalize() + "Route"] = TagsShowRoute.extend({ filterMode: filter }); + }); } }; diff --git a/app/assets/javascripts/discourse/routes/queued-posts.js.es6 b/app/assets/javascripts/discourse/routes/queued-posts.js.es6 index 32706c9a6c..cf5c204d94 100644 --- a/app/assets/javascripts/discourse/routes/queued-posts.js.es6 +++ b/app/assets/javascripts/discourse/routes/queued-posts.js.es6 @@ -13,6 +13,10 @@ export default DiscourseRoute.extend({ }, actions: { + removePost(post) { + this.modelFor('queued-posts').removeObject(post); + }, + refresh() { this.modelFor('queued-posts').refresh(); } diff --git a/app/assets/javascripts/discourse/routes/tags-index.js.es6 b/app/assets/javascripts/discourse/routes/tags-index.js.es6 index 7fbd3d529e..b6514ef278 100644 --- a/app/assets/javascripts/discourse/routes/tags-index.js.es6 +++ b/app/assets/javascripts/discourse/routes/tags-index.js.es6 @@ -7,6 +7,13 @@ export default Discourse.Route.extend({ return I18n.t("tagging.tags"); }, + setupController(controller, model) { + this.controllerFor('tags.index').setProperties({ + model, + sortProperties: this.siteSettings.tags_sort_alphabetically ? ['id'] : ['count:desc', 'id'] + }); + }, + actions: { didTransition() { this.controllerFor("application").set("showFooter", true); diff --git a/app/assets/javascripts/discourse/templates/badges/index.hbs b/app/assets/javascripts/discourse/templates/badges/index.hbs index 71964b0e6d..a5aac17b23 100644 --- a/app/assets/javascripts/discourse/templates/badges/index.hbs +++ b/app/assets/javascripts/discourse/templates/badges/index.hbs @@ -2,7 +2,7 @@

{{i18n 'badges.title'}}

- {{#each bg in badgeGroups}} + {{#each badgeGroups as |bg|}}

{{bg.badgeGrouping.displayName}}

diff --git a/app/assets/javascripts/discourse/templates/category-group-autocomplete.raw.hbs b/app/assets/javascripts/discourse/templates/category-group-autocomplete.raw.hbs index 1164fa80c6..bc2181f534 100644 --- a/app/assets/javascripts/discourse/templates/category-group-autocomplete.raw.hbs +++ b/app/assets/javascripts/discourse/templates/category-group-autocomplete.raw.hbs @@ -1,6 +1,6 @@
diff --git a/app/assets/javascripts/discourse/templates/category-tag-autocomplete.raw.hbs b/app/assets/javascripts/discourse/templates/category-tag-autocomplete.raw.hbs index 886c7bba73..efbf18a33b 100644 --- a/app/assets/javascripts/discourse/templates/category-tag-autocomplete.raw.hbs +++ b/app/assets/javascripts/discourse/templates/category-tag-autocomplete.raw.hbs @@ -1,6 +1,6 @@
    - {{#each option in options}} + {{#each options as |option|}}
  • {{#if option.model}} {{category-link option.model allowUncategorized="true" link="false"}} diff --git a/app/assets/javascripts/discourse/templates/choose_topic.hbs b/app/assets/javascripts/discourse/templates/choose_topic.hbs index 3300b22b6e..03af7f616a 100644 --- a/app/assets/javascripts/discourse/templates/choose_topic.hbs +++ b/app/assets/javascripts/discourse/templates/choose_topic.hbs @@ -8,7 +8,7 @@ {{#if view.noResults}}

    {{i18n 'choose_topic.none_found'}}

    {{else}} - {{#each t in view.topics}} + {{#each view.topics as |t|}}
{{user-info user=item.user}}{{number item.likes_received}}{{number item.likes_given}}{{number item.topic_count}}{{number item.post_count}}{{number item.topics_entered}}{{number item.posts_read}}{{number item.days_visited}}{{unbound item.time_read}}
{{#link-to "adminUser" a}}{{avatar a usernamePath="user.username" imageSize="small"}} {{a.username}}{{/link-to}} {{a.trustLevel.id}}