Skip to content

Commit

Permalink
feat: [1.x] [extensibility] feat: allow to be extended
Browse files Browse the repository at this point in the history
  • Loading branch information
imorland committed Sep 26, 2024
1 parent e43530e commit 1e8c4b5
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 16 deletions.
2 changes: 2 additions & 0 deletions framework/core/js/src/forum/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import routes from './routes';
import ForumApplication from './ForumApplication';
import isSafariMobile from './utils/isSafariMobile';
import AccessTokensList from './components/AccessTokensList';
import DiscussionsSearchItem from './components/DiscussionsSearchItem';

export default Object.assign(compat, {
'utils/PostControls': PostControls,
Expand Down Expand Up @@ -114,6 +115,7 @@ export default Object.assign(compat, {
'components/IndexPage': IndexPage,
'components/DiscussionRenamedNotification': DiscussionRenamedNotification,
'components/DiscussionsSearchSource': DiscussionsSearchSource,
'components/DiscussionsSearchItem': DiscussionsSearchItem,
'components/HeaderSecondary': HeaderSecondary,
'components/ComposerButton': ComposerButton,
'components/DiscussionList': DiscussionList,
Expand Down
61 changes: 61 additions & 0 deletions framework/core/js/src/forum/components/DiscussionsSearchItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import app from '../../forum/app';
import Component, { ComponentAttrs } from '../../common/Component';
import Link from '../../common/components/Link';
import highlight from '../../common/helpers/highlight';
import Discussion from '../../common/models/Discussion';
import Post from '../../common/models/Post';
import type Mithril from 'mithril';
import ItemList from '../../common/utils/ItemList';

export interface DiscussionsSearchItemAttrs extends ComponentAttrs {
query: string;
discussion: Discussion;
mostRelevantPost: Post;
}

export default class DiscussionsSearchItem extends Component<DiscussionsSearchItemAttrs> {
query!: string;
discussion!: Discussion;
mostRelevantPost!: Post | null | undefined;

oninit(vnode: Mithril.Vnode<DiscussionsSearchItemAttrs, this>) {
super.oninit(vnode);

this.query = this.attrs.query;
this.discussion = this.attrs.discussion;
this.mostRelevantPost = this.attrs.mostRelevantPost;
}

view() {
return (
<li className="DiscussionSearchResult" data-index={'discussions' + this.discussion.id()}>
<Link href={app.route.discussion(this.discussion, (this.mostRelevantPost && this.mostRelevantPost.number()) || 0)}>
{this.viewItems().toArray()}
</Link>
</li>
);
}

discussionTitle() {
return this.discussion.title();
}

mostRelevantPostContent() {
return this.mostRelevantPost?.contentPlain();
}

viewItems(): ItemList<Mithril.Children> {
const items = new ItemList<Mithril.Children>();

items.add('discussion-title', <div className="DiscussionSearchResult-title">{highlight(this.discussionTitle(), this.query)}</div>, 90);

!!this.mostRelevantPost &&
items.add(
'most-relevant',
<div className="DiscussionSearchResult-excerpt">{highlight(this.mostRelevantPostContent() ?? '', this.query, 100)}</div>,
80
);

return items;
}
}
41 changes: 25 additions & 16 deletions framework/core/js/src/forum/components/DiscussionsSearchSource.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import app from '../../forum/app';
import highlight from '../../common/helpers/highlight';
import LinkButton from '../../common/components/LinkButton';
import Link from '../../common/components/Link';
import { SearchSource } from './Search';
import type Mithril from 'mithril';
import Discussion from '../../common/models/Discussion';
import DiscussionsSearchItem from './DiscussionsSearchItem';

/**
* The `DiscussionsSearchSource` finds and displays discussion search results in
* the search dropdown.
*/
export default class DiscussionsSearchSource implements SearchSource {
protected results = new Map<string, Discussion[]>();
queryString: string | null = null;

async search(query: string): Promise<void> {
query = query.toLowerCase();

this.results.set(query, []);

this.setQueryString(query);

const params = {
filter: { q: query },
page: { limit: 3 },
include: 'mostRelevantPost',
filter: { q: this.queryString || query },
page: { limit: this.limit() },
include: this.includes().join(','),
};

return app.store.find<Discussion[]>('discussions', params).then((results) => {
Expand All @@ -36,26 +38,33 @@ export default class DiscussionsSearchSource implements SearchSource {
const results = (this.results.get(query) || []).map((discussion) => {
const mostRelevantPost = discussion.mostRelevantPost();

return (
<li className="DiscussionSearchResult" data-index={'discussions' + discussion.id()}>
<Link href={app.route.discussion(discussion, (mostRelevantPost && mostRelevantPost.number()) || 0)}>
<div className="DiscussionSearchResult-title">{highlight(discussion.title(), query)}</div>
{!!mostRelevantPost && (
<div className="DiscussionSearchResult-excerpt">{highlight(mostRelevantPost.contentPlain() ?? '', query, 100)}</div>
)}
</Link>
</li>
);
return <DiscussionsSearchItem query={query} discussion={discussion} mostRelevantPost={mostRelevantPost} />;
}) as Array<Mithril.Vnode>;

return [
<li className="Dropdown-header">{app.translator.trans('core.forum.search.discussions_heading')}</li>,
<li>
<LinkButton icon="fas fa-search" href={app.route('index', { q: query })}>
<LinkButton icon="fas fa-search" href={app.route('index', { q: this.queryString })}>
{app.translator.trans('core.forum.search.all_discussions_button', { query })}
</LinkButton>
</li>,
...results,
];
}

includes(): string[] {
return ['mostRelevantPost'];
}

limit(): number {
return 3;
}

queryMutators(): string[] {
return [];
}

setQueryString(query: string): void {
this.queryString = query + ' ' + this.queryMutators().join(' ');
}
}

0 comments on commit 1e8c4b5

Please sign in to comment.