mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
FEATURE: unified UI for pinning/banner topics
REFACTOR: ES6ified all the modals
This commit is contained in:
@ -1,5 +1,4 @@
|
|||||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
|
|
||||||
import ObjectController from 'discourse/controllers/object';
|
import ObjectController from 'discourse/controllers/object';
|
||||||
|
|
||||||
export default ObjectController.extend(ModalFunctionality, {
|
export default ObjectController.extend(ModalFunctionality, {
|
@ -1,7 +1,7 @@
|
|||||||
import ChangeSiteCustomizationDetailsController from "admin/controllers/change-site-customization-details";
|
import ChangeSiteCustomizationDetailsController from "admin/controllers/modals/change-site-customization-details";
|
||||||
|
|
||||||
export default ChangeSiteCustomizationDetailsController.extend({
|
export default ChangeSiteCustomizationDetailsController.extend({
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
this.selectPrevious();
|
this.send("selectPrevious");
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -25,7 +25,7 @@ export default Ember.Route.extend({
|
|||||||
|
|
||||||
editGroupings() {
|
editGroupings() {
|
||||||
const groupings = this.controllerFor('admin-badges').get('badgeGroupings');
|
const groupings = this.controllerFor('admin-badges').get('badgeGroupings');
|
||||||
showModal('admin_edit_badge_groupings', groupings);
|
showModal('modals/admin-edit-badge-groupings', groupings);
|
||||||
},
|
},
|
||||||
|
|
||||||
preview(badge, explain) {
|
preview(badge, explain) {
|
||||||
@ -40,7 +40,7 @@ export default Ember.Route.extend({
|
|||||||
}
|
}
|
||||||
}).then(function(json) {
|
}).then(function(json) {
|
||||||
badge.set('preview_loading', false);
|
badge.set('preview_loading', false);
|
||||||
showModal('admin_badge_preview', json);
|
showModal('modals/admin-badge-preview', json);
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
badge.set('preview_loading', false);
|
badge.set('preview_loading', false);
|
||||||
Em.Logger.error(error);
|
Em.Logger.error(error);
|
||||||
|
@ -13,12 +13,12 @@ export default Discourse.Route.extend({
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
showAgreeFlagModal(flaggedPost) {
|
showAgreeFlagModal(flaggedPost) {
|
||||||
showModal('admin_agree_flag', flaggedPost);
|
showModal('modals/admin-agree-flag', flaggedPost);
|
||||||
this.controllerFor('modal').set('modalClass', 'agree-flag-modal');
|
this.controllerFor('modal').set('modalClass', 'agree-flag-modal');
|
||||||
},
|
},
|
||||||
|
|
||||||
showDeleteFlagModal(flaggedPost) {
|
showDeleteFlagModal(flaggedPost) {
|
||||||
showModal('admin_delete_flag', flaggedPost);
|
showModal('modals/admin-delete-flag', flaggedPost);
|
||||||
this.controllerFor('modal').set('modalClass', 'delete-flag-modal');
|
this.controllerFor('modal').set('modalClass', 'delete-flag-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +13,13 @@ export default Discourse.Route.extend({
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
showDetailsModal(logRecord) {
|
showDetailsModal(logRecord) {
|
||||||
showModal('admin_staff_action_log_details', logRecord);
|
showModal('modals/admin-staff-action-log-details', logRecord);
|
||||||
this.controllerFor('modal').set('modalClass', 'log-details-modal');
|
this.controllerFor('modal').set('modalClass', 'log-details-modal');
|
||||||
},
|
},
|
||||||
|
|
||||||
showCustomDetailsModal(logRecord) {
|
showCustomDetailsModal(logRecord) {
|
||||||
showModal(logRecord.action_name + '_details', logRecord);
|
const modalName = "modals/" + (logRecord.action_name + '_details').replace("_", "-");
|
||||||
|
showModal(modalName, logRecord);
|
||||||
this.controllerFor('modal').set('modalClass', 'tabbed-modal log-details-modal');
|
this.controllerFor('modal').set('modalClass', 'tabbed-modal log-details-modal');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ export default Discourse.Route.extend({
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
showSuspendModal(user) {
|
showSuspendModal(user) {
|
||||||
showModal('admin_suspend_user', user);
|
showModal('modals/admin-suspend-user', user);
|
||||||
this.controllerFor('modal').set('modalClass', 'suspend-user-modal');
|
this.controllerFor('modal').set('modalClass', 'suspend-user-modal');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
Discourse.AdminAgreeFlagView = Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'admin/templates/modal/admin_agree_flag',
|
templateName: 'admin/templates/modal/admin_agree_flag',
|
||||||
title: I18n.t('admin.flags.agree_flag_modal_title')
|
title: I18n.t('admin.flags.agree_flag_modal_title')
|
||||||
});
|
});
|
@ -1,5 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
Discourse.AdminBadgePreviewView = Discourse.ModalBodyView.extend({
|
export default ModalBodyView.extend({
|
||||||
templateName: 'admin/templates/modal/admin_badge_preview',
|
templateName: 'admin/templates/modal/admin_badge_preview',
|
||||||
title: I18n.t('admin.badges.preview.modal_title')
|
title: I18n.t('admin.badges.preview.modal_title')
|
||||||
});
|
});
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/modal/admin_delete_flag',
|
||||||
|
title: I18n.t('admin.flags.delete_flag_modal_title')
|
||||||
|
});
|
@ -1,5 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
Discourse.AdminEditBadgeGroupingsView = Discourse.ModalBodyView.extend({
|
export default ModalBodyView.extend({
|
||||||
templateName: 'admin/templates/modal/admin_edit_badge_groupings',
|
templateName: 'admin/templates/modal/admin_edit_badge_groupings',
|
||||||
title: I18n.t('admin.badges.badge_groupings.modal_title')
|
title: I18n.t('admin.badges.badge_groupings.modal_title')
|
||||||
});
|
});
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/logs/details_modal',
|
||||||
|
title: I18n.t('admin.logs.staff_actions.modal_title')
|
||||||
|
});
|
@ -1,4 +1,6 @@
|
|||||||
Discourse.AdminStartBackupView = Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'admin/templates/modal/admin_start_backup',
|
templateName: 'admin/templates/modal/admin_start_backup',
|
||||||
title: I18n.t('admin.backups.operations.backup.confirm')
|
title: I18n.t('admin.backups.operations.backup.confirm')
|
||||||
});
|
});
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/modal/admin_suspend_user',
|
||||||
|
title: I18n.t('admin.user.suspend_modal_title')
|
||||||
|
});
|
@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
A modal view for deleting a flag.
|
|
||||||
|
|
||||||
@class AdminDeleteFlagView
|
|
||||||
@extends Discourse.ModalBodyView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminDeleteFlagView = Discourse.ModalBodyView.extend({
|
|
||||||
templateName: 'admin/templates/modal/admin_delete_flag',
|
|
||||||
title: I18n.t('admin.flags.delete_flag_modal_title')
|
|
||||||
});
|
|
@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
A modal view for details of a staff action log record in a modal.
|
|
||||||
|
|
||||||
@class AdminStaffActionLogDetailsView
|
|
||||||
@extends Discourse.ModalBodyView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminStaffActionLogDetailsView = Discourse.ModalBodyView.extend({
|
|
||||||
templateName: 'admin/templates/logs/details_modal',
|
|
||||||
title: I18n.t('admin.logs.staff_actions.modal_title')
|
|
||||||
});
|
|
@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
A modal view for suspending a user.
|
|
||||||
|
|
||||||
@class AdminSuspendUserView
|
|
||||||
@extends Discourse.ModalBodyView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminSuspendUserView = Discourse.ModalBodyView.extend({
|
|
||||||
templateName: 'admin/templates/modal/admin_suspend_user',
|
|
||||||
title: I18n.t('admin.user.suspend_modal_title')
|
|
||||||
});
|
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/logs/site_customization_change_modal',
|
||||||
|
title: I18n.t('admin.logs.staff_actions.modal_title')
|
||||||
|
});
|
@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
A modal view for details of a staff action log record in a modal
|
|
||||||
for when a site customization is created or changed.
|
|
||||||
|
|
||||||
@class ChangeSiteCustomizationDetailsView
|
|
||||||
@extends Discourse.ModalBodyView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.ChangeSiteCustomizationDetailsView = Discourse.ModalBodyView.extend({
|
|
||||||
templateName: 'admin/templates/logs/site_customization_change_modal',
|
|
||||||
title: I18n.t('admin.logs.staff_actions.modal_title')
|
|
||||||
});
|
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/logs/site_customization_change_modal',
|
||||||
|
title: I18n.t('admin.logs.staff_actions.modal_title')
|
||||||
|
});
|
@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
A modal view for details of a staff action log record in a modal
|
|
||||||
for when a site customization is deleted.
|
|
||||||
|
|
||||||
@class DeleteSiteCustomizationDetailsView
|
|
||||||
@extends Discourse.ModalBodyView
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.DeleteSiteCustomizationDetailsView = Discourse.ModalBodyView.extend({
|
|
||||||
templateName: 'admin/templates/logs/site_customization_change_modal',
|
|
||||||
title: I18n.t('admin.logs.staff_actions.modal_title')
|
|
||||||
});
|
|
@ -0,0 +1,77 @@
|
|||||||
|
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
|
import ObjectController from 'discourse/controllers/object';
|
||||||
|
import { categoryLinkHTML } from 'discourse/helpers/category-link';
|
||||||
|
|
||||||
|
export default ObjectController.extend(ModalFunctionality, {
|
||||||
|
needs: ["topic"],
|
||||||
|
|
||||||
|
loading: true,
|
||||||
|
pinnedInCategoryCount: 0,
|
||||||
|
pinnedGloballyCount: 0,
|
||||||
|
bannerCount: 0,
|
||||||
|
|
||||||
|
categoryLink: function() {
|
||||||
|
return categoryLinkHTML(this.get("category"), { allowUncategorized: true });
|
||||||
|
}.property("category"),
|
||||||
|
|
||||||
|
unPinMessage: function() {
|
||||||
|
return this.get("pinned_globally") ?
|
||||||
|
I18n.t("topic.feature_topic.unpin_globally") :
|
||||||
|
I18n.t("topic.feature_topic.unpin", { categoryLink: this.get("categoryLink") });
|
||||||
|
}.property("categoryLink", "pinned_globally"),
|
||||||
|
|
||||||
|
pinMessage: function() {
|
||||||
|
return I18n.t("topic.feature_topic.pin", { categoryLink: this.get("categoryLink") });
|
||||||
|
}.property("categoryLink"),
|
||||||
|
|
||||||
|
alreadyPinnedMessage: function() {
|
||||||
|
return I18n.t("topic.feature_topic.already_pinned", { categoryLink: this.get("categoryLink"), count: this.get("pinnedInCategoryCount") });
|
||||||
|
}.property("categoryLink", "pinnedInCategoryCount"),
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
this.set("loading", true);
|
||||||
|
|
||||||
|
return Discourse.ajax("/topics/feature_stats.json", {
|
||||||
|
data: { category_id: this.get("category.id") }
|
||||||
|
}).then(function(result) {
|
||||||
|
if (result) {
|
||||||
|
self.setProperties({
|
||||||
|
pinnedInCategoryCount: result.pinned_in_category_count,
|
||||||
|
pinnedGloballyCount: result.pinned_globally_count,
|
||||||
|
bannerCount: result.banner_count,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).finally(function() {
|
||||||
|
self.set("loading", false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_forwardAction(name) {
|
||||||
|
this.get("controllers.topic").send(name);
|
||||||
|
this.send("closeModal");
|
||||||
|
},
|
||||||
|
|
||||||
|
_confirmBeforePinning(count, name, action) {
|
||||||
|
if (count < 4) {
|
||||||
|
this._forwardAction(action);
|
||||||
|
} else {
|
||||||
|
this.send("hideModal");
|
||||||
|
const message = I18n.t("topic.feature_topic.confirm_" + name, { count: count });
|
||||||
|
bootbox.confirm(
|
||||||
|
message, I18n.t("no_value"), I18n.t("yes_value"),
|
||||||
|
(confirmed) => confirmed ? this._forwardAction(action) : this.send("reopenModal")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
pin() { this._confirmBeforePinning(this.get("pinnedInCategoryCount"), "pin", "togglePinned"); },
|
||||||
|
pinGlobally() { this._confirmBeforePinning(this.get("pinnedGloballyCount"), "pin_globally", "pinGlobally"); },
|
||||||
|
unpin() { this._forwardAction("togglePinned"); },
|
||||||
|
makeBanner() { this._forwardAction("makeBanner"); },
|
||||||
|
removeBanner() { this._forwardAction("removeBanner"); },
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@ -94,6 +94,19 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, BufferedCon
|
|||||||
this.set('selectedReplies', []);
|
this.set('selectedReplies', []);
|
||||||
}.on('init'),
|
}.on('init'),
|
||||||
|
|
||||||
|
_togglePinnedStates(property) {
|
||||||
|
const value = this.get('pinned_at') ? false : true,
|
||||||
|
topic = this.get('content');
|
||||||
|
|
||||||
|
// optimistic update
|
||||||
|
topic.setProperties({
|
||||||
|
pinned_at: value,
|
||||||
|
pinned_globally: value
|
||||||
|
});
|
||||||
|
|
||||||
|
return topic.saveStatus(property, value);
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
deleteTopic() {
|
deleteTopic() {
|
||||||
this.deleteTopic();
|
this.deleteTopic();
|
||||||
@ -352,13 +365,28 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, BufferedCon
|
|||||||
},
|
},
|
||||||
|
|
||||||
togglePinned() {
|
togglePinned() {
|
||||||
// Note that this is different than clearPin
|
const value = this.get('pinned_at') ? false : true,
|
||||||
this.get('content').setStatus('pinned', this.get('pinned_at') ? false : true);
|
topic = this.get('content');
|
||||||
|
|
||||||
|
// optimistic update
|
||||||
|
topic.setProperties({
|
||||||
|
pinned_at: value ? moment() : null,
|
||||||
|
pinned_globally: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return topic.saveStatus("pinned", value);
|
||||||
},
|
},
|
||||||
|
|
||||||
togglePinnedGlobally() {
|
pinGlobally() {
|
||||||
// Note that this is different than clearPin
|
const topic = this.get('content');
|
||||||
this.get('content').setStatus('pinned_globally', this.get('pinned_at') ? false : true);
|
|
||||||
|
// optimistic update
|
||||||
|
topic.setProperties({
|
||||||
|
pinned_at: moment(),
|
||||||
|
pinned_globally: true
|
||||||
|
});
|
||||||
|
|
||||||
|
return topic.saveStatus("pinned_globally", true);
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleArchived() {
|
toggleArchived() {
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
export default function showModal(name, model) {
|
export default function showModal(name, model) {
|
||||||
|
|
||||||
// We use the container here because modals are like singletons
|
// We use the container here because modals are like singletons
|
||||||
// in Discourse. Only one can be shown with a particular state.
|
// in Discourse. Only one can be shown with a particular state.
|
||||||
const route = Discourse.__container__.lookup('route:application');
|
const route = Discourse.__container__.lookup('route:application');
|
||||||
|
|
||||||
route.controllerFor('modal').set('modalClass', null);
|
route.controllerFor('modal').set('modalClass', null);
|
||||||
route.render(name, {into: 'modal', outlet: 'modalBody'});
|
route.render(name, { into: 'modal', outlet: 'modalBody' });
|
||||||
|
|
||||||
const controller = route.controllerFor(name);
|
const controller = route.controllerFor(name);
|
||||||
if (controller) {
|
if (controller) {
|
||||||
if (model) {
|
if (model) { controller.set('model', model); }
|
||||||
controller.set('model', model);
|
if (controller.onShow) { controller.onShow(); }
|
||||||
}
|
|
||||||
if (controller.onShow) {
|
|
||||||
controller.onShow();
|
|
||||||
}
|
|
||||||
controller.set('flashMessage', null);
|
controller.set('flashMessage', null);
|
||||||
}
|
}
|
||||||
return controller;
|
return controller;
|
||||||
|
@ -145,24 +145,16 @@ const Topic = Discourse.Model.extend({
|
|||||||
|
|
||||||
toggleStatus(property) {
|
toggleStatus(property) {
|
||||||
this.toggleProperty(property);
|
this.toggleProperty(property);
|
||||||
this.saveStatus(property, this.get(property) ? true : false);
|
this.saveStatus(property, !this.get(property));
|
||||||
},
|
|
||||||
|
|
||||||
setStatus(property, value) {
|
|
||||||
this.set(property, value);
|
|
||||||
this.saveStatus(property, value);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
saveStatus(property, value) {
|
saveStatus(property, value) {
|
||||||
if (property === 'closed' && value === true) {
|
if (property === 'closed' && value === true) {
|
||||||
this.set('details.auto_close_at', null);
|
this.set('details.auto_close_at', null);
|
||||||
}
|
}
|
||||||
if (property === 'pinned') {
|
|
||||||
this.set('pinned_at', value ? moment() : null);
|
|
||||||
}
|
|
||||||
return Discourse.ajax(this.get('url') + "/status", {
|
return Discourse.ajax(this.get('url') + "/status", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {status: property, enabled: value ? 'true' : 'false' }
|
data: { status: property, enabled: !!value }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ const ApplicationRoute = Discourse.Route.extend({
|
|||||||
|
|
||||||
// Close the current modal, and destroy its state.
|
// Close the current modal, and destroy its state.
|
||||||
closeModal() {
|
closeModal() {
|
||||||
this.render('hide-modal', {into: 'modal', outlet: 'modalBody'});
|
this.render('hide-modal', { into: 'modal', outlet: 'modalBody' });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,6 +59,11 @@ const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
|||||||
this.controllerFor('modal').set('modalClass', 'edit-auto-close-modal');
|
this.controllerFor('modal').set('modalClass', 'edit-auto-close-modal');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showFeatureTopic() {
|
||||||
|
showModal('featureTopic', this.modelFor('topic'));
|
||||||
|
this.controllerFor('modal').set('modalClass', 'feature-topic-modal');
|
||||||
|
},
|
||||||
|
|
||||||
showInvite() {
|
showInvite() {
|
||||||
showModal('invite', this.modelFor('topic'));
|
showModal('invite', this.modelFor('topic'));
|
||||||
this.controllerFor('invite').reset();
|
this.controllerFor('invite').reset();
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
<div class="modal-body">
|
||||||
|
{{#if pinned_at}}
|
||||||
|
<div>
|
||||||
|
{{d-button action="unpin" icon="thumb-tack" label="topic.actions.unpin" class="btn-primary btn-small"}}
|
||||||
|
<p>{{{unPinMessage}}}</p>
|
||||||
|
{{#if pinned_globally}}
|
||||||
|
<p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
|
||||||
|
<p>
|
||||||
|
{{#loading-spinner size="small" condition=loading}}
|
||||||
|
{{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
</p>
|
||||||
|
{{else}}
|
||||||
|
<p>{{i18n "topic.feature_topic.pin_note"}}</p>
|
||||||
|
<p>
|
||||||
|
{{#loading-spinner size="small" condition=loading}}
|
||||||
|
{{{alreadyPinnedMessage}}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div>
|
||||||
|
{{d-button action="pin" icon="thumb-tack" label="topic.actions.pin" class="btn-primary btn-small"}}
|
||||||
|
<p>{{{pinMessage}}}</p>
|
||||||
|
<p>{{i18n "topic.feature_topic.pin_note"}}</p>
|
||||||
|
<p>
|
||||||
|
{{#loading-spinner size="small" condition=loading}}
|
||||||
|
{{{alreadyPinnedMessage}}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{d-button action="pinGlobally" icon="thumb-tack" label="topic.actions.pin_globally" class="btn-primary btn-small"}}
|
||||||
|
<p>{{i18n "topic.feature_topic.pin_globally"}}</p>
|
||||||
|
<p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
|
||||||
|
<p>
|
||||||
|
{{#loading-spinner size="small" condition=loading}}
|
||||||
|
{{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div>
|
||||||
|
{{#if isBanner}}
|
||||||
|
{{d-button action="removeBanner" icon="bullhorn" label="topic.actions.remove_banner" class="btn-primary btn-small"}}
|
||||||
|
<p>{{i18n "topic.feature_topic.remove_banner"}}</p>
|
||||||
|
{{else}}
|
||||||
|
{{d-button action="makeBanner" icon="bullhorn" label="topic.actions.make_banner" class="btn-primary btn-small"}}
|
||||||
|
<p>{{i18n "topic.feature_topic.make_banner"}}</p>
|
||||||
|
{{/if}}
|
||||||
|
<p>{{i18n "topic.feature_topic.banner_note"}}</p>
|
||||||
|
<p>
|
||||||
|
{{#loading-spinner size="small" condition=loading}}
|
||||||
|
{{{i18n "topic.feature_topic.already_banner" count=bannerCount}}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="pull-right" {{action "closeModal"}}>{{i18n "cancel"}}</a>
|
||||||
|
</div>
|
@ -27,26 +27,11 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
{{#unless isPrivateMessage}}
|
{{#unless isPrivateMessage}}
|
||||||
<li>
|
{{#if visible}}
|
||||||
{{#if isBanner}}
|
<li>
|
||||||
{{d-button action="removeBanner" icon="bullhorn" label="topic.actions.remove_banner" class="btn-admin"}}
|
{{d-button action="showFeatureTopic" icon="bullhorn" label="topic.actions.feature" class="btn-admin"}}
|
||||||
{{else}}
|
</li>
|
||||||
{{#if visible}}
|
{{/if}}
|
||||||
{{d-button action="makeBanner" icon="bullhorn" label="topic.actions.make_banner" class="btn-admin"}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
{{#if pinned_at}}
|
|
||||||
{{d-button action="togglePinned" icon="thumb-tack" label="topic.actions.unpin" class="btn-admin"}}
|
|
||||||
{{else}}
|
|
||||||
{{#if visible}}
|
|
||||||
{{d-button action="togglePinned" icon="thumb-tack" label="topic.actions.pin" class="btn-admin"}}
|
|
||||||
{{d-button action="togglePinnedGlobally" icon="thumb-tack" label="topic.actions.pin_globally" class="btn-admin"}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/archetype_options',
|
templateName: 'modal/archetype_options',
|
||||||
title: I18n.t('topic.options')
|
title: I18n.t('topic.options')
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/avatar_selector',
|
templateName: 'modal/avatar_selector',
|
||||||
classNames: ['avatar-selector'],
|
classNames: ['avatar-selector'],
|
||||||
title: I18n.t('user.change_avatar.title'),
|
title: I18n.t('user.change_avatar.title'),
|
||||||
@ -9,10 +11,6 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
// *HACK* used to select the proper radio button, cause {{action}}
|
// *HACK* used to select the proper radio button, cause {{action}}
|
||||||
// stops the default behavior
|
// stops the default behavior
|
||||||
selectedChanged: function() {
|
selectedChanged: function() {
|
||||||
var self = this;
|
Em.run.next(() => $('input:radio[name="avatar"]').val([this.get('controller.selected')]) );
|
||||||
Em.run.next(function() {
|
|
||||||
var value = self.get('controller.selected');
|
|
||||||
$('input:radio[name="avatar"]').val([value]);
|
|
||||||
});
|
|
||||||
}.observes('controller.selected')
|
}.observes('controller.selected')
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/change_owner',
|
templateName: 'modal/change_owner',
|
||||||
title: I18n.t('topic.change_owner.title')
|
title: I18n.t('topic.change_owner.title')
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/create-account',
|
templateName: 'modal/create-account',
|
||||||
title: I18n.t('create_account.title'),
|
title: I18n.t('create_account.title'),
|
||||||
classNames: ['create-account'],
|
classNames: ['create-account'],
|
||||||
@ -6,7 +8,7 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
_setup: function() {
|
_setup: function() {
|
||||||
// allows the submission the form when pressing 'ENTER' on *any* text input field
|
// allows the submission the form when pressing 'ENTER' on *any* text input field
|
||||||
// but only when the submit button is enabled
|
// but only when the submit button is enabled
|
||||||
var createAccountController = this.get('controller');
|
const createAccountController = this.get('controller');
|
||||||
Em.run.schedule('afterRender', function() {
|
Em.run.schedule('afterRender', function() {
|
||||||
$("input[type='text'], input[type='password']").keydown(function(e) {
|
$("input[type='text'], input[type='password']").keydown(function(e) {
|
||||||
if (createAccountController.get('submitDisabled') === false && e.keyCode === 13) {
|
if (createAccountController.get('submitDisabled') === false && e.keyCode === 13) {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/edit-category',
|
templateName: 'modal/edit-category',
|
||||||
|
|
||||||
_initializePanels: function() {
|
_initializePanels: function() {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/auto_close',
|
templateName: 'modal/auto_close',
|
||||||
title: I18n.t('topic.auto_close_title')
|
title: I18n.t('topic.auto_close_title')
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
|
templateName: 'modal/feature-topic',
|
||||||
|
title: I18n.t('topic.feature_topic.title')
|
||||||
|
});
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/flag',
|
templateName: 'modal/flag',
|
||||||
|
|
||||||
title: function() {
|
title: function() {
|
||||||
@ -6,12 +8,13 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
}.property('controller.flagTopic'),
|
}.property('controller.flagTopic'),
|
||||||
|
|
||||||
selectedChanged: function() {
|
selectedChanged: function() {
|
||||||
var self = this;
|
const self = this;
|
||||||
|
|
||||||
Em.run.next(function() {
|
Em.run.next(function() {
|
||||||
self.$("input[type='radio']").prop('checked', false);
|
self.$("input[type='radio']").prop('checked', false);
|
||||||
|
|
||||||
var nameKey = self.get('controller.selected.name_key');
|
const nameKey = self.get('controller.selected.name_key');
|
||||||
if (!nameKey) return;
|
if (!nameKey) { return; }
|
||||||
|
|
||||||
self.$('#radio_' + nameKey).prop('checked', 'true');
|
self.$('#radio_' + nameKey).prop('checked', 'true');
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/forgot_password',
|
templateName: 'modal/forgot_password',
|
||||||
title: I18n.t('forgot_password.title'),
|
title: I18n.t('forgot_password.title'),
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/history',
|
templateName: 'modal/history',
|
||||||
title: I18n.t('history'),
|
title: I18n.t('history'),
|
||||||
|
|
||||||
resizeModal: function(){
|
resizeModal: function(){
|
||||||
var viewPortHeight = $(window).height();
|
const viewPortHeight = $(window).height();
|
||||||
this.$(".modal-body").css("max-height", Math.floor(0.8 * viewPortHeight) + "px");
|
this.$(".modal-body").css("max-height", Math.floor(0.8 * viewPortHeight) + "px");
|
||||||
}.on("didInsertElement")
|
}.on("didInsertElement")
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/invite_private',
|
templateName: 'modal/invite_private',
|
||||||
title: I18n.t('topic.invite_private.title')
|
title: I18n.t('topic.invite_private.title')
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/invite',
|
templateName: 'modal/invite',
|
||||||
|
|
||||||
title: function() {
|
title: function() {
|
||||||
if (this.get('controller.invitingToTopic')) {
|
return this.get('controller.invitingToTopic') ?
|
||||||
return I18n.t('topic.invite_reply.title');
|
I18n.t('topic.invite_reply.title') :
|
||||||
} else {
|
I18n.t('user.invited.create');
|
||||||
return I18n.t('user.invited.create');
|
|
||||||
}
|
|
||||||
}.property('controller.invitingToTopic')
|
}.property('controller.invitingToTopic')
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/keyboard_shortcuts_help',
|
templateName: 'modal/keyboard_shortcuts_help',
|
||||||
title: I18n.t('keyboard_shortcuts_help.title')
|
title: I18n.t('keyboard_shortcuts_help.title')
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/login',
|
templateName: 'modal/login',
|
||||||
title: I18n.t('login.title'),
|
title: I18n.t('login.title'),
|
||||||
classNames: ['login-modal'],
|
classNames: ['login-modal'],
|
||||||
@ -9,7 +11,7 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_setup: function() {
|
_setup: function() {
|
||||||
var loginController = this.get('controller');
|
const loginController = this.get('controller');
|
||||||
|
|
||||||
// Get username and password from the browser's password manager,
|
// Get username and password from the browser's password manager,
|
||||||
// if it filled the hidden static login form:
|
// if it filled the hidden static login form:
|
||||||
@ -18,10 +20,8 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
|
|
||||||
Em.run.schedule('afterRender', function() {
|
Em.run.schedule('afterRender', function() {
|
||||||
$('#login-account-password, #login-account-name').keydown(function(e) {
|
$('#login-account-password, #login-account-name').keydown(function(e) {
|
||||||
if (e.keyCode === 13) {
|
if (e.keyCode === 13 && !loginController.get('loginDisabled')) {
|
||||||
if (!loginController.get('loginDisabled')) {
|
loginController.send('login');
|
||||||
loginController.send('login');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/merge_topic',
|
templateName: 'modal/merge_topic',
|
||||||
title: I18n.t('topic.merge_topic.title')
|
title: I18n.t('topic.merge_topic.title')
|
||||||
});
|
});
|
||||||
|
30
app/assets/javascripts/discourse/views/modal-body.js.es6
Normal file
30
app/assets/javascripts/discourse/views/modal-body.js.es6
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export default Discourse.View.extend({
|
||||||
|
focusInput: true,
|
||||||
|
|
||||||
|
_setupModal: function() {
|
||||||
|
$('#modal-alert').hide();
|
||||||
|
$('#discourse-modal').modal('show');
|
||||||
|
|
||||||
|
// Focus on first element
|
||||||
|
if (!Discourse.Mobile.mobileView && this.get('focusInput')) {
|
||||||
|
Em.run.schedule('afterRender', () => this.$('input:first').focus() );
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = this.get('title');
|
||||||
|
if (title) {
|
||||||
|
this.set('controller.controllers.modal.title', title);
|
||||||
|
}
|
||||||
|
}.on('didInsertElement'),
|
||||||
|
|
||||||
|
flashMessageChanged: function() {
|
||||||
|
const flashMessage = this.get('controller.flashMessage');
|
||||||
|
if (flashMessage) {
|
||||||
|
const messageClass = flashMessage.get('messageClass') || 'success';
|
||||||
|
$('#modal-alert').hide()
|
||||||
|
.removeClass('alert-error', 'alert-success')
|
||||||
|
.addClass("alert alert-" + messageClass).html(flashMessage.get('message'))
|
||||||
|
.fadeIn();
|
||||||
|
}
|
||||||
|
}.observes('controller.flashMessage')
|
||||||
|
|
||||||
|
});
|
@ -4,13 +4,13 @@ export default Ember.View.extend({
|
|||||||
classNameBindings: [':modal', ':hidden', 'controller.modalClass'],
|
classNameBindings: [':modal', ':hidden', 'controller.modalClass'],
|
||||||
|
|
||||||
click: function(e) {
|
click: function(e) {
|
||||||
var $target = $(e.target);
|
const $target = $(e.target);
|
||||||
if ($target.hasClass("modal-middle-container") ||
|
if ($target.hasClass("modal-middle-container") ||
|
||||||
$target.hasClass("modal-outer-container")) {
|
$target.hasClass("modal-outer-container")) {
|
||||||
// Delegate click to modal backdrop if clicked outside. We do this
|
// Delegate click to modal close if clicked outside.
|
||||||
// because some CSS of ours seems to cover the backdrop and makes it
|
// We do this because some CSS of ours seems to cover
|
||||||
// unclickable.
|
// the backdrop and makes it unclickable.
|
||||||
$('.modal-backdrop').click();
|
$('.modal-header a.close').click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
A base class for helping us display modal content
|
|
||||||
|
|
||||||
@class ModalBodyView
|
|
||||||
@extends Discourse.View
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.ModalBodyView = Discourse.View.extend({
|
|
||||||
focusInput: true,
|
|
||||||
|
|
||||||
_setupModal: function() {
|
|
||||||
var self = this,
|
|
||||||
$discourseModal = $('#discourse-modal');
|
|
||||||
|
|
||||||
$discourseModal.modal('show');
|
|
||||||
$discourseModal.one("hide", function () {
|
|
||||||
self.get("controller").send("closeModal");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#modal-alert').hide();
|
|
||||||
|
|
||||||
// Focus on first element
|
|
||||||
if (!Discourse.Mobile.mobileView && self.get('focusInput')) {
|
|
||||||
Em.run.schedule('afterRender', function() {
|
|
||||||
self.$('input:first').focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var title = this.get('title');
|
|
||||||
if (title) {
|
|
||||||
this.set('controller.controllers.modal.title', title);
|
|
||||||
}
|
|
||||||
}.on('didInsertElement'),
|
|
||||||
|
|
||||||
flashMessageChanged: function() {
|
|
||||||
var flashMessage = this.get('controller.flashMessage');
|
|
||||||
if (flashMessage) {
|
|
||||||
var messageClass = flashMessage.get('messageClass') || 'success';
|
|
||||||
var $alert = $('#modal-alert').hide().removeClass('alert-error', 'alert-success');
|
|
||||||
$alert.addClass("alert alert-" + messageClass).html(flashMessage.get('message'));
|
|
||||||
$alert.fadeIn();
|
|
||||||
}
|
|
||||||
}.observes('controller.flashMessage')
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/not_activated',
|
templateName: 'modal/not_activated',
|
||||||
title: I18n.t('log_in')
|
title: I18n.t('log_in')
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/raw_email',
|
templateName: 'modal/raw_email',
|
||||||
title: I18n.t('raw_email.title'),
|
title: I18n.t('raw_email.title'),
|
||||||
|
|
||||||
resizeModal: function(){
|
resizeModal: function(){
|
||||||
var viewPortHeight = $(window).height();
|
const viewPortHeight = $(window).height();
|
||||||
this.$(".modal-body").css("max-height", Math.floor(0.8 * viewPortHeight) + "px");
|
this.$(".modal-body").css("max-height", Math.floor(0.8 * viewPortHeight) + "px");
|
||||||
}.on("didInsertElement")
|
}.on("didInsertElement")
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/search_help',
|
templateName: 'modal/search_help',
|
||||||
title: I18n.t('search_help.title'),
|
title: I18n.t('search_help.title'),
|
||||||
focusInput: false
|
focusInput: false
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend(Discourse.SelectedPostsCount, {
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend(Discourse.SelectedPostsCount, {
|
||||||
templateName: 'modal/split_topic',
|
templateName: 'modal/split_topic',
|
||||||
title: I18n.t('topic.split_topic.title')
|
title: I18n.t('topic.split_topic.title')
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export default Discourse.ModalBodyView.extend({
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/topic-bulk-actions',
|
templateName: 'modal/topic-bulk-actions',
|
||||||
title: I18n.t('topics.bulk.actions')
|
title: I18n.t('topics.bulk.actions')
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
import ModalBodyView from "discourse/views/modal-body";
|
||||||
|
|
||||||
function uploadTranslate(key, options) {
|
function uploadTranslate(key, options) {
|
||||||
var opts = options || {};
|
const opts = options || {};
|
||||||
if (Discourse.Utilities.allowsAttachments()) { key += "_with_attachments"; }
|
if (Discourse.Utilities.allowsAttachments()) { key += "_with_attachments"; }
|
||||||
return I18n.t("upload_selector." + key, opts);
|
return I18n.t("upload_selector." + key, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Discourse.ModalBodyView.extend({
|
export default ModalBodyView.extend({
|
||||||
templateName: 'modal/upload_selector',
|
templateName: 'modal/upload_selector',
|
||||||
classNames: ['upload-selector'],
|
classNames: ['upload-selector'],
|
||||||
|
|
||||||
@ -12,17 +14,16 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
uploadIcon: function() { return Discourse.Utilities.allowsAttachments() ? "fa-upload" : "fa-picture-o"; }.property(),
|
uploadIcon: function() { return Discourse.Utilities.allowsAttachments() ? "fa-upload" : "fa-picture-o"; }.property(),
|
||||||
|
|
||||||
tip: function() {
|
tip: function() {
|
||||||
var source = this.get("controller.local") ? "local" : "remote";
|
const source = this.get("controller.local") ? "local" : "remote",
|
||||||
var opts = { authorized_extensions: Discourse.Utilities.authorizedExtensions() };
|
opts = { authorized_extensions: Discourse.Utilities.authorizedExtensions() };
|
||||||
return uploadTranslate(source + "_tip", opts);
|
return uploadTranslate(source + "_tip", opts);
|
||||||
}.property("controller.local"),
|
}.property("controller.local"),
|
||||||
|
|
||||||
hint: function() {
|
hint: function() {
|
||||||
// cf. http://stackoverflow.com/a/9851769/11983
|
// cf. http://stackoverflow.com/a/9851769/11983
|
||||||
var isChrome = !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0);
|
const isChrome = !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0),
|
||||||
var isFirefox = typeof InstallTrigger !== 'undefined';
|
isFirefox = typeof InstallTrigger !== 'undefined',
|
||||||
var isSupported = isChrome || isFirefox;
|
isSupported = isChrome || isFirefox;
|
||||||
|
|
||||||
// chrome is the only browser that support copy & paste of images.
|
// chrome is the only browser that support copy & paste of images.
|
||||||
return I18n.t("upload_selector.hint" + (isSupported ? "_for_supported_browsers" : ""));
|
return I18n.t("upload_selector.hint" + (isSupported ? "_for_supported_browsers" : ""));
|
||||||
}.property(),
|
}.property(),
|
||||||
@ -32,7 +33,7 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
}.on('didInsertElement'),
|
}.on('didInsertElement'),
|
||||||
|
|
||||||
selectedChanged: function() {
|
selectedChanged: function() {
|
||||||
var self = this;
|
const self = this;
|
||||||
Em.run.next(function() {
|
Em.run.next(function() {
|
||||||
// *HACK* to select the proper radio button
|
// *HACK* to select the proper radio button
|
||||||
var value = self.get('controller.local') ? 'local' : 'remote';
|
var value = self.get('controller.local') ? 'local' : 'remote';
|
||||||
@ -47,9 +48,9 @@ export default Discourse.ModalBodyView.extend({
|
|||||||
if (this.get("controller.local")) {
|
if (this.get("controller.local")) {
|
||||||
$('#reply-control').fileupload('add', { fileInput: $('#filename-input') });
|
$('#reply-control').fileupload('add', { fileInput: $('#filename-input') });
|
||||||
} else {
|
} else {
|
||||||
var imageUrl = $('#fileurl-input').val();
|
const imageUrl = $('#fileurl-input').val(),
|
||||||
var imageLink = $('#link-input').val();
|
imageLink = $('#link-input').val(),
|
||||||
var composerView = this.get('controller.composerView');
|
composerView = this.get('controller.composerView');
|
||||||
if (this.get("controller.showMore") && imageLink.length > 3) {
|
if (this.get("controller.showMore") && imageLink.length > 3) {
|
||||||
composerView.addMarkdown("[](" + imageLink + ")");
|
composerView.addMarkdown("[](" + imageLink + ")");
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
//= require ./discourse/controllers/navigation/default
|
//= require ./discourse/controllers/navigation/default
|
||||||
//= require ./discourse/views/view
|
//= require ./discourse/views/view
|
||||||
//= require ./discourse/views/container
|
//= require ./discourse/views/container
|
||||||
//= require ./discourse/views/modal_body_view
|
//= require ./discourse/views/modal-body
|
||||||
//= require ./discourse/views/flag
|
//= require ./discourse/views/flag
|
||||||
//= require ./discourse/views/combo-box
|
//= require ./discourse/views/combo-box
|
||||||
//= require ./discourse/views/button
|
//= require ./discourse/views/button
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
//= require admin/models/user-field
|
//= require admin/models/user-field
|
||||||
//= require admin/models/site-setting
|
//= require admin/models/site-setting
|
||||||
//= require admin/controllers/admin-email-skipped
|
//= require admin/controllers/admin-email-skipped
|
||||||
//= require admin/controllers/change-site-customization-details
|
|
||||||
//= require discourse/lib/export-result
|
//= require discourse/lib/export-result
|
||||||
//= require_tree ./admin
|
//= require_tree ./admin
|
||||||
|
|
||||||
|
@ -158,6 +158,19 @@ class TopicsController < ApplicationController
|
|||||||
render_serialized(topics, BasicTopicSerializer)
|
render_serialized(topics, BasicTopicSerializer)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def feature_stats
|
||||||
|
params.require(:category_id)
|
||||||
|
category_id = params[:category_id].to_i
|
||||||
|
|
||||||
|
topics = Topic.listable_topics.visible
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
pinned_in_category_count: topics.where(category_id: category_id).where(pinned_globally: false).where.not(pinned_at: nil).count,
|
||||||
|
pinned_globally_count: topics.where(pinned_globally: true).where.not(pinned_at: nil).count,
|
||||||
|
banner_count: topics.where(archetype: Archetype.banner).count,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
params.require(:status)
|
params.require(:status)
|
||||||
params.require(:enabled)
|
params.require(:enabled)
|
||||||
@ -492,7 +505,7 @@ class TopicsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_for_status_presence(key, attr)
|
def check_for_status_presence(key, attr)
|
||||||
invalid_param(key) unless %w(pinned_globally visible closed pinned archived).include?(attr)
|
invalid_param(key) unless %w(pinned pinned_globally visible closed archived).include?(attr)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalid_param(key)
|
def invalid_param(key)
|
||||||
|
@ -973,10 +973,11 @@ en:
|
|||||||
open: "Open Topic"
|
open: "Open Topic"
|
||||||
close: "Close Topic"
|
close: "Close Topic"
|
||||||
auto_close: "Auto Close"
|
auto_close: "Auto Close"
|
||||||
|
feature: "Feature Topic"
|
||||||
make_banner: "Banner Topic"
|
make_banner: "Banner Topic"
|
||||||
remove_banner: "Remove Banner Topic"
|
remove_banner: "Remove Banner Topic"
|
||||||
unpin: "Un-Pin Topic"
|
|
||||||
pin: "Pin Topic"
|
pin: "Pin Topic"
|
||||||
|
unpin: "Un-Pin Topic"
|
||||||
pin_globally: "Pin Topic Globally"
|
pin_globally: "Pin Topic Globally"
|
||||||
unarchive: "Unarchive Topic"
|
unarchive: "Unarchive Topic"
|
||||||
archive: "Archive Topic"
|
archive: "Archive Topic"
|
||||||
@ -1002,6 +1003,31 @@ en:
|
|||||||
help: 'privately flag this topic for attention or send a private notification about it'
|
help: 'privately flag this topic for attention or send a private notification about it'
|
||||||
success_message: 'You successfully flagged this topic.'
|
success_message: 'You successfully flagged this topic.'
|
||||||
|
|
||||||
|
feature_topic:
|
||||||
|
title: "Feature this topic"
|
||||||
|
pin: "Make this topic appear at the top of the {{categoryLink}} category."
|
||||||
|
confirm_pin: "Are you sure? You already have {{count}} pinned topics -- too many pinned topics can obscure other active topics."
|
||||||
|
unpin: "Remove this topic from the topic of the {{categoryLink}} category."
|
||||||
|
pin_note: "Users can unpin the topic individually for themselves."
|
||||||
|
already_pinned:
|
||||||
|
zero: "No topic currently pinned in {{categoryLink}}."
|
||||||
|
one: "Topic currently pinned in {{categoryLink}}: <strong>1.</strong>"
|
||||||
|
other: "Topics currently pinned in {{categoryLink}}: <strong>{{count}}</strong>."
|
||||||
|
pin_globally: "Make this topic appear at the top of all topic lists, until a staff member unpins it."
|
||||||
|
confirm_pin_globally: "Are you sure? You already have {{count}} globally pinned topics -- too many pinned topics can obscure other active topics."
|
||||||
|
unpin_globally: "Remove this topic from the top of all topic lists."
|
||||||
|
global_pin_note: "Users can unpin the topic individually for themselves."
|
||||||
|
already_pinned_globally:
|
||||||
|
zero: "No topic currently pinned globally."
|
||||||
|
one: "Topic currently pinned globally: <strong>1.</strong>"
|
||||||
|
other: "Topics currently pinned globally: <strong>{{count}}</strong>."
|
||||||
|
make_banner: "Make this topic into a banner that appears at the top of all pages."
|
||||||
|
remove_banner: "Remove the banner that appears at the top of all pages."
|
||||||
|
banner_note: "Users can dismiss the banner by closing it. Only one topic can be bannered at any given time."
|
||||||
|
already_banner:
|
||||||
|
zero: "There is currently no banner topic."
|
||||||
|
one: "There is currently a banner topic."
|
||||||
|
|
||||||
inviting: "Inviting..."
|
inviting: "Inviting..."
|
||||||
automatically_add_to_groups_optional: "This invite also includes access to these groups: (optional, admin only)"
|
automatically_add_to_groups_optional: "This invite also includes access to these groups: (optional, admin only)"
|
||||||
automatically_add_to_groups_required: "This invite also includes access to these groups: (<b>Required</b>, admin only)"
|
automatically_add_to_groups_required: "This invite also includes access to these groups: (<b>Required</b>, admin only)"
|
||||||
|
@ -392,6 +392,7 @@ Discourse::Application.routes.draw do
|
|||||||
put "topics/reset-new" => 'topics#reset_new'
|
put "topics/reset-new" => 'topics#reset_new'
|
||||||
post "topics/timings"
|
post "topics/timings"
|
||||||
get "topics/similar_to"
|
get "topics/similar_to"
|
||||||
|
get "topics/feature_stats"
|
||||||
get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT}
|
get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
get "topics/private-messages/:username" => "list#private_messages", as: "topics_private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
|
get "topics/private-messages/:username" => "list#private_messages", as: "topics_private_messages", constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
get "topics/private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", constraints: {username: USERNAME_ROUTE_FORMAT}
|
get "topics/private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
|
@ -19,7 +19,7 @@ test("modal", function() {
|
|||||||
|
|
||||||
click('.login-button');
|
click('.login-button');
|
||||||
andThen(function() {
|
andThen(function() {
|
||||||
ok(find('#discourse-modal:visible').length === 1, 'modal should appear');
|
ok(find('#discourse-modal:visible').length === 1, 'modal should reappear');
|
||||||
});
|
});
|
||||||
|
|
||||||
keyEvent('#main-outlet', 'keyup', 27);
|
keyEvent('#main-outlet', 'keyup', 27);
|
||||||
|
Reference in New Issue
Block a user