Merge remote-tracking branch 'upstream/master' into update-locale-vietnamese

* upstream/master: (185 commits)
  SECURITY: Upgrade rails.
  FIX: new user summary page was broken
  Version bump to v1.5.0.beta9
  Remove addressable from Discourse.
  UX: change glyph when inviting existing user to a topic
  FIX: Allow for large free disk space
  Revert "FIX: disk_space should be a BigDecimal to handle large disk (closes #3923)"
  UX: improve styling of messages and mobile view of messages
  FIX: correct counts on user summary
  FIX: link to filtered down list of badges from summary FEATURE: pick featured badges in summary page
  FIX: do not allow new email to be duplicate FIX: return proper error message when email already exists
  retain unactivated accounts a bit longer default
  FEATURE: blocked users can send and reply to private messages from staff
  Remove Arel patch that has been merged upstream.
  correct path
  little typo
  FIX: Missing tag in CSS.
  PERF: remove 10-20ms of work from every page view
  FIX: remove green background for wiki (this can be re-added via a customization if needed)
  Hotfix for unsubscribe via email
  ...

# Conflicts:
#	.tx/config
This commit is contained in:
Khoa, Le Ngoc
2016-01-26 12:44:29 +07:00
438 changed files with 16120 additions and 10710 deletions

View File

