Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: TS refactor #107

Merged
merged 28 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a9b23c5
wip: full ts
imorland Oct 23, 2024
7f74bcf
wip
imorland Oct 28, 2024
1d72f89
progress..
imorland Oct 31, 2024
e6a07c4
fix some ts erros
imorland Oct 31, 2024
cb6013f
more ts
imorland Oct 31, 2024
07570fb
ts
imorland Oct 31, 2024
310263d
disable ts
imorland Oct 31, 2024
c8cdaeb
chore: install typescript-coverage-report, reenable TS in workflow
DavideIadeluca Nov 1, 2024
6c77ba5
fix: add a11y label to jump button
imorland Nov 1, 2024
0e4c161
Update js/src/forum/components/SelectBestAnswerNotification.ts
imorland Nov 1, 2024
0896f79
Update js/src/forum/components/SolutionSearchItem.tsx
imorland Nov 1, 2024
45d0f8b
Update js/src/forum/components/SolutionSearchItem.tsx
imorland Nov 1, 2024
9771c9b
Update js/src/forum/components/SolutionSearchItem.tsx
imorland Nov 1, 2024
7dda67a
Update js/src/forum/extend.ts
imorland Nov 1, 2024
12e9a89
Update js/src/forum/extenders/extendDiscussionComposer.tsx
imorland Nov 1, 2024
4ab4534
Update js/src/forum/extenders/extendDiscussionSearchSource.tsx
imorland Nov 1, 2024
151537b
Update js/src/forum/components/AwardedBestAnswerNotification.ts
imorland Nov 1, 2024
cdb4c5a
Update js/src/forum/components/BestAnswerInDiscussionNotification.ts
imorland Nov 1, 2024
b3706dc
chore: remove unneeded tsignore
imorland Nov 1, 2024
da39943
Update js/src/forum/addBestAnswerCountToUsers.tsx
imorland Nov 1, 2024
63e97d4
Update js/src/@types/shims.d.ts
imorland Nov 1, 2024
fb2c686
Update js/src/@types/shims.d.ts
imorland Nov 1, 2024
6a8a887
Update js/src/forum/extenders/extendIndexPage.tsx
imorland Nov 1, 2024
1527ed0
Update js/src/forum/extenders/extendIndexPage.tsx
imorland Nov 1, 2024
440b89c
import type PaginatedListParams
imorland Nov 1, 2024
f8a2b0c
chore: format
imorland Nov 1, 2024
a73cbd3
chore: add dummy imports
imorland Nov 2, 2024
a1c51f8
chore: format
imorland Nov 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
enable_typescript: true

