Support for "Only show overridden" in site text customization

This commit is contained in:
Robin Ward 2015-11-30 15:22:58 -05:00
parent 04593b8fef
commit de88be2fbc
17 changed files with 119 additions and 35 deletions

View File

@ -2,6 +2,7 @@ import { on } from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend({
classNames: ['site-text'],
classNameBindings: ['siteText.overridden'],
@on('didInsertElement')
highlightTerm() {

View File

@ -5,8 +5,20 @@ export default Ember.Controller.extend({
searching: false,
siteTexts: null,
preferred: false,
_overridden: null,
queryParams: ['q', 'overridden'],
queryParams: ['q'],
@computed
overridden: {
set(value) {
if (!value || value === "false") { value = false; }
this._overridden = value;
return value;
},
get() {
return this._overridden;
}
},
@computed
q: {
@ -21,8 +33,7 @@ export default Ember.Controller.extend({
},
_performSearch() {
const q = this.get('q');
this.store.find('site-text', { q }).then(results => {
this.store.find('site-text', this.getProperties('q', 'overridden')).then(results => {
this.set('siteTexts', results);
}).finally(() => this.set('searching', false));
},

View File

@ -1,10 +1,11 @@
export default Ember.Route.extend({
queryParams: {
q: { replace: true }
q: { replace: true },
overridden: { replace: true }
},
model(params) {
return this.store.find('site-text', { q: params.q });
return this.store.find('site-text', Ember.getProperties(params, 'q', 'overridden'));
},
setupController(controller, model) {

View File

@ -5,13 +5,17 @@
placeholderKey="admin.site_text.search"
class="no-blur site-text-search"
autofocus="true"
keyUpAction="search"}}
key-up="search"}}
<div class='extra-options'>
{{d-checkbox label="admin.site_text.show_overriden" checked=overridden change="search"}}
</div>
</div>
{{#conditional-loading-spinner condition=searching}}
{{#unless siteTexts.findArgs.q}}
{{#if siteTexts.extras.recommended}}
<p><b>{{i18n "admin.site_text.recommended"}}</b></p>
{{/unless}}
{{/if}}
{{#each siteTexts as |siteText|}}
{{site-text-summary siteText=siteText editAction="edit" term=q}}

View File

@ -0,0 +1,18 @@
import { on } from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
tagName: 'label',
@on('didInsertElement')
_watchChanges() {
// In Ember 13.3 we can use action on the checkbox `{{input}}` but not in 1.11
this.$('input').on('click.d-checkbox', () => {
Ember.run.scheduleOnce('afterRender', () => this.sendAction('change'));
});
},
@on('willDestroyElement')
_stopWatching() {
this.$('input').off('click.d-checkbox');
}
});

View File

@ -6,12 +6,5 @@ export default Ember.TextField.extend({
@computed("placeholderKey")
placeholder(placeholderKey) {
return placeholderKey ? I18n.t(placeholderKey) : "";
},
keyUp() {
const act = this.get('keyUpAction');
if (act) {
this.sendAction('keyUpAction');
}
}
});

View File

@ -88,9 +88,9 @@ export default Ember.Object.extend({
refreshResults(resultSet, type, url) {
const self = this;
return Discourse.ajax(url).then(function(result) {
const typeName = Ember.String.underscore(self.pluralize(type)),
content = result[typeName].map(obj => self._hydrate(type, obj, result));
return Discourse.ajax(url).then(result => {
const typeName = Ember.String.underscore(self.pluralize(type));
const content = result[typeName].map(obj => self._hydrate(type, obj, result));
resultSet.set('content', content);
});
},
@ -143,13 +143,24 @@ export default Ember.Object.extend({
},
_resultSet(type, result, findArgs) {
const typeName = Ember.String.underscore(this.pluralize(type)),
content = result[typeName].map(obj => this._hydrate(type, obj, result)),
totalRows = result["total_rows_" + typeName] || content.length,
loadMoreUrl = result["load_more_" + typeName],
refreshUrl = result['refresh_' + typeName];
const typeName = Ember.String.underscore(this.pluralize(type));
const content = result[typeName].map(obj => this._hydrate(type, obj, result));
return ResultSet.create({ content, totalRows, loadMoreUrl, refreshUrl, findArgs, store: this, __type: type });
const createArgs = {
content,
findArgs,
totalRows: result["total_rows_" + typeName] || content.length,
loadMoreUrl: result["load_more_" + typeName],
refreshUrl: result['refresh_' + typeName],
store: this,
__type: type
};
if (result.extras) {
createArgs.extras = result.extras;
}
return ResultSet.create(createArgs);
},
_build(type, obj) {

View File

@ -0,0 +1,2 @@
{{input type="checkbox" checked=checked}}
{{i18n label}}

View File

@ -50,11 +50,19 @@ td.flaggers td {
margin-top: 0;
}
input {
.site-text-search {
padding: 0.5em;
font-size: 1em;
width: 50%;
}
.extra-options {
float: right;
input[type=checkbox] {
margin-right: 0.5em;
}
}
}
.text-highlight {
font-weight: bold;
@ -65,6 +73,10 @@ td.flaggers td {
border-bottom: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
margin-bottom: 0.5em;
&.overridden {
background-color: dark-light-diff($highlight, $secondary, 50%, -60%);
}
h3 {
font-weight: normal;
font-size: 1.1em;

View File

@ -8,11 +8,15 @@ class Admin::SiteTextsController < Admin::AdminController
end
def index
if params[:q].blank?
overridden = params[:overridden] == 'true'
extras = {}
if params[:q].blank? && !overridden
extras[:recommended] = true
results = self.class.preferred_keys.map {|k| {id: k, value: I18n.t(k) }}
else
results = []
translations = I18n.search(params[:q])
translations = I18n.search(params[:q], overridden: overridden)
translations.each do |k, v|
results << {id: k, value: v}
end
@ -21,7 +25,7 @@ class Admin::SiteTextsController < Admin::AdminController
end
end
render_serialized(results[0..50], SiteTextSerializer, root: 'site_texts', rest_serializer: true)
render_serialized(results[0..50], SiteTextSerializer, root: 'site_texts', rest_serializer: true, extras: extras)
end
def show

View File

@ -229,6 +229,8 @@ class ApplicationController < ActionController::Base
opts.each do |k, v|
obj[k] = v if k.to_s.start_with?("refresh_")
end
obj['extras'] = opts[:extras] if opts[:extras]
end
render json: MultiJson.dump(obj), status: opts[:status] || 200

View File

@ -1,5 +1,5 @@
class SiteTextSerializer < ApplicationSerializer
attributes :id, :value, :can_revert?
attributes :id, :value, :overridden?, :can_revert?
def id
object[:id]
@ -9,12 +9,14 @@ class SiteTextSerializer < ApplicationSerializer
object[:value]
end
def can_revert?
def overridden?
current_val = value
I18n.overrides_disabled do
return I18n.t(object[:id]) != current_val
end
end
alias_method :can_revert?, :overridden?
end

View File

@ -2492,6 +2492,7 @@ en:
revert_confirm: "Are you sure you want to revert your changes?"
go_back: "Back to Search"
recommended: "We recommend customizing the following text to suit your needs:"
show_overriden: 'Only show overridden'
site_settings:
show_overriden: 'Only show overridden'

View File

@ -56,7 +56,7 @@ module I18n
opts ||= {}
target = opts[:backend] || backend
results = target.search(config.locale, query)
results = opts[:overridden] ? {} : target.search(config.locale, query)
regexp = /#{query}/i
(overrides_by_locale || {}).each do |k, v|

View File

@ -6,9 +6,22 @@ test("search for a key", () => {
visit("/admin/customize/site_texts");
fillIn('.site-text-search', 'Test');
andThen(() => ok(exists('.site-text')));
andThen(() => {
ok(exists('.site-text'));
ok(exists(".site-text:not(.overridden)"));
ok(exists('.site-text.overridden'));
});
// Only show overridden
click('.extra-options input');
andThen(() => {
ok(!exists(".site-text:not(.overridden)"));
ok(exists('.site-text.overridden'));
});
});
test("edit and revert a site text by key", () => {
visit("/admin/customize/site_texts/site.test");
andThen(() => {

View File

@ -210,7 +210,7 @@ export default function() {
});
this.get('/fruits', function() {
return response({ __rest_serializer: "1", fruits, farmers, colors });
return response({ __rest_serializer: "1", fruits, farmers, colors, extras: {hello: 'world'} });
});
this.get('/widgets/:widget_id', function(request) {
@ -262,7 +262,16 @@ export default function() {
this.post('/topics/timings', () => response(200, {}));
const siteText = {id: 'site.test', value: 'Test McTest'};
this.get('/admin/customize/site_texts', () => response(200, {site_texts: [siteText] }));
const overridden = {id: 'site.overridden', value: 'Overridden', overridden: true };
this.get('/admin/customize/site_texts', request => {
if (request.queryParams.overridden) {
return response(200, {site_texts: [overridden] })
} else {
return response(200, {site_texts: [siteText, overridden] })
}
});
this.get('/admin/customize/site_texts/:key', () => response(200, {site_text: siteText }));
this.delete('/admin/customize/site_texts/:key', () => response(200, {site_text: siteText }));

View File

@ -116,7 +116,6 @@ test('destroyRecord when new', function(assert) {
});
});
test('find embedded', function(assert) {
const store = createStore();
return store.find('fruit', 2).then(function(f) {
@ -136,6 +135,7 @@ test('findAll embedded', function(assert) {
return store.findAll('fruit').then(function(fruits) {
assert.equal(fruits.objectAt(0).get('farmer.name'), 'Old MacDonald');
assert.equal(fruits.objectAt(0).get('farmer'), fruits.objectAt(1).get('farmer'), 'points at the same object');
assert.equal(fruits.get('extras.hello'), 'world', 'it can supply extra information');
const fruitCols = fruits.objectAt(0).get('colors');
assert.equal(fruitCols.length, 2);