FIX: Fix behavior of category reorder dialog

This commit is contained in:
Kane York 2015-09-10 13:04:25 -07:00
parent ad481b3427
commit 0c5fb207e9
3 changed files with 58 additions and 54 deletions

View File

@ -5,6 +5,8 @@ import { popupAjaxError } from 'discourse/lib/ajax-error';
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
import Ember from 'ember'; import Ember from 'ember';
const SortableArrayProxy = Ember.ArrayProxy.extend(Ember.SortableMixin);
export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, { export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
@computed("site.categories") @computed("site.categories")
@ -13,24 +15,23 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
return categories.map(c => bufProxy.create({ content: c })); return categories.map(c => bufProxy.create({ content: c }));
}, },
// uses propertyDidChange() categoriesOrdered: function() {
@computed('categoriesBuffered') return SortableArrayProxy.create({
categoriesGrouped(cats) { sortProperties: ['content.position'],
const map = {}; content: this.get('categoriesBuffered')
cats.forEach((cat) => { });
const p = cat.get('position') || 0; }.property('categoriesBuffered'),
if (!map[p]) {
map[p] = {pos: p, cats: [cat]}; showFixIndices: function() {
} else { const cats = this.get('categoriesOrdered');
map[p].cats.push(cat); const len = cats.get('length');
for (let i = 0; i < len; i++) {
if (cats.objectAt(i).get('position') !== i) {
return true;
} }
}); }
const result = []; return false;
Object.keys(map).map(p => parseInt(p)).sort((a,b) => a-b).forEach(function(pos) { }.property('categoriesOrdered.@each.position'),
result.push(map[pos]);
});
return result;
},
showApplyAll: function() { showApplyAll: function() {
let anyChanged = false; let anyChanged = false;
@ -38,29 +39,22 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
return anyChanged; return anyChanged;
}.property('categoriesBuffered.@each.hasBufferedChanges'), }.property('categoriesBuffered.@each.hasBufferedChanges'),
saveDisabled: Ember.computed.alias('showApplyAll'), @computed('showApplyAll', 'showFixIndices')
saveDisabled(a, b) {
return a || b;
},
moveDir(cat, dir) { moveDir(cat, dir) {
const grouped = this.get('categoriesGrouped'), const cats = this.get('categoriesOrdered');
curPos = cat.get('position'), const curIdx = cats.indexOf(cat);
curGroupIdx = binarySearch(grouped, curPos, "pos"), const curPos = cat.get('position');
curGroup = grouped[curGroupIdx]; const desiredIdx = curIdx + dir;
if (desiredIdx >= 0 && desiredIdx < cats.get('length')) {
if (curGroup.cats.length === 1 && ((dir === -1 && curGroupIdx !== 0) || (dir === 1 && curGroupIdx !== (grouped.length - 1)))) { cat.set('position', cat.get('position') + dir);
const nextGroup = grouped[curGroupIdx + dir], const otherCat = cats.objectAt(desiredIdx);
nextPos = nextGroup.pos; otherCat.set('position', cat.get('position') - dir);
cat.set('position', nextPos); this.send('commit');
} else {
cat.set('position', curPos + dir);
} }
cat.applyBufferedChanges();
Ember.run.next(this, () => {
this.propertyDidChange('categoriesGrouped');
Ember.run.schedule('afterRender', this, () => {
this.set('scrollIntoViewId', cat.get('id'));
this.trigger('scrollIntoView');
});
});
}, },
actions: { actions: {
@ -72,13 +66,22 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, {
this.moveDir(cat, 1); this.moveDir(cat, 1);
}, },
fixIndices() {
const cats = this.get('categoriesOrdered');
const len = cats.get('length');
for (let i = 0; i < len; i++) {
cats.objectAt(i).set('position', i);
}
this.send('commit');
},
commit() { commit() {
this.get('categoriesBuffered').forEach(bc => { this.get('categoriesBuffered').forEach(bc => {
if (bc.get('hasBufferedChanges')) { if (bc.get('hasBufferedChanges')) {
bc.applyBufferedChanges(); bc.applyBufferedChanges();
} }
}); });
this.propertyDidChange('categoriesGrouped'); this.propertyDidChange('categoriesBuffered');
}, },
saveOrder() { saveOrder() {

View File

@ -6,28 +6,27 @@
<th class="th-pos">Position</th> <th class="th-pos">Position</th>
<th class="th-cat">Category</th> <th class="th-cat">Category</th>
</thead> </thead>
{{#each categoriesGrouped as |group|}} {{#each categoriesOrdered as |cat|}}
<tbody> <tr data-category-id="{{cat.id}}">
{{#each group.cats as |cat|}} <td>
<tr data-category-id="{{cat.id}}"> {{number-field number=cat.position}}
<td> {{d-button class="no-text" action="moveUp" actionParam=cat icon="arrow-up"}}
{{number-field number=cat.position}} {{d-button class="no-text" action="moveDown" actionParam=cat icon="arrow-down"}}
{{d-button class="no-text" action="moveUp" actionParam=cat icon="arrow-up"}} {{#if cat.hasBufferedChanges}}
{{d-button class="no-text" action="moveDown" actionParam=cat icon="arrow-down"}} {{d-button class="no-text" action="commit" icon="check"}}
{{#if cat.hasBufferedChanges}} {{/if}}
{{d-button class="no-text" action="commit" icon="check"}} </td>
{{/if}} <td>{{category-badge cat allowUncategorized="true"}}</td>
</td> </tr>
<td>{{category-badge cat allowUncategorized="true"}}</td>
</tr>
{{/each}}
</tbody>
{{/each}} {{/each}}
</table> </table>
<div id="rc-scroll-bottom"></div> <div id="rc-scroll-bottom"></div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
{{#if showFixIndices}}
{{d-button action="fixIndices" icon="random" label="categories.reorder.fix_order" title="categories.reorder.fix_order_tooltip"}}
{{/if}}
{{#if showApplyAll}} {{#if showApplyAll}}
{{d-button action="commit" icon="check" label="categories.reorder.apply_all"}} {{d-button action="commit" icon="check" label="categories.reorder.apply_all"}}
{{/if}} {{/if}}

View File

@ -370,6 +370,8 @@ en:
category: "Category" category: "Category"
reorder: reorder:
title: "Reorder Categories" title: "Reorder Categories"
fix_order: "Fix Positions"
fix_order_tooltip: "Not all categories have a unique position number, which may cause unexpected results."
save: "Save Order" save: "Save Order"
apply_all: "Apply" apply_all: "Apply"
posts: "Posts" posts: "Posts"