Replaces remaining {{category-chooser}} by {{category-select-box}}

To achieve replacement, this commit also adds support for:
- clearSelectionLabel which will allows to unselect any chosen category
- select-box inside a modal
- fixes minor css positioning issues

Note: {{category-chooser}} will be removed in the next weeks.
This commit is contained in:
Joffrey JAFFEUX
2017-08-30 17:04:17 +02:00
committed by GitHub
parent 85ff6b8083
commit 746c5927e1
20 changed files with 145 additions and 51 deletions

View File

@ -9,7 +9,7 @@
{{input value=buffered.path_whitelist placeholder="/blog/.*" enter="save" class="path-whitelist"}} {{input value=buffered.path_whitelist placeholder="/blog/.*" enter="save" class="path-whitelist"}}
</td> </td>
<td> <td>
{{category-chooser value=categoryId}} {{category-select-box value=categoryId class="small"}}
</td> </td>
<td> <td>
{{d-button icon="check" action="save" class="btn-primary" disabled=cantSave}} {{d-button icon="check" action="save" class="btn-primary" disabled=cantSave}}

View File

@ -15,10 +15,19 @@ export default SelectBoxComponent.extend({
castInteger: true, castInteger: true,
width: "100%",
clearable: true, clearable: true,
allowUncategorized: null,
init() {
this._super();
if (!Ember.isNone(this.get("categories"))) {
this.set("content", this.get("categories"));
this._scopeCategories();
}
},
filterFunction: function(content) { filterFunction: function(content) {
const _matchFunction = (filter, text) => { const _matchFunction = (filter, text) => {
return text.toLowerCase().indexOf(filter) > -1; return text.toLowerCase().indexOf(filter) > -1;
@ -57,7 +66,6 @@ export default SelectBoxComponent.extend({
this.set("headerText", headerText); this.set("headerText", headerText);
}, },
// original method is kept for compatibility
templateForRow: function() { templateForRow: function() {
return (rowComponent) => this.rowContentTemplate(rowComponent.get("content")); return (rowComponent) => this.rowContentTemplate(rowComponent.get("content"));
}.property(), }.property(),
@ -79,8 +87,11 @@ export default SelectBoxComponent.extend({
const categoryId = c.get("id"); const categoryId = c.get("id");
if (scopedCategoryId && categoryId !== scopedCategoryId && c.get("parent_category_id") !== scopedCategoryId) { return false; } if (scopedCategoryId && categoryId !== scopedCategoryId && c.get("parent_category_id") !== scopedCategoryId) { return false; }
if (excludeCategoryId === categoryId) { return false; } if (excludeCategoryId === categoryId) { return false; }
if (!this.siteSettings.allow_uncategorized_topics && c.get("isUncategorizedCategory")) { if (this.get("allowUncategorized") === false && c.get("isUncategorizedCategory")) { return false; }
return false; if (this.get("allowUncategorized") !== true) {
if (!this.siteSettings.allow_uncategorized_topics && c.get("isUncategorizedCategory")) {
return false;
}
} }
return c.get("permission") === PermissionType.FULL; return c.get("permission") === PermissionType.FULL;
}); });

View File

@ -14,6 +14,7 @@ export default Ember.Component.extend({
renderBody: false, renderBody: false,
wrapper: true, wrapper: true,
tabindex: 0, tabindex: 0,
scrollableParentSelector: ".modal-body",
caretUpIcon: "caret-up", caretUpIcon: "caret-up",
caretDownIcon: "caret-down", caretDownIcon: "caret-down",
@ -24,8 +25,9 @@ export default Ember.Component.extend({
value: null, value: null,
selectedContent: null, selectedContent: null,
noContentText: I18n.t("select_box.no_content"), noContentLabel: I18n.t("select_box.no_content"),
lastHovered: null, lastHovered: null,
clearSelectionLabel: null,
idKey: "id", idKey: "id",
textKey: "text", textKey: "text",
@ -41,7 +43,7 @@ export default Ember.Component.extend({
selectBoxHeaderComponent: "select-box/select-box-header", selectBoxHeaderComponent: "select-box/select-box-header",
selectBoxCollectionComponent: "select-box/select-box-collection", selectBoxCollectionComponent: "select-box/select-box-collection",
width: 220, minWidth: 220,
maxCollectionHeight: 200, maxCollectionHeight: 200,
verticalOffset: 0, verticalOffset: 0,
horizontalOffset: 0, horizontalOffset: 0,
@ -65,7 +67,7 @@ export default Ember.Component.extend({
shouldHighlightRow: function() { shouldHighlightRow: function() {
return (rowComponent) => { return (rowComponent) => {
if (Ember.isNone(this.get("value"))) { if (Ember.isNone(this.get("value")) && Ember.isNone(this.get("lastHovered"))) {
return false; return false;
} }
@ -96,14 +98,14 @@ export default Ember.Component.extend({
applyDirection() { applyDirection() {
const offsetTop = this.$()[0].getBoundingClientRect().top; const offsetTop = this.$()[0].getBoundingClientRect().top;
const windowHeight = $(window).height(); const windowHeight = $(window).height();
const headerHeight = this.$(".select-box-header").outerHeight(); const headerHeight = this.$(".select-box-header").outerHeight(false);
const filterHeight = this.$(".select-box-filter").outerHeight(); const filterHeight = this.$(".select-box-filter").outerHeight(false);
if (windowHeight - (offsetTop + this.get("maxCollectionHeight") + filterHeight + headerHeight) < 0) { if (windowHeight - (offsetTop + this.get("maxCollectionHeight") + filterHeight + headerHeight) < 0) {
this.$().addClass("is-reversed"); this.$().addClass("is-reversed");
this.$(".select-box-body").css({ this.$(".select-box-body").css({
left: this.get("horizontalOffset"), left: this.get("horizontalOffset"),
top: "", top: "auto",
bottom: headerHeight + this.get("verticalOffset") bottom: headerHeight + this.get("verticalOffset")
}); });
} else { } else {
@ -111,7 +113,7 @@ export default Ember.Component.extend({
this.$(".select-box-body").css({ this.$(".select-box-body").css({
left: this.get("horizontalOffset"), left: this.get("horizontalOffset"),
top: headerHeight + this.get("verticalOffset"), top: headerHeight + this.get("verticalOffset"),
bottom: "" bottom: "auto"
}); });
} }
}, },
@ -150,21 +152,31 @@ export default Ember.Component.extend({
@on("didRender") @on("didRender")
_configureSelectBoxDOM: function() { _configureSelectBoxDOM: function() {
this.$().css("width", this.get("width")); if (this.get("scrollableParent").length === 1) {
this.$(".select-box-header").css("height", this.$().css("height")); this._removeFixedPosition();
this.$(".select-box-filter").css("height", this.$().css("height")); }
this.$().css("min-width", this.get("minWidth"));
const computedWidth = this.$().outerWidth(false);
const computedHeight = this.$().outerHeight(false);
this.$(".select-box-header").css("height", computedHeight);
this.$(".select-box-filter").css("height", computedHeight);
if (this.get("expanded")) { if (this.get("expanded")) {
this.$(".select-box-body").css("width", this.$().css("width")); if (this.get("scrollableParent").length === 1) {
this._applyFixedPosition(computedWidth, computedHeight);
}
this.$(".select-box-body").css("width", computedWidth);
this.$(".select-box-collection").css("max-height", this.get("maxCollectionHeight")); this.$(".select-box-collection").css("max-height", this.get("maxCollectionHeight"));
Ember.run.schedule("afterRender", () => { this.applyDirection();
this.applyDirection();
if (this.get("wrapper")) { if (this.get("wrapper")) {
this._positionSelectBoxWrapper(); this._positionSelectBoxWrapper();
} }
});
} else { } else {
if (this.get("wrapper")) { if (this.get("wrapper")) {
this.$(".select-box-wrapper").hide(); this.$(".select-box-wrapper").hide();
@ -250,12 +262,16 @@ export default Ember.Component.extend({
}); });
}, },
@computed("headerText", "dynamicHeaderText", "selectedContent", "textKey") @computed("headerText", "dynamicHeaderText", "selectedContent", "textKey", "clearSelectionLabel")
generatedHeadertext(headerText, dynamic, selectedContent, textKey) { generatedHeadertext(headerText, dynamic, selectedContent, textKey, clearSelectionLabel) {
if (dynamic && !Ember.isNone(selectedContent)) { if (dynamic && !Ember.isNone(selectedContent)) {
return selectedContent[textKey]; return selectedContent[textKey];
} }
if (dynamic && Ember.isNone(selectedContent) && !Ember.isNone(clearSelectionLabel)) {
return I18n.t(clearSelectionLabel);
}
return headerText; return headerText;
}, },
@ -272,6 +288,11 @@ export default Ember.Component.extend({
return filteredContent; return filteredContent;
}, },
@computed("scrollableParentSelector")
scrollableParent(scrollableParentSelector) {
return this.$().parents(scrollableParentSelector).first();
},
actions: { actions: {
onToggle() { onToggle() {
this.toggleProperty("expanded"); this.toggleProperty("expanded");
@ -288,18 +309,22 @@ export default Ember.Component.extend({
}); });
}, },
onClearSelection() {
this.setProperties({ value: null, expanded: false });
},
onHoverRow(content) { onHoverRow(content) {
this.set("lastHovered", this._castInteger(content[this.get("idKey")])); this.set("lastHovered", this._castInteger(content[this.get("idKey")]));
} }
}, },
_positionSelectBoxWrapper() { _positionSelectBoxWrapper() {
const headerHeight = this.$(".select-box-header").outerHeight(); const headerHeight = this.$(".select-box-header").outerHeight(false);
this.$(".select-box-wrapper").css({ this.$(".select-box-wrapper").css({
width: this.$().width(), width: this.$().width(),
display: "block", display: "block",
height: headerHeight + this.$(".select-box-body").outerHeight() height: headerHeight + this.$(".select-box-body").outerHeight(false)
}); });
}, },
@ -309,5 +334,33 @@ export default Ember.Component.extend({
} }
return id; return id;
},
_applyFixedPosition(width, height) {
const $placeholder = $(`<div class='select-box-fixed-placeholder-${this.get("componentId")}' style='vertical-align: middle; height: ${height}px; width: ${width}px; line-height: ${height}px;display:inline-block'></div>`);
this.$()
.before($placeholder)
.css({
width,
position: "fixed",
"margin-top": -this.get("scrollableParent").scrollTop(),
"margin-left": -width
});
this.get("scrollableParent").on("scroll.select-box", () => this.set("expanded", false) );
},
_removeFixedPosition() {
$(`.select-box-fixed-placeholder-${this.get("componentId")}`).remove();
this.$().css({
top: "auto",
left: "auto",
"margin-left": "auto",
"margin-top": "auto",
position: "relative"
});
this.get("scrollableParent").off("scroll.select-box");
} }
}); });

View File

@ -1,3 +1,9 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
classNames: "select-box-collection" classNames: "select-box-collection",
actions: {
onClearSelection() {
this.sendAction("onClearSelection");
}
}
}); });

View File

@ -19,7 +19,11 @@
{{/each}} {{/each}}
{{else}} {{else}}
<label>{{i18n 'category.parent'}}</label> <label>{{i18n 'category.parent'}}</label>
{{category-chooser valueAttribute="id" value=category.parent_category_id categories=parentCategories rootNone=true allowUncategorized="true"}} {{category-select-box
clearSelectionLabel="category.none"
value=category.parent_category_id
categories=parentCategories
allowUncategorized=true}}
{{/if}} {{/if}}
</section> </section>
{{/if}} {{/if}}

View File

@ -24,7 +24,7 @@
<span class="edit-title"> <span class="edit-title">
{{text-field value=buffered.title maxlength=siteSettings.max_topic_title_length}} {{text-field value=buffered.title maxlength=siteSettings.max_topic_title_length}}
</span> </span>
{{category-chooser value=buffered.category_id}} {{category-select-box value=buffered.category_id}}
{{else}} {{else}}
<span class='post-title'> <span class='post-title'>
{{i18n "queue.topic"}} {{i18n "queue.topic"}}

View File

@ -30,6 +30,7 @@
{{/if}} {{/if}}
{{component selectBoxCollectionComponent {{component selectBoxCollectionComponent
clearSelectionLabel=clearSelectionLabel
filteredContent=filteredContent filteredContent=filteredContent
selectBoxRowComponent=selectBoxRowComponent selectBoxRowComponent=selectBoxRowComponent
templateForRow=templateForRow templateForRow=templateForRow
@ -38,7 +39,8 @@
lastHovered=lastHovered lastHovered=lastHovered
onSelectRow=(action "onSelectRow") onSelectRow=(action "onSelectRow")
onHoverRow=(action "onHoverRow") onHoverRow=(action "onHoverRow")
noContentText=noContentText onClearSelection=(action "onClearSelection")
noContentLabel=noContentLabel
value=value value=value
}} }}
{{/if}} {{/if}}

View File

@ -1,4 +1,10 @@
<ul class="collection"> <ul class="collection">
{{#if clearSelectionLabel}}
<li {{action "onClearSelection" on="click"}} class="select-box-row clear-selection">
{{i18n clearSelectionLabel}}
</li>
{{/if}}
{{#each filteredContent as |content|}} {{#each filteredContent as |content|}}
{{component selectBoxRowComponent {{component selectBoxRowComponent
content=content content=content
@ -11,9 +17,9 @@
value=value value=value
}} }}
{{else}} {{else}}
{{#if noContentText}} {{#if noContentLabel}}
<li class="select-box-row no-content"> <li class="select-box-row no-content">
{{noContentText}} {{noContentLabel}}
</li> </li>
{{/if}} {{/if}}
{{/each}} {{/each}}

View File

@ -1,6 +1,6 @@
<p>{{i18n "topics.bulk.choose_new_category"}}</p> <p>{{i18n "topics.bulk.choose_new_category"}}</p>
<p>{{category-chooser value=newCategoryId}}</p> <p>{{category-select-box value=newCategoryId}}</p>
{{#conditional-loading-spinner condition=loading}} {{#conditional-loading-spinner condition=loading}}
{{d-button action="changeCategory" label="topics.bulk.change_category"}} {{d-button action="changeCategory" label="topics.bulk.change_category"}}

View File

@ -13,10 +13,9 @@
{{else if publishToCategory}} {{else if publishToCategory}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'topic.topic_status_update.publish_to'}}</label> <label>{{i18n 'topic.topic_status_update.publish_to'}}</label>
{{category-chooser {{category-select-box
valueAttribute="id" value=topicTimer.category_id
value=topicTimer.category_id excludeCategoryId=excludeCategoryId}}
excludeCategoryId=excludeCategoryId}}
</div> </div>
{{auto-update-input {{auto-update-input

View File

@ -6,7 +6,7 @@
{{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}} {{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}}
<label>{{i18n 'categories.category'}}</label> <label>{{i18n 'categories.category'}}</label>
{{category-chooser value=categoryId}} {{category-select-box value=categoryId class="small"}}
</form> </form>
{{/d-modal-body}} {{/d-modal-body}}

View File

@ -349,7 +349,7 @@ td.flaggers td {
margin-top: 10px; margin-top: 10px;
} }
input, textarea, select { input, textarea, select, .select-box {
width: 350px; width: 350px;
} }
@ -1672,6 +1672,10 @@ table#user-badges {
} }
} }
.embedding td input {
margin-bottom: 0;
}
// Emails // Emails
.email-list { .email-list {

View File

@ -10,6 +10,10 @@
position: relative; position: relative;
height: 34px; height: 34px;
&.small {
height: 28px;
}
&.is-expanded { &.is-expanded {
z-index: 102; z-index: 102;
@ -97,6 +101,7 @@
.select-box-body { .select-box-body {
display: none; display: none;
background: $secondary;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }

View File

@ -239,7 +239,7 @@
position: relative; position: relative;
display: inline-block; display: inline-block;
.category-input { .category-input .category-select-box {
width: 430px; width: 430px;
@include medium-width { width: 285px; } @include medium-width { width: 285px; }
@include small-width { width: 220px; } @include small-width { width: 220px; }

View File

@ -70,6 +70,10 @@
} }
.modal { .modal {
.category-select-box {
width: 430px;
}
.category-combobox { .category-combobox {
width: 430px; width: 430px;

View File

@ -148,6 +148,10 @@ input[type=radio], input[type=checkbox] {
} }
.category-input { .category-input {
margin-top: 3px; margin-top: 3px;
.category-select-box {
width: 100%;
}
} }
.wmd-controls { .wmd-controls {
transition: top 0.3s ease; transition: top 0.3s ease;

View File

@ -91,10 +91,6 @@
width: 100%; width: 100%;
} }
} }
.category-combobox {
width: 100%;
}
} }
.flag-modal { .flag-modal {

View File

@ -74,11 +74,12 @@ QUnit.test("Subcategory list settings", assert => {
}); });
click('.edit-category-general'); click('.edit-category-general');
selectDropdown('.edit-category-tab-general .category-combobox', 2);
selectBox('.edit-category-tab-general .category-select-box', 'feature')
click('.edit-category-settings'); click('.edit-category-settings');
andThen(() => { andThen(() => {
assert.ok(!visible(".show-subcategory-list-field"), "show subcategory list isn't visible for child categories"); assert.ok(!visible(".show-subcategory-list-field"), "show subcategory list isn't visible for child categories");
assert.ok(!visible(".subcategory-list-style-field"), "subcategory list style isn't visible for child categories"); assert.ok(!visible(".subcategory-list-style-field"), "subcategory list style isn't visible for child categories");
}); });
}); });

View File

@ -20,7 +20,7 @@ QUnit.test("For topics: body of post, title, category and tags are all editbale"
andThen(() => { andThen(() => {
assert.ok(exists(".d-editor-container"), "the body should be editable"); assert.ok(exists(".d-editor-container"), "the body should be editable");
assert.ok(exists(".edit-title .ember-text-field"), "the title should be editable"); assert.ok(exists(".edit-title .ember-text-field"), "the title should be editable");
assert.ok(exists(".category-combobox"), "category should be editbale"); assert.ok(exists(".category-select-box"), "category should be editbale");
assert.ok(exists(".tag-chooser"), "tags should be editable"); assert.ok(exists(".tag-chooser"), "tags should be editable");
}); });
}); });
@ -41,7 +41,7 @@ QUnit.test("For replies: only the body of post is editbale", assert => {
andThen(() => { andThen(() => {
assert.ok(exists(".d-editor-container"), "the body should be editable"); assert.ok(exists(".d-editor-container"), "the body should be editable");
assert.notOk(exists(".edit-title .ember-text-field"), "title should not be editbale"); assert.notOk(exists(".edit-title .ember-text-field"), "title should not be editbale");
assert.notOk(exists(".category-combobox"), "category should not be editable"); assert.notOk(exists(".category-select-box"), "category should not be editable");
assert.notOk(exists("div.tag-chooser"), "tags should not be editable"); assert.notOk(exists("div.tag-chooser"), "tags should not be editable");
}); });
}); });

View File

@ -222,7 +222,7 @@ componentTest('persists filter state when expandind/collapsing', {
}); });
componentTest('supports options to limit size', { componentTest('supports options to limit size', {
template: '{{select-box width=50 maxCollectionHeight=20 content=content}}', template: '{{select-box maxCollectionHeight=20 content=content}}',
beforeEach() { beforeEach() {
this.set("content", [{ id: 1, text: "robin" }]); this.set("content", [{ id: 1, text: "robin" }]);
@ -233,7 +233,6 @@ componentTest('supports options to limit size', {
andThen(() => { andThen(() => {
assert.equal(find(".select-box-body").height(), 20, "it limits the height"); assert.equal(find(".select-box-body").height(), 20, "it limits the height");
assert.equal(find(".select-box").width(), 50, "it limits the width");
}); });
} }
}); });