UX: Using CategoryChooser for param param_input (#306)
This change changes the category selector to use CategoryChooser instead of a bare text input to improve the user experience. Related meta link: https://meta.discourse.org/t/wishlist-param-dropdown-for-data-explorer-query/253883/28
This commit is contained in:
parent
41dfa217ca
commit
902b8c7913
|
@ -64,6 +64,14 @@
|
|||
/>
|
||||
<span class="param-name">{{@info.identifier}}</span>
|
||||
|
||||
{{else if (eq this.type "category_id")}}
|
||||
<CategoryChooser
|
||||
@value={{this.value}}
|
||||
@onChange={{this.updateValue}}
|
||||
name={{@info.identifier}}
|
||||
/>
|
||||
<span class="param-name">{{@info.identifier}}</span>
|
||||
|
||||
{{else}}
|
||||
<TextField
|
||||
@value={{this.value}}
|
||||
|
|
|
@ -19,7 +19,7 @@ const layoutMap = {
|
|||
user_id: "user_id",
|
||||
post_id: "string",
|
||||
topic_id: "generic",
|
||||
category_id: "generic",
|
||||
category_id: "category_id",
|
||||
group_id: "generic",
|
||||
badge_id: "generic",
|
||||
int_list: "generic",
|
||||
|
@ -62,24 +62,27 @@ export default class ParamInput extends Component {
|
|||
this.args.updateParams(this.args.info.identifier, this.boolValue);
|
||||
}
|
||||
} else {
|
||||
this.value =
|
||||
this.args.info.type === "category_id"
|
||||
? this.dasherizeCategoryId(initialValue)
|
||||
: initialValue;
|
||||
this.value = this.normalizeValue(initialValue);
|
||||
this.args.updateParams(this.args.info.identifier, this.value);
|
||||
}
|
||||
} else {
|
||||
// if no parsed params then get and set default values
|
||||
const defaultValue = this.args.info.default;
|
||||
this.value =
|
||||
this.args.info.type === "category_id"
|
||||
? this.dasherizeCategoryId(defaultValue)
|
||||
: defaultValue;
|
||||
this.value = this.normalizeValue(defaultValue);
|
||||
this.boolValue = defaultValue !== "false";
|
||||
this.nullableBoolValue = defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
normalizeValue(value) {
|
||||
switch (this.args.info.type) {
|
||||
case "category_id":
|
||||
return this.digitalizeCategoryId(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
get type() {
|
||||
const type = this.args.info.type;
|
||||
if ((type === "time" || type === "date") && !allowsInputTypeTime()) {
|
||||
|
@ -135,18 +138,8 @@ export default class ParamInput extends Component {
|
|||
case "category_id":
|
||||
if (isPositiveInt) {
|
||||
return !!this.site.categories.find((c) => c.id === intVal);
|
||||
} else if (/\//.test(value)) {
|
||||
const match = /(.*)\/(.*)/.exec(value);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
const result = Category.findBySlug(
|
||||
dasherize(match[2]),
|
||||
dasherize(match[1])
|
||||
);
|
||||
return !!result;
|
||||
} else {
|
||||
return !!Category.findBySlug(dasherize(value));
|
||||
return false;
|
||||
}
|
||||
case "group_id":
|
||||
const groups = this.site.get("groups");
|
||||
|
@ -163,13 +156,25 @@ export default class ParamInput extends Component {
|
|||
return this.site.get("groups");
|
||||
}
|
||||
|
||||
dasherizeCategoryId(value) {
|
||||
digitalizeCategoryId(value) {
|
||||
value = String(value || "");
|
||||
const isPositiveInt = /^\d+$/.test(value);
|
||||
if (!isPositiveInt && value !== dasherize(value)) {
|
||||
return dasherize(value);
|
||||
if (!isPositiveInt) {
|
||||
if (/\//.test(value)) {
|
||||
const match = /(.*)\/(.*)/.exec(value);
|
||||
if (!match) {
|
||||
value = null;
|
||||
} else {
|
||||
value = Category.findBySlug(
|
||||
dasherize(match[2]),
|
||||
dasherize(match[1])
|
||||
)?.id;
|
||||
}
|
||||
} else {
|
||||
value = Category.findBySlug(dasherize(value))?.id;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
return value?.toString();
|
||||
}
|
||||
|
||||
@action
|
||||
|
@ -177,12 +182,9 @@ export default class ParamInput extends Component {
|
|||
// handle selectKit inputs as well as traditional inputs
|
||||
const value = input.target ? input.target.value : input;
|
||||
if (value.length) {
|
||||
this.value =
|
||||
this.args.info.type === "category_id"
|
||||
? this.dasherizeCategoryId(value.toString())
|
||||
: value.toString();
|
||||
this.value = this.normalizeValue(value.toString());
|
||||
} else {
|
||||
this.value = value;
|
||||
this.value = this.normalizeValue(value);
|
||||
}
|
||||
|
||||
this.args.updateParams(this.args.info.identifier, this.value);
|
||||
|
|
|
@ -63,6 +63,12 @@ RSpec.describe "Param input", type: :system, js: true do
|
|||
|
||||
::DiscourseDataExplorer::Parameter
|
||||
.create_from_sql(ALL_PARAMS_SQL)
|
||||
.each { |param| expect(page).to have_css(".query-params [name=\"#{param.identifier}\"]") }
|
||||
.each do |param|
|
||||
if !param.nullable && param.type != :boolean && param.default.nil?
|
||||
expect(page).to have_css(".query-params .param.invalid [name=\"#{param.identifier}\"]")
|
||||
else
|
||||
expect(page).to have_css(".query-params .param.valid [name=\"#{param.identifier}\"]")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { render } from "@ember/test-helpers";
|
||||
import hbs from "htmlbars-inline-precompile";
|
||||
import { module, test } from "qunit";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
const values = {};
|
||||
function updateParams(identifier, value) {
|
||||
values[identifier] = value;
|
||||
}
|
||||
|
||||
module("Data Explorer Plugin | Component | param-input", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("Renders the categroy_id type correctly", async function (assert) {
|
||||
this.setProperties({
|
||||
info: {
|
||||
identifier: "category_id",
|
||||
type: "category_id",
|
||||
default: null,
|
||||
nullable: false,
|
||||
},
|
||||
initialValues: {},
|
||||
params: {},
|
||||
updateParams,
|
||||
});
|
||||
|
||||
await render(hbs`<ParamInput
|
||||
@params={{this.params}}
|
||||
@initialValues={{this.initialValues}}
|
||||
@info={{this.info}}
|
||||
@updateParams={{this.updateParams}}
|
||||
/>`);
|
||||
|
||||
const categoryChooser = selectKit(".category-chooser");
|
||||
|
||||
await categoryChooser.expand();
|
||||
await categoryChooser.selectRowByValue(2);
|
||||
|
||||
assert.strictEqual(values.category_id, "2");
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue