mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-07 10:56:41 +08:00
## Summary The existing column-based topic list API works well for simple layouts, but becomes unwieldy when trying to create richer card designs. Adding features like assigned users, vote counts, solved status, tags, and excerpts to the grid system required increasingly complex CSS hacks and left awkward empty spaces when optional elements weren't present. This adds a new "high context" layout mode that takes a different approach: instead of fighting the column system, we use the topic-list-columns API to replace all columns with a single component that has full control over its internal layout. This gives us the flexibility to arrange content in logical rows (header, content, context, footer) using simple flexbox, without the rigidity of the grid. ## Changes ### Horizon Theme The new `topic_card_context` theme setting lets admins choose between: - **Simple** - the existing compact layout - **High Context (experimental)** - rich cards with additional information The high context cards display: - Creator avatar and username with timestamp - Solved/unsolved status pill (when discourse-solved is enabled) - Hot/pinned status indicators - Topic title with status icons - Post excerpt - Last reply info with relative timestamp - Assigned users including post-level assignments (when discourse-assign is enabled) - Vote count badge (when discourse-topic-voting is enabled) - Category badge and tags - Reply and like counts - Unread indicator and post badges The layout is only applied to public topic list routes (discovery and tag routes), falling back to simple layout on private messages, user activity, and bookmarks pages. ### Core Changes **BEM naming for topic status classes:** - All status classes now use `--modifier` pattern: `--bookmarked`, `--closed`, `--archived`, `--warning`, `--personal-message`, `--pinned`, `--unpinned`, `--invisible` - Updated discourse-solved plugin to use `--solved` and `--unsolved` **Code cleanup:** - Extracted duplicated bulk selection checkbox into reusable `BulkSelectCheckbox` component - Removed unused `newDotText` getter from topic-cell - Added `className` parameter to `render-tags` helper for flexibility --------- Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
50 lines
1.7 KiB
JavaScript
50 lines
1.7 KiB
JavaScript
import { click, fillIn, visit } from "@ember/test-helpers";
|
|
import { test } from "qunit";
|
|
import { cloneJSON } from "discourse/lib/object";
|
|
import pretender, {
|
|
fixturesByUrl,
|
|
response,
|
|
} from "discourse/tests/helpers/create-pretender";
|
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
|
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
|
|
|
acceptance(`Discourse Solved Plugin`, function (needs) {
|
|
needs.user();
|
|
|
|
test("A topic with an accepted answer shows an excerpt of the answer, if provided", async function (assert) {
|
|
pretender.get("/t/11.json", () =>
|
|
response(postStreamWithAcceptedAnswerExcerpt("this is an excerpt"))
|
|
);
|
|
|
|
pretender.get("/t/12.json", () =>
|
|
response(postStreamWithAcceptedAnswerExcerpt(null))
|
|
);
|
|
|
|
await visit("/t/with-excerpt/11");
|
|
|
|
assert.dom(".quote.accepted-answer blockquote").exists();
|
|
assert
|
|
.dom(".quote.accepted-answer blockquote")
|
|
.hasText("this is an excerpt");
|
|
|
|
await visit("/t/without-excerpt/12");
|
|
|
|
assert.dom(".quote.accepted-answer.title-only").exists();
|
|
assert.dom(".quote.accepted-answer blockquote").doesNotExist();
|
|
});
|
|
|
|
test("Full page search displays solved status", async function (assert) {
|
|
pretender.get("/search", () => {
|
|
const fixtures = cloneJSON(fixturesByUrl["/search.json"]);
|
|
fixtures.topics[0].has_accepted_answer = true;
|
|
return response(fixtures);
|
|
});
|
|
|
|
await visit("/search");
|
|
await fillIn(".search-query", "discourse");
|
|
await click(".search-cta");
|
|
|
|
assert.dom(".fps-topic").exists({ count: 1 }, "has one post");
|
|
assert.dom(".topic-statuses .--solved").exists("shows the right icon");
|
|
});
|
|
});
|