Skip to content
This repository was archived by the owner on Jul 14, 2025. It is now read-only.

Commit 5a2bfce

Browse files
Yuriy Kurantjjaffeux
andauthored
UX: category-id-input: allows no-category selection (#377)
The `category_id` parameter now includes the *(no category)* option, which allows clearing a previously selected category. The *(no category)* option is selected by default. --------- Co-authored-by: Joffrey JAFFEUX <[email protected]>
1 parent a0a7f8d commit 5a2bfce

File tree

3 files changed

+90
-155
lines changed

3 files changed

+90
-155
lines changed

assets/javascripts/discourse/components/param-input/category-id-input.gjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Component from "@glimmer/component";
2+
import { hash } from "@ember/helper";
23
import CategoryChooser from "select-kit/components/category-chooser";
34

45
export default class CategoryIdInput extends Component {
@@ -15,6 +16,11 @@ export default class CategoryIdInput extends Component {
1516
<CategoryChooser
1617
@value={{this.data.value}}
1718
@onChange={{@field.set}}
19+
@options={{hash
20+
allowUncategorized=null
21+
autoInsertNoneItem=true
22+
none=true
23+
}}
1824
name={{@info.identifier}}
1925
/>
2026
</@field.Custom>

test/javascripts/acceptance/list-queries-test.js

Lines changed: 1 addition & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,7 @@ acceptance("Data Explorer Plugin | List Queries", function (needs) {
99

1010
needs.pretender((server, helper) => {
1111
server.get("/admin/plugins/explorer/groups.json", () => {
12-
return helper.response([
13-
{
14-
id: 1,
15-
name: "admins",
16-
},
17-
{
18-
id: 2,
19-
name: "moderators",
20-
},
21-
{
22-
id: 3,
23-
name: "staff",
24-
},
25-
{
26-
id: 0,
27-
name: "everyone",
28-
},
29-
{
30-
id: 10,
31-
name: "trust_level_0",
32-
},
33-
{
34-
id: 11,
35-
name: "trust_level_1",
36-
},
37-
{
38-
id: 12,
39-
name: "trust_level_2",
40-
},
41-
{
42-
id: 13,
43-
name: "trust_level_3",
44-
},
45-
{
46-
id: 14,
47-
name: "trust_level_4",
48-
},
49-
]);
50-
});
51-
52-
server.get("/admin/plugins/explorer/schema.json", () => {
53-
return helper.response({
54-
anonymous_users: [
55-
{
56-
column_name: "id",
57-
data_type: "serial",
58-
primary: true,
59-
},
60-
{
61-
column_name: "user_id",
62-
data_type: "integer",
63-
fkey_info: "users",
64-
},
65-
{
66-
column_name: "master_user_id",
67-
data_type: "integer",
68-
fkey_info: "users",
69-
},
70-
{
71-
column_name: "active",
72-
data_type: "boolean",
73-
},
74-
{
75-
column_name: "created_at",
76-
data_type: "timestamp",
77-
},
78-
{
79-
column_name: "updated_at",
80-
data_type: "timestamp",
81-
},
82-
],
83-
});
12+
return helper.response([]);
8413
});
8514

8615
server.get("/admin/plugins/explorer/queries", () => {

test/javascripts/acceptance/param-input-test.js

Lines changed: 83 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,24 @@
11
import { click, currentURL, fillIn, visit } from "@ember/test-helpers";
22
import { test } from "qunit";
3+
import Category from "discourse/models/category";
34
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
5+
import selectKit from "discourse/tests/helpers/select-kit-helper";
6+
7+
async function runQuery() {
8+
await click("form.query-run button");
9+
}
410

511
acceptance("Data Explorer Plugin | Param Input", function (needs) {
612
needs.user();
713
needs.settings({ data_explorer_enabled: true });
814

915
needs.pretender((server, helper) => {
1016
server.get("/admin/plugins/explorer/groups.json", () => {
11-
return helper.response([
12-
{
13-
id: 1,
14-
name: "admins",
15-
},
16-
{
17-
id: 2,
18-
name: "moderators",
19-
},
20-
{
21-
id: 3,
22-
name: "staff",
23-
},
24-
{
25-
id: 0,
26-
name: "everyone",
27-
},
28-
{
29-
id: 10,
30-
name: "trust_level_0",
31-
},
32-
{
33-
id: 11,
34-
name: "trust_level_1",
35-
},
36-
{
37-
id: 12,
38-
name: "trust_level_2",
39-
},
40-
{
41-
id: 13,
42-
name: "trust_level_3",
43-
},
44-
{
45-
id: 14,
46-
name: "trust_level_4",
47-
},
48-
{
49-
id: 41,
50-
name: "discourse",
51-
},
52-
]);
17+
return helper.response([]);
5318
});
5419

5520
server.get("/admin/plugins/explorer/schema.json", () => {
56-
return helper.response({
57-
anonymous_users: [
58-
{
59-
column_name: "id",
60-
data_type: "serial",
61-
primary: true,
62-
},
63-
{
64-
column_name: "user_id",
65-
data_type: "integer",
66-
fkey_info: "users",
67-
},
68-
{
69-
column_name: "master_user_id",
70-
data_type: "integer",
71-
fkey_info: "users",
72-
},
73-
{
74-
column_name: "active",
75-
data_type: "boolean",
76-
},
77-
{
78-
column_name: "created_at",
79-
data_type: "timestamp",
80-
},
81-
{
82-
column_name: "updated_at",
83-
data_type: "timestamp",
84-
},
85-
],
86-
});
21+
return helper.response({});
8722
});
8823

8924
server.get("/admin/plugins/explorer/queries", () => {
@@ -373,28 +308,58 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) {
373308
},
374309
});
375310
});
311+
312+
server.get("/admin/plugins/explorer/queries/4", () => {
313+
return helper.response({
314+
query: {
315+
id: 4,
316+
sql: "-- [params]\n-- null category_id :category\n\nSELECT 1",
317+
name: "Params test - category_id chooser",
318+
description: "Test for category_id param.",
319+
param_info: [
320+
{
321+
identifier: "category",
322+
type: "category_id",
323+
default: null,
324+
nullable: true,
325+
},
326+
],
327+
created_at: "2025-06-03T09:05:59.337Z",
328+
username: "system",
329+
group_ids: [],
330+
last_run_at: "2025-06-03T09:05:59.337Z",
331+
hidden: false,
332+
category_id: null,
333+
},
334+
});
335+
});
336+
337+
server.post("/admin/plugins/explorer/queries/4/run", () => {
338+
return helper.response({});
339+
});
376340
});
377341

342+
function getSearchParam(param) {
343+
const searchParams = new URLSearchParams(currentURL().split("?")[1]);
344+
return JSON.parse(searchParams.get("params"))[param];
345+
}
346+
378347
test("puts params for the query into the url", async function (assert) {
379348
await visit("/admin/plugins/explorer/queries/-6");
380349
const monthsAgoValue = "2";
381350
await fillIn(".query-params input", monthsAgoValue);
382-
await click("form.query-run button");
351+
await runQuery();
383352

384-
const searchParams = new URLSearchParams(currentURL().split("?")[1]);
385-
const monthsAgoParam = JSON.parse(searchParams.get("params")).months_ago;
386-
assert.strictEqual(monthsAgoParam, monthsAgoValue);
353+
assert.strictEqual(getSearchParam("months_ago"), monthsAgoValue);
387354
});
388355

389356
test("puts params for the query into the url for group reports", async function (assert) {
390357
await visit("/g/discourse/reports/-8");
391358
const monthsAgoValue = "2";
392359
await fillIn(".query-params input", monthsAgoValue);
393-
await click("form.query-run button");
360+
await runQuery();
394361

395-
const searchParams = new URLSearchParams(currentURL().split("?")[1]);
396-
const monthsAgoParam = JSON.parse(searchParams.get("params")).months_ago;
397-
assert.strictEqual(monthsAgoParam, monthsAgoValue);
362+
assert.strictEqual(getSearchParam("months_ago"), monthsAgoValue);
398363
});
399364

400365
test("loads the page if one of the parameter is null", async function (assert) {
@@ -413,20 +378,55 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) {
413378
await visit("/g/discourse/reports/-8");
414379
const monthsAgoValue = "2";
415380
await fillIn(".query-params input", monthsAgoValue);
416-
await click("form.query-run button");
381+
await runQuery();
417382
assert.dom(".query-params input").hasValue(monthsAgoValue);
418383
});
419384

420385
test("creates input boxes if has parameters when save", async function (assert) {
421386
await visit("/admin/plugins/explorer/queries/3");
422387
assert.dom(".query-params input").doesNotExist();
423388
await click(".query-edit .btn-edit-query");
424-
await click(".query-editor .ace_text-input");
425389
await fillIn(
426390
".query-editor .ace_text-input",
427391
"-- [params]\n-- int :months_ago = 1\n\nSELECT 1"
428392
);
393+
await click(".query-editor .ace_text-input"); // enables `Save Changes` button
429394
await click(".query-edit .btn-save-query");
430395
assert.dom(".query-params input").exists();
431396
});
397+
398+
test("nullable category_id param", async function (assert) {
399+
await visit("/admin/plugins/explorer/queries/4");
400+
const catChooser = selectKit(".category-chooser");
401+
402+
assert.strictEqual(catChooser.header().value(), null);
403+
404+
await runQuery();
405+
406+
assert.strictEqual(getSearchParam("category"), "");
407+
408+
const category = Category.findById(6);
409+
await catChooser.expand();
410+
await catChooser.selectRowByValue(category.id);
411+
412+
assert.strictEqual(catChooser.header().label(), category.name);
413+
414+
await runQuery();
415+
416+
assert.strictEqual(
417+
getSearchParam("category"),
418+
category.id.toString(),
419+
"it updates the URL with the selected category id"
420+
);
421+
422+
await catChooser.expand();
423+
await catChooser.selectRowByIndex(0);
424+
await runQuery();
425+
426+
assert.strictEqual(
427+
getSearchParam("category"),
428+
undefined,
429+
"it removes the category id from the URL when selecting the first row (null value)"
430+
);
431+
});
432432
});

0 commit comments

Comments
 (0)