From 746c5927e13a22829cdf83500fe7b10ddf362471 Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Wed, 30 Aug 2017 17:04:17 +0200 Subject: [PATCH] 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. --- .../templates/components/embeddable-host.hbs | 2 +- .../components/category-select-box.js.es6 | 21 +++- .../discourse/components/select-box.js.es6 | 95 +++++++++++++++---- .../select-box/select-box-collection.js.es6 | 8 +- .../components/edit-category-general.hbs | 6 +- .../templates/components/queued-post.hbs | 2 +- .../templates/components/select-box.hbs | 4 +- .../select-box/select-box-collection.hbs | 10 +- .../templates/modal/bulk-change-category.hbs | 2 +- .../templates/modal/edit-topic-timer.hbs | 7 +- .../discourse/templates/modal/split-topic.hbs | 2 +- .../stylesheets/common/admin/admin_base.scss | 6 +- .../common/components/select-box.scss | 5 + app/assets/stylesheets/desktop/compose.scss | 2 +- app/assets/stylesheets/desktop/modal.scss | 4 + app/assets/stylesheets/mobile/compose.scss | 4 + app/assets/stylesheets/mobile/modal.scss | 4 - .../acceptance/category-edit-test.js.es6 | 5 +- .../acceptance/queued-posts-test.js.es6 | 4 +- .../components/select-box-test.js.es6 | 3 +- 20 files changed, 145 insertions(+), 51 deletions(-) diff --git a/app/assets/javascripts/admin/templates/components/embeddable-host.hbs b/app/assets/javascripts/admin/templates/components/embeddable-host.hbs index f4367abefff..88317ecd187 100644 --- a/app/assets/javascripts/admin/templates/components/embeddable-host.hbs +++ b/app/assets/javascripts/admin/templates/components/embeddable-host.hbs @@ -9,7 +9,7 @@ {{input value=buffered.path_whitelist placeholder="/blog/.*" enter="save" class="path-whitelist"}} - {{category-chooser value=categoryId}} + {{category-select-box value=categoryId class="small"}} {{d-button icon="check" action="save" class="btn-primary" disabled=cantSave}} diff --git a/app/assets/javascripts/discourse/components/category-select-box.js.es6 b/app/assets/javascripts/discourse/components/category-select-box.js.es6 index 9dfe0302a1d..185dfe673f4 100644 --- a/app/assets/javascripts/discourse/components/category-select-box.js.es6 +++ b/app/assets/javascripts/discourse/components/category-select-box.js.es6 @@ -15,10 +15,19 @@ export default SelectBoxComponent.extend({ castInteger: true, - width: "100%", - clearable: true, + allowUncategorized: null, + + init() { + this._super(); + + if (!Ember.isNone(this.get("categories"))) { + this.set("content", this.get("categories")); + this._scopeCategories(); + } + }, + filterFunction: function(content) { const _matchFunction = (filter, text) => { return text.toLowerCase().indexOf(filter) > -1; @@ -57,7 +66,6 @@ export default SelectBoxComponent.extend({ this.set("headerText", headerText); }, - // original method is kept for compatibility templateForRow: function() { return (rowComponent) => this.rowContentTemplate(rowComponent.get("content")); }.property(), @@ -79,8 +87,11 @@ export default SelectBoxComponent.extend({ const categoryId = c.get("id"); if (scopedCategoryId && categoryId !== scopedCategoryId && c.get("parent_category_id") !== scopedCategoryId) { return false; } if (excludeCategoryId === categoryId) { return false; } - if (!this.siteSettings.allow_uncategorized_topics && c.get("isUncategorizedCategory")) { - return false; + if (this.get("allowUncategorized") === false && c.get("isUncategorizedCategory")) { return false; } + if (this.get("allowUncategorized") !== true) { + if (!this.siteSettings.allow_uncategorized_topics && c.get("isUncategorizedCategory")) { + return false; + } } return c.get("permission") === PermissionType.FULL; }); diff --git a/app/assets/javascripts/discourse/components/select-box.js.es6 b/app/assets/javascripts/discourse/components/select-box.js.es6 index 3085f35eaea..8a48b9e4d3a 100644 --- a/app/assets/javascripts/discourse/components/select-box.js.es6 +++ b/app/assets/javascripts/discourse/components/select-box.js.es6 @@ -14,6 +14,7 @@ export default Ember.Component.extend({ renderBody: false, wrapper: true, tabindex: 0, + scrollableParentSelector: ".modal-body", caretUpIcon: "caret-up", caretDownIcon: "caret-down", @@ -24,8 +25,9 @@ export default Ember.Component.extend({ value: null, selectedContent: null, - noContentText: I18n.t("select_box.no_content"), + noContentLabel: I18n.t("select_box.no_content"), lastHovered: null, + clearSelectionLabel: null, idKey: "id", textKey: "text", @@ -41,7 +43,7 @@ export default Ember.Component.extend({ selectBoxHeaderComponent: "select-box/select-box-header", selectBoxCollectionComponent: "select-box/select-box-collection", - width: 220, + minWidth: 220, maxCollectionHeight: 200, verticalOffset: 0, horizontalOffset: 0, @@ -65,7 +67,7 @@ export default Ember.Component.extend({ shouldHighlightRow: function() { return (rowComponent) => { - if (Ember.isNone(this.get("value"))) { + if (Ember.isNone(this.get("value")) && Ember.isNone(this.get("lastHovered"))) { return false; } @@ -96,14 +98,14 @@ export default Ember.Component.extend({ applyDirection() { const offsetTop = this.$()[0].getBoundingClientRect().top; const windowHeight = $(window).height(); - const headerHeight = this.$(".select-box-header").outerHeight(); - const filterHeight = this.$(".select-box-filter").outerHeight(); + const headerHeight = this.$(".select-box-header").outerHeight(false); + const filterHeight = this.$(".select-box-filter").outerHeight(false); if (windowHeight - (offsetTop + this.get("maxCollectionHeight") + filterHeight + headerHeight) < 0) { this.$().addClass("is-reversed"); this.$(".select-box-body").css({ left: this.get("horizontalOffset"), - top: "", + top: "auto", bottom: headerHeight + this.get("verticalOffset") }); } else { @@ -111,7 +113,7 @@ export default Ember.Component.extend({ this.$(".select-box-body").css({ left: this.get("horizontalOffset"), top: headerHeight + this.get("verticalOffset"), - bottom: "" + bottom: "auto" }); } }, @@ -150,21 +152,31 @@ export default Ember.Component.extend({ @on("didRender") _configureSelectBoxDOM: function() { - this.$().css("width", this.get("width")); - this.$(".select-box-header").css("height", this.$().css("height")); - this.$(".select-box-filter").css("height", this.$().css("height")); + if (this.get("scrollableParent").length === 1) { + this._removeFixedPosition(); + } + + 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")) { - 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")); - Ember.run.schedule("afterRender", () => { - this.applyDirection(); + this.applyDirection(); - if (this.get("wrapper")) { - this._positionSelectBoxWrapper(); - } - }); + if (this.get("wrapper")) { + this._positionSelectBoxWrapper(); + } } else { if (this.get("wrapper")) { this.$(".select-box-wrapper").hide(); @@ -250,12 +262,16 @@ export default Ember.Component.extend({ }); }, - @computed("headerText", "dynamicHeaderText", "selectedContent", "textKey") - generatedHeadertext(headerText, dynamic, selectedContent, textKey) { + @computed("headerText", "dynamicHeaderText", "selectedContent", "textKey", "clearSelectionLabel") + generatedHeadertext(headerText, dynamic, selectedContent, textKey, clearSelectionLabel) { if (dynamic && !Ember.isNone(selectedContent)) { return selectedContent[textKey]; } + if (dynamic && Ember.isNone(selectedContent) && !Ember.isNone(clearSelectionLabel)) { + return I18n.t(clearSelectionLabel); + } + return headerText; }, @@ -272,6 +288,11 @@ export default Ember.Component.extend({ return filteredContent; }, + @computed("scrollableParentSelector") + scrollableParent(scrollableParentSelector) { + return this.$().parents(scrollableParentSelector).first(); + }, + actions: { onToggle() { this.toggleProperty("expanded"); @@ -288,18 +309,22 @@ export default Ember.Component.extend({ }); }, + onClearSelection() { + this.setProperties({ value: null, expanded: false }); + }, + onHoverRow(content) { this.set("lastHovered", this._castInteger(content[this.get("idKey")])); } }, _positionSelectBoxWrapper() { - const headerHeight = this.$(".select-box-header").outerHeight(); + const headerHeight = this.$(".select-box-header").outerHeight(false); this.$(".select-box-wrapper").css({ width: this.$().width(), 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; + }, + + _applyFixedPosition(width, height) { + const $placeholder = $(`
`); + + 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"); } }); diff --git a/app/assets/javascripts/discourse/components/select-box/select-box-collection.js.es6 b/app/assets/javascripts/discourse/components/select-box/select-box-collection.js.es6 index 922121c7088..4b5fea95d5b 100644 --- a/app/assets/javascripts/discourse/components/select-box/select-box-collection.js.es6 +++ b/app/assets/javascripts/discourse/components/select-box/select-box-collection.js.es6 @@ -1,3 +1,9 @@ export default Ember.Component.extend({ - classNames: "select-box-collection" + classNames: "select-box-collection", + + actions: { + onClearSelection() { + this.sendAction("onClearSelection"); + } + } }); diff --git a/app/assets/javascripts/discourse/templates/components/edit-category-general.hbs b/app/assets/javascripts/discourse/templates/components/edit-category-general.hbs index 734ad2b4c70..d0690538630 100644 --- a/app/assets/javascripts/discourse/templates/components/edit-category-general.hbs +++ b/app/assets/javascripts/discourse/templates/components/edit-category-general.hbs @@ -19,7 +19,11 @@ {{/each}} {{else}} - {{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}} diff --git a/app/assets/javascripts/discourse/templates/components/queued-post.hbs b/app/assets/javascripts/discourse/templates/components/queued-post.hbs index e0bbe42ac7f..172275ce093 100644 --- a/app/assets/javascripts/discourse/templates/components/queued-post.hbs +++ b/app/assets/javascripts/discourse/templates/components/queued-post.hbs @@ -24,7 +24,7 @@ {{text-field value=buffered.title maxlength=siteSettings.max_topic_title_length}} - {{category-chooser value=buffered.category_id}} + {{category-select-box value=buffered.category_id}} {{else}} {{i18n "queue.topic"}} diff --git a/app/assets/javascripts/discourse/templates/components/select-box.hbs b/app/assets/javascripts/discourse/templates/components/select-box.hbs index 65e99d5b8ac..338c850b881 100644 --- a/app/assets/javascripts/discourse/templates/components/select-box.hbs +++ b/app/assets/javascripts/discourse/templates/components/select-box.hbs @@ -30,6 +30,7 @@ {{/if}} {{component selectBoxCollectionComponent + clearSelectionLabel=clearSelectionLabel filteredContent=filteredContent selectBoxRowComponent=selectBoxRowComponent templateForRow=templateForRow @@ -38,7 +39,8 @@ lastHovered=lastHovered onSelectRow=(action "onSelectRow") onHoverRow=(action "onHoverRow") - noContentText=noContentText + onClearSelection=(action "onClearSelection") + noContentLabel=noContentLabel value=value }} {{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/select-box/select-box-collection.hbs b/app/assets/javascripts/discourse/templates/components/select-box/select-box-collection.hbs index 5c0123b6471..1e0aae5268d 100644 --- a/app/assets/javascripts/discourse/templates/components/select-box/select-box-collection.hbs +++ b/app/assets/javascripts/discourse/templates/components/select-box/select-box-collection.hbs @@ -1,4 +1,10 @@