frontend_directory: ./js
backend_directory: .
Expand Down
11 changes: 5 additions & 6 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
"version": "0.0.0",
"private": true,
"prettier": "@flarum/prettier-config",
"dependencies": {
"devDependencies": {
"@flarum/prettier-config": "^1.0.0",
"flarum-tsconfig": "^1.0.2",
"flarum-tsconfig": "^1.0.3",
"flarum-webpack-config": "^2.0.2",
"webpack": "^5.88.0",
"webpack-cli": "^5.1.4"
},
"devDependencies": {
"prettier": "^3.0.3"
"webpack-cli": "^5.1.4",
"prettier": "^3.3.3",
"typescript-coverage-report": "^0.6.1"
},
"scripts": {
"dev": "webpack --mode development --watch",
Expand Down
35 changes: 28 additions & 7 deletions js/src/@types/shims.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
import Post from 'flarum/common/models/Post';
import User from 'flarum/common/models/User';
import 'flarum/common/models/Discussion'
import 'flarum/tags/common/models/Tag'
import 'flarum/forum/states/DiscussionListState'
import 'flarum/common/models/User'

import type Post from 'flarum/common/models/Post';
import type Discussion from 'flarum/common/models/Discussion';
import type User from 'flarum/common/models/User';
import type Tag from 'flarum/tags/common/models/Tag';
import type DiscussionListState from 'flarum/forum/states/DiscussionListState';

declare module 'flarum/common/models/Discussion' {
export default interface Discussion {
hasBestAnswer(): boolean;
bestAnswerPost(): Post;
bestAnswerUser(): User;
hasBestAnswer(): boolean | undefined;
bestAnswerPost(): Post | null;
bestAnswerUser(): User | null;
canSelectBestAnswer(): boolean;
bestAnswerSetAt(): Date;
bestAnswerSetAt(): Date | null;
}
}

declare module 'flarum/tags/models/Tag' {
declare module 'flarum/tags/common/models/Tag' {
export default interface Tag {
isQnA(): boolean;
reminders(): boolean;
}
}

declare module 'flarum/forum/states/DiscussionListState' {
export default interface DiscussionListState {
bestAnswer: string | undefined;
}
}

declare module 'flarum/common/models/User' {
export default interface User {
bestAnswerCount(): number;
}
}
3 changes: 1 addition & 2 deletions js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Extend from 'flarum/common/extenders';
// @ts-ignore
import Tag from 'flarum/tags/models/Tag';
import Tag from 'flarum/tags/common/models/Tag';

export default [
new Extend.Model(Tag) //
Expand Down
117 changes: 0 additions & 117 deletions js/src/forum/addBestAnswerAction.js

This file was deleted.

123 changes: 123 additions & 0 deletions js/src/forum/addBestAnswerAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import app from 'flarum/forum/app';
import { extend } from 'flarum/common/extend';
import Button from 'flarum/common/components/Button';
import PostControls from 'flarum/forum/utils/PostControls';
import DiscussionPage from 'flarum/forum/components/DiscussionPage';
import CommentPost from 'flarum/forum/components/CommentPost';
import Discussion from 'flarum/common/models/Discussion';
import Post from 'flarum/common/models/Post';
import extractText from 'flarum/common/utils/extractText';

export default function addBestAnswerAction() {
const ineligible = (discussion: Discussion, post: Post) => {
return post.isHidden() || post.number() === 1 || !discussion.canSelectBestAnswer() || !app.session.user;
};

const blockSelectOwnPost = (post: Post): boolean => {
const user = post.user();
return !app.forum.attribute<boolean>('canSelectBestAnswerOwnPost') && user !== false && user.id() === app.session.user?.id();
};

const isThisBestAnswer = (discussion: Discussion, post: Post): boolean => {
const bestAnswerPost = discussion.bestAnswerPost();
const hasBestAnswer = discussion.hasBestAnswer();
return hasBestAnswer !== undefined && hasBestAnswer && bestAnswerPost !== null && bestAnswerPost.id() === post.id();
};

const actionLabel = (isBestAnswer: boolean): string => {
return extractText(app.translator.trans(isBestAnswer ? 'fof-best-answer.forum.remove_best_answer' : 'fof-best-answer.forum.this_best_answer'));
};

const saveDiscussion = (discussion: Discussion, isBestAnswer: boolean, post: Post) =>
discussion
.save(
{
bestAnswerPostId: isBestAnswer ? post.id() : 0,
bestAnswerUserId: app.session.user?.id(),
relationships: isBestAnswer ? { bestAnswerPost: post, bestAnswerUser: app.session.user } : { bestAnswerPost: null },
},
{
params: {
include: 'tags',
},
}
)
.then(() => {
if (!isBestAnswer) {
if (discussion.data.relationships) {
delete discussion.data.relationships.bestAnswerPost;
delete discussion.data.relationships.bestAnswerUser;
}
}

if (app.current.matches(DiscussionPage)) {
app.current.get('stream').update();
}

m.redraw();

if (isBestAnswer) {
m.route.set(app.route.discussion(discussion));
}
});

extend(PostControls, 'moderationControls', function (items, post) {
if (app.forum.attribute('useAlternativeBestAnswerUi')) return;

const discussion = post.discussion();
let isBestAnswer = isThisBestAnswer(discussion, post);

post.pushAttributes({ isBestAnswer });

if (post.contentType() !== 'comment') return;

if (ineligible(discussion, post) || blockSelectOwnPost(post) || !app.current.matches(DiscussionPage)) return;

items.add(
'bestAnswer',
<Button
icon={`fa${isBestAnswer ? 's' : 'r'} fa-comment-dots`}
onclick={() => {
isBestAnswer = !isBestAnswer;

saveDiscussion(discussion, isBestAnswer, post).finally(() => {
isBestAnswer = isThisBestAnswer(discussion, post);
});
}}
>
{actionLabel(isBestAnswer)}
</Button>
);
});

extend(CommentPost.prototype, 'actionItems', function (items) {
if (!app.forum.attribute('useAlternativeBestAnswerUi')) return;

const post = this.attrs.post;
const discussion = this.attrs.post.discussion();
let isBestAnswer = isThisBestAnswer(discussion, post);
let hasBestAnswer = discussion.bestAnswerPost() !== null;

post.pushAttributes({ isBestAnswer });

if (ineligible(discussion, post) || blockSelectOwnPost(post) || !app.current.matches(DiscussionPage)) return;

items.add(
'bestAnswer',
<Button
className={`Button Button--${!hasBestAnswer || isBestAnswer ? 'primary' : 'link'}`}
onclick={() => {
hasBestAnswer = !hasBestAnswer;
isBestAnswer = !isBestAnswer;

saveDiscussion(discussion, isBestAnswer, post).finally(() => {
hasBestAnswer = !!discussion.hasBestAnswer() && discussion.bestAnswerPost() !== null;
isBestAnswer = isThisBestAnswer(discussion, post);
});
}}
>
{actionLabel(isBestAnswer)}
</Button>
);
});
}
4 changes: 3 additions & 1 deletion js/src/forum/addBestAnswerCountToUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import UserCard from 'flarum/forum/components/UserCard';
import icon from 'flarum/common/helpers/icon';

import type Mithril from 'mithril';
import type User from 'flarum/common/models/User';

export default function addBestAnswerCountToUsers() {
extend(UserCard.prototype, 'infoItems', function (items: ItemList<Mithril.Children>) {
const user = this.attrs.user;
// @ts-expect-error
const user = this.attrs.user as User;

items.add(
'best-answer-count',
Expand Down
15 changes: 10 additions & 5 deletions js/src/forum/addBestAnswerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default () => {
const post = this.attrs.post;
const discussion = post.discussion();

if (discussion?.hasBestAnswer() && discussion.bestAnswerPost() && discussion.bestAnswerPost().id() === post.id() && !post.isHidden()) {
if (discussion?.hasBestAnswer() && discussion.bestAnswerPost() && discussion.bestAnswerPost()?.id() === post.id() && !post.isHidden()) {
items.add('isBestAnswer', <SelectBestAnswerItem post={post} discussion={discussion} />, -100);
}
});
Expand Down Expand Up @@ -41,17 +41,22 @@ export default () => {
extend(DiscussionPage.prototype, 'sidebarItems', function (items) {
if (!app.forum.attribute<boolean>('bestAnswerDiscussionSidebarJumpButton')) return;

/** @ts-ignore */
// @ts-ignore
const discussion = this.discussion;

if (!discussion) return;
if (discussion === null) return;

const post = discussion.hasBestAnswer() && discussion.bestAnswerPost();

if (post && !post.isHidden() && post.number() !== 1 && !discussion.bestAnswerPost().isHidden()) {
if (post && !post.isHidden() && post.number() !== 1 && !discussion.bestAnswerPost()?.isHidden()) {
items.add(
'jumpToBestAnswer',
<Button className="Button Button-jumpBestAnswer" icon="fas fa-check" onclick={() => app.current.get('stream').goToNumber(post.number())}>
<Button
className="Button Button-jumpBestAnswer"
icon="fas fa-check"
onclick={() => app.current.get('stream').goToNumber(post.number())}
aria-label={app.translator.trans('fof-best-answer.forum.discussion.jump_to_best_answer_button')}
>
{app.translator.trans('fof-best-answer.forum.discussion.jump_to_best_answer_button')}
</Button>,
90
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type Discussion from 'flarum/common/models/Discussion';
import app from 'flarum/forum/app';
import Notification from 'flarum/forum/components/Notification';

Expand All @@ -8,7 +9,7 @@ export default class AwardedBestAnswerNotification extends Notification {

href() {
const notification = this.attrs.notification;
const discussion = notification.subject();
const discussion = notification.subject() as Discussion;

return app.route.discussion(discussion);
}
Expand Down
Loading
Loading