@@ -15,7 +15,7 @@ export default Ember.Controller.extend({
showResultsDisabled: Em.computed.equal("poll.voters", 0),
hideResultsDisabled: Em.computed.or("isClosed", "post.topic.closed", "post.topic.archived"),
@computed("model", "vote")
@computed("model", "vote", "model.voters", "model.options", "model.status")
poll(poll, vote) {
if (poll) {
const options = _.map(poll.get("options"), o => Em.Object.create(o));

View File

@@ -1,4 +1,7 @@
import PostView from "discourse/views/post";
import TopicController from "discourse/controllers/topic";
import Post from "discourse/models/post";
import { on } from "ember-addons/ember-computed-decorators";
function createPollView(container, post, poll, vote) {
@@ -6,7 +9,7 @@ function createPollView(container, post, poll, vote) {
view = container.lookup("view:poll");
controller.set("vote", vote);
controller.setProperties({ model: Em.Object.create(poll), post });
controller.setProperties({ model: poll, post });
view.set("controller", controller);
return view;
@@ -17,13 +20,39 @@ export default {
initialize(container) {
const messageBus = container.lookup("message-bus:main");
Post.reopen({
// we need a proper ember object so it is bindable
pollsChanged: function(){
const polls = this.get("polls");
if (polls) {
this._polls = this._polls || {};
_.map(polls, (v,k) => {
const existing = this._polls[k];
if (existing) {
this._polls[k].setProperties(v);
} else {
this._polls[k] = Em.Object.create(v);
}
});
this.set("pollsObject", this._polls);
}
}.observes("polls")
});
// listen for back-end to tell us when a post has a poll
messageBus.subscribe("/polls", data => {
const post = container.lookup("controller:topic").get('model.postStream').findLoadedPost(data.post_id);
// HACK to trigger the "postViewUpdated" event
Em.run.next(() => post.set("cooked", post.get("cooked") + " "));
TopicController.reopen({
subscribe(){
this._super();
this.messageBus.subscribe("/polls/" + this.get("model.id"), msg => {
const post = this.get('model.postStream').findLoadedPost(msg.post_id);
if (post) {
post.set('polls', msg.polls);
}
});
},
unsubscribe(){
this.messageBus.unsubscribe('/polls/*');
this._super();
}
});
// overwrite polls
@@ -32,12 +61,16 @@ export default {
@on("postViewInserted", "postViewUpdated")
_createPollViews($post) {
const post = this.get("post"),
polls = post.get("polls"),
votes = post.get("polls_votes") || {};
post.pollsChanged();
const polls = post.get("pollsObject");
// don't even bother when there's no poll
if (!polls) { return; }
// TODO inject cleanly into
// clean-up if needed
this._cleanUpPollViews();
@@ -55,23 +88,11 @@ export default {
pollViews[pollName] = pollView;
});
messageBus.subscribe(`/polls/${this.get("post.id")}`, results => {
if (results && results.polls) {
_.forEach(results.polls, poll => {
if (pollViews[poll.name]) {
pollViews[poll.name].get("controller").set("model", Em.Object.create(poll));
}
});
}
});
this.set("pollViews", pollViews);
},
@on("willClearRender")
_cleanUpPollViews() {
messageBus.unsubscribe(`/polls/${this.get("post.id")}`);
if (this.get("pollViews")) {
_.forEach(this.get("pollViews"), v => v.destroy());
}

View File

@@ -5,11 +5,13 @@ function sumsUpTo100(percentages) {
export default (percentages) => {
const sumOfDecimals = Math.ceil(percentages.map(a => a % 1).reduce((a, b) => a + b));
// compensate error by adding 1 to the first n items
for (let i = 0; i < sumOfDecimals; i++) {
percentages[i] = ++percentages[i];
// quit early when there is a rounding issue
if (sumsUpTo100(percentages)) break;
// compensate error by adding 1 to the first n "non-zero" items
for (let i = 0, max = percentages.length; i < sumOfDecimals && i < max; i++) {
if (percentages[i] > 0) {
percentages[i] = ++percentages[i];
// quit early when there is a rounding issue
if (sumsUpTo100(percentages)) break;
}
}
return percentages.map(p => Math.floor(p));
};

View File

@@ -10,7 +10,7 @@ fi:
poll:
voters:
one: "äänestäjä"
other: "äänestäjät"
other: "äänestäjää"
total_votes:
one: "ääni"
other: "ääntä"

View File

@@ -8,9 +8,29 @@
ro:
js:
poll:
voters:
one: "participant"
few: "participanți"
other: "participanți"
total_votes:
one: "un vot"
few: "total voturi"
other: "total voturi"
average_rating: "Media: <strong>%{average}</strong>."
multiple:
help:
at_least_min_options:
one: "Trebuie să selectați cel puțin <strong>1</strong> opțiune."
few: "Trebuie să selectați cel puțin <strong>%{count}</strong> opțiuni."
other: "Trebuie să selectați cel puțin <strong>%{count}</strong> opțiuni."
up_to_max_options:
one: "Puteţi alege cel mult o <strong>%{count}</strong> opţiune."
few: "Puteţi selecta cel mult <strong>1</strong> opţiune."
other: "Puteți selecta până la <strong>%{count}</strong> opțiuni."
x_options:
one: "Trebuie să selectați <strong>1</strong> opțiune."
few: "Trebuie să selectați <strong>%{count}</strong> opțiuni."
other: "Trebuie să alegeți <strong>%{count}</strong> opțiuni."
between_min_and_max_options: "Puteţi alege între <strong>%{min}</strong> şi <strong>%{max}</strong> opţiuni."
cast-votes:
title: "Exprimaţi-vă votul"
@@ -26,8 +46,8 @@ ro:
label: "Deschis"
confirm: "Sunteţi sigur că doriţi să deschideţi acest sondaj?"
close:
title: "Închide sondaj"
label: "Închis"
title: "Închideți sondajul"
label: "Închideți"
confirm: "Sunteţi sigur că vreţi să închideţi acest sondaj?"
error_while_toggling_status: "A apărut o eroare în timpul schimbării stării acestui sondaj."
error_while_casting_votes: "A apărut o eroare în timpul exprimării votului dvs."

View File

@@ -0,0 +1,53 @@
# encoding: utf-8
#
# Never edit this file. It will be overwritten when translations are pulled from Transifex.
#
# To work with us on translations, join this project:
# https://www.transifex.com/projects/p/discourse-org/
sk:
js:
poll:
voters:
one: "volič"
few: "voliči"
other: "voliči"
total_votes:
one: "hlas celkom"
few: "hlasy celkom"
other: "hlasov celkom"
average_rating: "Priemerné hodnotenie: <strong>%{average}</strong>."
multiple:
help:
at_least_min_options:
one: "Musíte si vybrať minimálne <strong>%{count}</strong> možnosť."
few: "Musíte si vybrať minimálne <strong>%{count}</strong> možnosti."
other: "Musíte si vybrať minimálne <strong>%{count}</strong> možností."
up_to_max_options:
one: "Môžete si vybrať maximálne <strong>%{count}</strong> možnosť."
few: "Môžete si vybrať maximálne <strong>%{count}</strong> možnosti."
other: "Môžete si vybrať maximálne <strong>%{count}</strong> možností."
x_options:
one: "Musíte si vybrať <strong>%{count}</strong> možnosť."
few: "Musíte si vybrať <strong>%{count}</strong> možnosti."
other: "Musíte si vybrať <strong>%{count}</strong> možností."
between_min_and_max_options: "Môžete si vybrať medzi možnosťami <strong>%{min}</strong> až <strong>%{max}</strong>."
cast-votes:
title: "Hlasovať"
label: "Hlasuj teraz!"
show-results:
title: "Zobraz výsledky hlasovania"
label: "Zobraz výsledky"
hide-results:
title: "Návrat na odovzdané hlasy"
label: "Skyť výsledky"
open:
title: "Zahájiť hlasovanie"
label: "Zahájiť"
confirm: "Ste si istý, že chcete zahájiť toto hlasovanie?"
close:
title: "Zatvoriť hlasovanie"
label: "Zatvoriť"
confirm: "Ste si istý, že chcete zatvoriť toto hlasovanie?"
error_while_toggling_status: "Pri zmene stavu hlasovania sa vyskytla chyba."
error_while_casting_votes: "Pri hlasovaní sa vyskytla chyba."

View File

@@ -5,4 +5,37 @@
# To work with us on translations, join this project:
# https://www.transifex.com/projects/p/discourse-org/
ro: {}
ro:
site_settings:
poll_enabled: "Permiți utilizatorilor să creeze sondaje?"
poll_maximum_options: "Numărul maxim admis de opțiuni într-un sondaj"
poll:
multiple_polls_without_name: "Există mai multe sondaje fără nume. Folosește atributul '<code>name</code>' pentru a identifica sondajele proprii"
multiple_polls_with_same_name: "Există mai multe sondaje cu același nume: <strong>%{name}</strong>. Folosește atributul '<code>name</code>' pentru a identifica sondajele proprii."
default_poll_must_have_at_least_2_options: "Sondajul trebuie să aibă cel puțin 2 opțiuni."
named_poll_must_have_at_least_2_options: "Sondajul numit <strong>%{name}</strong> trebuie să aibă cel puțin 2 opțiuni."
default_poll_must_have_less_options:
one: "Sondajul trebuie să aibă mai puțin de 1 opțiune."
few: "Sondajul trebuie să conțină cel mult %{count} opțiuni."
other: "Sondajul trebuie să aibă mai puțin de %{count} opțiuni."
named_poll_must_have_less_options:
one: "Sondajul numit <strong>%{name}</strong> trebuie să aibă cel mult 1 opțiune."
few: "Sondajul numit <strong>%{name}</strong> trebuie să aibă mai puțin de %{count} opțiuni."
other: "Sondajul numit <strong>%{name}</strong> trebuie să aibă cel mult %{count} opțiuni."
default_poll_must_have_different_options: "Sondajul trebuie să aibă opțiuni diferite."
named_poll_must_have_different_options: "Sondajul numit <strong>%{name}</strong> trebuie să aibă opțiuni diferite."
default_poll_with_multiple_choices_has_invalid_parameters: "Sondajul cu opțiuni multiple are parametri invalizi."
named_poll_with_multiple_choices_has_invalid_parameters: "Sondajul numit <strong>%{name}</strong> cu opțiuni multiple are parametri invalizi."
requires_at_least_1_valid_option: "Trebuie să selectezi cel puțin 1 valoare validă."
cannot_change_polls_after_5_minutes: "Nu poți adăuga, elimina sau redenumi sondaje după primele 5 minute."
op_cannot_edit_options_after_5_minutes: "Nu poți adăuga sau elimina opțiuni ale unui sondaj după primele 5 minute. Te rugăm contactează un moderator pentru a edita o opțiune din sondaj."
staff_cannot_add_or_remove_options_after_5_minutes: "Nu poți adăuga sau elimina opțiuni ale unui sondaj după primele 5 minute. Ar trebui să închizi discuția și să creezi alta în loc."
no_polls_associated_with_this_post: "Nu există sondaje asociate acestei postări."
no_poll_with_this_name: "Nu există nici un sondaj cu numele <strong>%{name}</strong> asociat acestei postări."
post_is_deleted: "Postările șterse nu se pot modifica."
topic_must_be_open_to_vote: "Discuția trebuie să fie activă pentru a se putea vota."
poll_must_be_open_to_vote: "Sondajul trebuie să fie deschis pentru a se putea vota."
topic_must_be_open_to_toggle_status: "Discuția trebuie să fie activă pentru a se schimba statutul."
only_staff_or_op_can_toggle_status: "Doar un administrator sau autorul postării inițiale pot schimba statusul unui sondaj."
email:
link_to_poll: "Click pentru afișarea sondajului."

View File

@@ -0,0 +1,41 @@
# encoding: utf-8
#
# Never edit this file. It will be overwritten when translations are pulled from Transifex.
#
# To work with us on translations, join this project:
# https://www.transifex.com/projects/p/discourse-org/
sk:
site_settings:
poll_enabled: "Umožnit používaťeľom vytvárať hlasovania?"
poll_maximum_options: "Maximálny počet povolených možností v hlasovaní."
poll:
multiple_polls_without_name: "Existujú viaceré hlasovania bez mena. Použite atribút '<code>meno</code>', aby ste hlasovanie jednoznačne rozlíšili."
multiple_polls_with_same_name: "Existujú viaceré hlasovania s rovnakým menom: <strong>%{name}</strong>. Použite atribút '<code>meno</code>', aby ste hlasovanie jednoznačne rozlíšili."
default_poll_must_have_at_least_2_options: "Hlasovanie musí mať minimálne 2 možnosti."
named_poll_must_have_at_least_2_options: "Hlasovanie s názvom <strong>%{name}</strong> musí mať minimálne 2 možnosti."
default_poll_must_have_less_options:
one: "Hlasovanie musí mať menej ako jednu možnosť."
few: "Hlasovanie musí mať menej ako %{count} možnosti."
other: "Hlasovanie musí mať menej ako %{count} možnosti."
named_poll_must_have_less_options:
one: "Hlasovanie s názvom <strong>%{name}</strong> musí mať menej ako 1 možnost."
few: "Hlasovanie s názvom <strong>%{name}</strong> musí mať menej ako %{count} možnosti."
other: "Hlasovanie s názvom <strong>%{name}</strong> musí mať menej ako %{count} možností."
default_poll_must_have_different_options: "Hlasovanie musí mať rôzne možnosti."
named_poll_must_have_different_options: "Hlasovanie s názvom <strong>%{name}</strong> musí mať rôzne možnosti."
default_poll_with_multiple_choices_has_invalid_parameters: "Hlasovanie s viac možnosťami má nesprávne parametre."
named_poll_with_multiple_choices_has_invalid_parameters: "Hlasovanie s názvom <strong>%{name}</strong> s viac možnosťami má nesprávne parametre."
requires_at_least_1_valid_option: "Musite vybrať aspoň 1 platnú možnosť."
cannot_change_polls_after_5_minutes: "Po prvých 5 minútach už nemôžete pridať, odstrániť alebo premenovať hlasovanie."
op_cannot_edit_options_after_5_minutes: "Po prvých 5 minútach už nemôžete pridať alebo odstrániť možnosti hlasovania. Ak potrebujete upraviť možnosti hlasovania prosím kontaktujte moderátora."
staff_cannot_add_or_remove_options_after_5_minutes: "Po prvých 5 minútach už nemôžete pridať alebo odstrániť možnosti hlasovania. Miesto toho by ste mali uzavrieť túto tému a miesto nej vytvoriť inú."
no_polls_associated_with_this_post: "S týmto príspevkom nie sú spojené žiadne hlasovania."
no_poll_with_this_name: "S týmto príspevkom nie je spojené žiadne hlasovanie s názvom <strong>%{name}</strong>."
post_is_deleted: "Na vymazanom príspevku nie je možné vykonať."
topic_must_be_open_to_vote: "Na odovzdanie hlasu téma otvorená."
poll_must_be_open_to_vote: "Na odovzdanie hlasu musí byť hlasovanie otvorené."
topic_must_be_open_to_toggle_status: "Na zmenu stavu musí byť téma otvorená."
only_staff_or_op_can_toggle_status: "Zmeniť stav hlasovania môže iba zamestnanec alebo pôvodný prispievateľ."
email:
link_to_poll: "Kliknite na zobrazenie hlasovania."

View File

@@ -81,7 +81,7 @@ after_initialize do
post.custom_fields[VOTES_CUSTOM_FIELD]["#{user_id}"] ||= {}
post.custom_fields[VOTES_CUSTOM_FIELD]["#{user_id}"][poll_name] = options
post.custom_fields[VOTES_CUSTOM_FIELD].each do |user_id, user_votes|
post.custom_fields[VOTES_CUSTOM_FIELD].each do |_, user_votes|
next unless votes = user_votes[poll_name]
votes.each { |option| all_options[option] += 1 }
poll["voters"] += 1 if (available_options & votes.to_set).size > 0
@@ -92,7 +92,7 @@ after_initialize do
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
post.save_custom_fields(true)
MessageBus.publish("/polls/#{post_id}", { polls: polls })
MessageBus.publish("/polls/#{post.topic_id}", { post_id: post_id, polls: polls })
return [poll, options]
end
@@ -128,7 +128,7 @@ after_initialize do
post.save_custom_fields(true)
MessageBus.publish("/polls/#{post_id}", { polls: polls })
MessageBus.publish("/polls/#{post.topic_id}", {post_id: post.id, polls: polls })
polls[poll_name]
end
@@ -350,7 +350,7 @@ after_initialize do
post.save_custom_fields(true)
# publish the changes
MessageBus.publish("/polls/#{post.id}", { polls: polls })
MessageBus.publish("/polls/#{post.topic_id}", { post_id: post.id, polls: polls })
end
end
else
@@ -370,7 +370,9 @@ after_initialize do
# tells the front-end we have a poll for that post
on(:post_created) do |post|
next if post.is_first_post? || post.custom_fields[POLLS_CUSTOM_FIELD].blank?
MessageBus.publish("/polls", { post_id: post.id })
MessageBus.publish("/polls/#{post.topic_id}", {
post_id: post.id,
polls: post.custom_fields[POLLS_CUSTOM_FIELD]})
end
add_to_serializer(:post, :polls, false) { post_custom_fields[POLLS_CUSTOM_FIELD] }