Refactor category edit to use components

This commit is contained in:
Robin Ward 2015-07-02 13:07:49 -04:00
parent 23daa9d8ce
commit 84a1acb2ec
15 changed files with 139 additions and 128 deletions

View File

@ -0,0 +1,60 @@
import { buildCategoryPanel } from 'discourse/components/edit-category-panel';
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
export default buildCategoryPanel('general', {
foregroundColors: ['FFFFFF', '000000'],
canSelectParentCategory: Em.computed.not('category.isUncategorizedCategory'),
// background colors are available as a pipe-separated string
backgroundColors: function() {
const categories = Discourse.Category.list();
return this.siteSettings.category_colors.split("|").map(function(i) { return i.toUpperCase(); }).concat(
categories.map(function(c) { return c.color.toUpperCase(); }) ).uniq();
}.property(),
usedBackgroundColors: function() {
const categories = Discourse.Category.list();
const category = this.get('category');
// If editing a category, don't include its color:
return categories.map(function(c) {
return (category.get('id') && category.get('color').toUpperCase() === c.color.toUpperCase()) ? null : c.color.toUpperCase();
}, this).compact();
}.property('category.id', 'category.color'),
parentCategories: function() {
return Discourse.Category.list().filter(function (c) {
return !c.get('parentCategory');
});
}.property(),
categoryBadgePreview: function() {
const category = this.get('category');
const c = Discourse.Category.create({
name: category.get('categoryName'),
color: category.get('color'),
text_color: category.get('text_color'),
parent_category_id: parseInt(category.get('parent_category_id'),10),
read_restricted: category.get('read_restricted')
});
return categoryBadgeHTML(c, {link: false});
}.property('category.parent_category_id', 'category.categoryName', 'category.color', 'category.text_color'),
// We can change the parent if there are no children
subCategories: function() {
if (Ember.isEmpty(this.get('category.id'))) { return null; }
return Discourse.Category.list().filterBy('parent_category_id', this.get('category.id'));
}.property('category.id'),
showDescription: function() {
return !this.get('category.isUncategorizedCategory') && this.get('category.id');
}.property('category.isUncategorizedCategory', 'category.id'),
actions: {
showCategoryTopic() {
Discourse.URL.routeTo(this.get('category.topic_url'));
return false;
}
}
});

View File

@ -0,0 +1,2 @@
import { buildCategoryPanel } from 'discourse/components/edit-category-panel';
export default buildCategoryPanel('images');

View File

@ -0,0 +1,11 @@
const EditCategoryPanel = Ember.Component.extend({
classNameBindings: [':modal-tab', 'activeTab::invisible'],
});
export default EditCategoryPanel;
export function buildCategoryPanel(tab, extras) {
return EditCategoryPanel.extend({
activeTab: Ember.computed.equal('selectedTab', tab)
}, extras || {});
}

View File

@ -0,0 +1,22 @@
import { buildCategoryPanel } from 'discourse/components/edit-category-panel';
export default buildCategoryPanel('security', {
editingPermissions: false,
selectedGroup: null,
selectedPermission: null,
actions: {
editPermissions() {
this.set('editingPermissions', true);
},
addPermission(group, id) {
this.get('category').addPermission({group_name: group + "",
permission: Discourse.PermissionType.create({id})});
},
removePermission(permission) {
this.get('category').removePermission(permission);
},
}
});

View File

@ -0,0 +1,6 @@
import { buildCategoryPanel } from 'discourse/components/edit-category-panel';
export default buildCategoryPanel('settings', {
emailInEnabled: Discourse.computed.setting('email_in'),
showPositionInput: Discourse.computed.setting('fixed_category_positions'),
});

View File

@ -5,8 +5,8 @@ export default Em.Component.extend({
active: Discourse.computed.propertyEqual('selectedTab', 'tab'),
title: Discourse.computed.i18n('tab', 'category.%@'),
_insertInParent: function() {
this.get('parentView.panels').addObject(this.get('tab'));
_addToCollection: function() {
this.get('panels').addObject('edit-category-' + this.get('tab'));
}.on('didInsertElement'),
actions: {

View File

@ -1,28 +1,16 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
// Modal for editing / creating a category
export default ObjectController.extend(ModalFunctionality, {
foregroundColors: ['FFFFFF', '000000'],
editingPermissions: false,
selectedTab: null,
saving: false,
deleting: false,
panels: null,
parentCategories: function() {
return Discourse.Category.list().filter(function (c) {
return !c.get('parentCategory');
});
}.property(),
// We can change the parent if there are no children
subCategories: function() {
if (Em.isEmpty(this.get('model.id'))) { return null; }
return Discourse.Category.list().filterBy('parent_category_id', this.get('model.id'));
}.property('model.id'),
canSelectParentCategory: Em.computed.not('model.isUncategorizedCategory'),
_initPanels: function() {
this.set('panels', []);
}.on('init'),
onShow() {
this.changeSize();
@ -55,46 +43,10 @@ export default ObjectController.extend(ModalFunctionality, {
return false;
}.property('saving', 'model.name', 'model.color', 'deleting'),
emailInEnabled: Discourse.computed.setting('email_in'),
deleteDisabled: function() {
return (this.get('deleting') || this.get('saving') || false);
}.property('disabled', 'saving', 'deleting'),
colorStyle: function() {
return "background-color: #" + this.get('model.color') + "; color: #" + this.get('model.text_color') + ";";
}.property('model.color', 'model.text_color'),
categoryBadgePreview: function() {
const model = this.get('model');
const c = Discourse.Category.create({
name: model.get('categoryName'),
color: model.get('color'),
text_color: model.get('text_color'),
parent_category_id: parseInt(model.get('parent_category_id'),10),
read_restricted: model.get('read_restricted')
});
return categoryBadgeHTML(c, {link: false});
}.property('model.parent_category_id', 'model.categoryName', 'model.color', 'model.text_color'),
// background colors are available as a pipe-separated string
backgroundColors: function() {
const categories = Discourse.Category.list();
return Discourse.SiteSettings.category_colors.split("|").map(function(i) { return i.toUpperCase(); }).concat(
categories.map(function(c) { return c.color.toUpperCase(); }) ).uniq();
}.property('Discourse.SiteSettings.category_colors'),
usedBackgroundColors: function() {
const categories = Discourse.Category.list();
const currentCat = this.get('model');
return categories.map(function(c) {
// If editing a category, don't include its color:
return (currentCat.get('id') && currentCat.get('color').toUpperCase() === c.color.toUpperCase()) ? null : c.color.toUpperCase();
}, this).compact();
}.property('model.id', 'model.color'),
categoryName: function() {
const name = this.get('name') || "";
return name.trim().length > 0 ? name : I18n.t("preview");
@ -106,32 +58,7 @@ export default ObjectController.extend(ModalFunctionality, {
return this.get('model.id') ? "category.save" : "category.create";
}.property('saving', 'model.id'),
showDescription: function() {
return !this.get('model.isUncategorizedCategory') && this.get('model.id');
}.property('model.isUncategorizedCategory', 'model.id'),
showPositionInput: Discourse.computed.setting('fixed_category_positions'),
actions: {
showCategoryTopic() {
this.send('closeModal');
Discourse.URL.routeTo(this.get('model.topic_url'));
return false;
},
editPermissions() {
this.set('editingPermissions', true);
},
addPermission(group, id) {
this.get('model').addPermission({group_name: group + "",
permission: Discourse.PermissionType.create({id})});
},
removePermission(permission) {
this.get('model').removePermission(permission);
},
saveCategory() {
const self = this,
model = this.get('model'),

View File

@ -2,11 +2,11 @@
<section class='field'>
<section class="field-item">
<label>{{i18n 'category.name'}}</label>
{{text-field value=model.name placeholderKey="category.name_placeholder" maxlength="50"}}
{{text-field value=category.name placeholderKey="category.name_placeholder" maxlength="50"}}
</section>
<section class="field-item">
<label>{{i18n 'category.slug'}}</label>
{{text-field value=model.slug placeholderKey="category.slug_placeholder" maxlength="255"}}
{{text-field value=category.slug placeholderKey="category.slug_placeholder" maxlength="255"}}
</section>
</section>
@ -14,12 +14,12 @@
<section class='field'>
{{#if subCategories}}
<label>{{i18n 'categories.subcategories'}}</label>
{{#each s in subCategories}}
{{#each subCategories as |s|}}
{{category-badge s hideParent="true"}}
{{/each}}
{{else}}
<label>{{i18n 'category.parent'}}</label>
{{category-chooser valueAttribute="id" value=model.parent_category_id categories=parentCategories rootNone=true}}
{{category-chooser valueAttribute="id" value=category.parent_category_id categories=parentCategories rootNone=true}}
{{/if}}
</section>
{{/if}}
@ -27,12 +27,12 @@
{{#if showDescription}}
<section class='field'>
<label>{{i18n 'category.description'}}</label>
{{#if model.description}}
{{{model.description}}}
{{#if category.description}}
{{{category.description}}}
{{else}}
{{i18n 'category.no_description'}}
{{/if}}
{{#if model.topic_url}}
{{#if category.topic_url}}
<br/>
{{d-button class="btn-small" action="showCategoryTopic" icon="pencil" label="category.change_in_category_topic"}}
{{/if}}
@ -46,14 +46,14 @@
<div class='input-prepend input-append' style="margin-top: 10px;">
<span class='color-title'>{{i18n 'category.background_color'}}:</span>
<span class='add-on'>#</span>{{text-field value=model.color placeholderKey="category.color_placeholder" maxlength="6"}}
{{color-picker colors=backgroundColors usedColors=usedBackgroundColors value=model.color}}
<span class='add-on'>#</span>{{text-field value=category.color placeholderKey="category.color_placeholder" maxlength="6"}}
{{color-picker colors=backgroundColors usedColors=usedBackgroundColors value=category.color}}
</div>
<div class='input-prepend input-append'>
<span class='color-title'>{{i18n 'category.foreground_color'}}:</span>
<span class='add-on'>#</span>{{text-field value=model.text_color placeholderKey="category.color_placeholder" maxlength="6"}}
{{color-picker colors=foregroundColors value=model.text_color id='edit-text-color'}}
<span class='add-on'>#</span>{{text-field value=category.text_color placeholderKey="category.color_placeholder" maxlength="6"}}
{{color-picker colors=foregroundColors value=category.text_color id='edit-text-color'}}
</div>
</div>
</section>

View File

@ -1,9 +1,9 @@
<section class='field'>
<label>{{i18n 'category.logo'}}</label>
{{image-uploader imageUrl=model.logo_url type="category_logo"}}
{{image-uploader imageUrl=category.logo_url type="category_logo"}}
</section>
<section class='field'>
<label>{{i18n 'category.background_image'}}</label>
{{image-uploader imageUrl=model.background_url type="category_background"}}
{{image-uploader imageUrl=category.background_url type="category_background"}}
</section>

View File

@ -1,19 +1,19 @@
<section class='field'>
<ul class='permission-list'>
{{#each model.permissions as |p|}}
{{#each category.permissions as |p|}}
<li>
<span class="name"><span class="badge-group">{{p.group_name}}</span></span>
{{{i18n "category.can"}}}
<span class="permission">{{p.permission.description}}</span>
{{#if controller.editingPermissions}}
<a {{action "removePermission" p}}><i class="fa fa-times-circle"></i></a>
{{#if editingPermissions}}
<a href {{action "removePermission" p}}>{{fa-icon "times-circle"}}</a>
{{/if}}
</li>
{{/each}}
</ul>
{{#if controller.editingPermissions}}
{{view 'select' content=availableGroups value=selectedGroup}}
{{view 'select' class="permission-selector" optionValuePath="content.id" optionLabelPath="content.description" content=availablePermissions value=selectedPermission}}
{{#if editingPermissions}}
{{view 'select' content=category.availableGroups value=selectedGroup}}
{{view 'select' class="permission-selector" optionValuePath="content.id" optionLabelPath="content.description" content=category.availablePermissions value=selectedPermission}}
<button {{action "addPermission" selectedGroup selectedPermission}} class="btn btn-small">{{i18n 'category.add_permission'}}</button>
{{else}}
<button {{action "editPermissions"}} class="btn btn-small">{{i18n 'category.edit_permissions'}}</button>

View File

@ -1,13 +1,13 @@
<section class='field'>
{{auto-close-form autoCloseTime=model.auto_close_hours
autoCloseBasedOnLastPost=model.auto_close_based_on_last_post
{{auto-close-form autoCloseTime=category.auto_close_hours
autoCloseBasedOnLastPost=category.auto_close_based_on_last_post
limited="true" }}
</section>
<section class='field'>
<div class="allow-badges">
<div>
{{input type="checkbox" checked=model.allow_badges}}
{{input type="checkbox" checked=category.allow_badges}}
{{i18n 'category.allow_badges_label'}}
</div>
</div>
@ -19,11 +19,11 @@
<div>
<i class="fa fa-envelope-o"></i>
{{i18n 'category.email_in'}}
{{text-field value=email_in}}
{{text-field value=category.email_in}}
</div>
<div>
<label class="checkbox-label">
{{input type="checkbox" checked=email_in_allow_strangers}}
{{input type="checkbox" checked=category.email_in_allow_strangers}}
{{i18n 'category.email_in_allow_strangers'}}
</label>
</div>
@ -37,7 +37,7 @@
<section class='field'>
{{#if showPositionInput}}
<label>{{i18n 'category.position'}}</label>
{{text-field value=position class="position-input"}}
{{text-field value=category.position class="position-input"}}
{{else}}
{{i18n 'category.position_disabled'}}
<a href="/admin/site_settings/category/basic">{{i18n 'category.position_disabled_click'}}</a>

View File

@ -1,16 +1,16 @@
<div>
<ul class="nav nav-pills">
{{edit-category-tab selectedTab=selectedTab tab="general"}}
{{edit-category-tab panels=panels selectedTab=selectedTab tab="general"}}
{{#unless model.isUncategorizedCategory}}
{{edit-category-tab selectedTab=selectedTab tab="security"}}
{{edit-category-tab panels=panels selectedTab=selectedTab tab="security"}}
{{/unless}}
{{edit-category-tab selectedTab=selectedTab tab="settings"}}
{{edit-category-tab selectedTab=selectedTab tab="images"}}
{{edit-category-tab panels=panels selectedTab=selectedTab tab="settings"}}
{{edit-category-tab panels=panels selectedTab=selectedTab tab="images"}}
</ul>
<div class="modal-body">
{{#each view.panels as |tab|}}
{{view 'edit-category-panel' tab=tab}}
{{#each panels as |tab|}}
{{component tab selectedTab=selectedTab category=model}}
{{/each}}
</div>

View File

@ -1,9 +0,0 @@
export default Em.View.extend({
classNameBindings: [':modal-tab', 'invisible'],
invisible: Discourse.computed.propertyNotEqual('controller.selectedTab', 'tab'),
templateName: function() {
return "modal/edit-category-" + this.get('tab');
}.property('tab')
});

View File

@ -1,9 +0,0 @@
import ModalBodyView from "discourse/views/modal-body";
export default ModalBodyView.extend({
templateName: 'modal/edit-category',
_initializePanels: function() {
this.set('panels', []);
}.on('init')
});

View File

@ -44,6 +44,7 @@
//= require ./discourse/views/flag
//= require ./discourse/views/cloaked
//= require ./discourse/components/combo-box
//= require ./discourse/components/edit-category-panel
//= require ./discourse/views/button
//= require ./discourse/components/search-result
//= require ./discourse/components/dropdown-button