diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6df17d57..76916e60 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @dessalines @SleeplessOne1917 +* @dessalines @SleeplessOne1917 @alectrocute diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 2273a138..ae2d4e51 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -21,7 +21,7 @@ body: - label: Is this only a single bug? Do not put multiple bugs in one issue. required: true - label: Is this a server side (not related to the UI) issue? Use the [Lemmy back end](https://github.com/LemmyNet/lemmy) repo. - required: true + required: false - type: textarea id: summary attributes: diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index 2f6f3fc1..3c75050a 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -19,7 +19,7 @@ body: - label: Is this only a feature request? Do not put multiple feature requests in one issue. required: true - label: Is this a server side (not related to the UI) issue? Use the [Lemmy back end](https://github.com/LemmyNet/lemmy) repo. - required: true + required: false - type: textarea id: problem attributes: diff --git a/Dockerfile b/Dockerfile index 3d6d6212..2b36581d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:alpine as builder +FROM node:20.2-alpine as builder RUN apk update && apk add curl yarn python3 build-base gcc wget git --no-cache RUN curl -sf https://gobinaries.com/tj/node-prune | sh diff --git a/dev.dockerfile b/dev.dockerfile index 0e925c0a..3bfc10da 100644 --- a/dev.dockerfile +++ b/dev.dockerfile @@ -1,4 +1,4 @@ -FROM node:alpine as builder +FROM node:20.2-alpine as builder RUN apk update && apk add curl yarn python3 build-base gcc wget git --no-cache WORKDIR /usr/src/app diff --git a/src/shared/components/common/markdown-textarea.tsx b/src/shared/components/common/markdown-textarea.tsx index 9318d3bb..a4459ac0 100644 --- a/src/shared/components/common/markdown-textarea.tsx +++ b/src/shared/components/common/markdown-textarea.tsx @@ -184,53 +184,6 @@ export class MarkdownTextArea extends Component<
- {this.props.buttonTitle && ( - - )} - {this.props.replyType && ( - - )} - {this.state.content && ( - - )} - {/* A flex expander */} -
- - {this.props.showLanguage && ( - - )} {this.getFormatButton("bold", this.handleInsertBold)} {this.getFormatButton("italic", this.handleInsertItalic)} {this.getFormatButton("link", this.handleInsertLink)} @@ -283,6 +236,57 @@ export class MarkdownTextArea extends Component<
+ +
+ {this.props.showLanguage && ( + + )} + + {/* A flex expander */} +
+ + {this.props.buttonTitle && ( + + )} + {this.props.replyType && ( + + )} + {this.state.content && ( + + )} +
); diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 7dc150f3..05fa55e1 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -647,6 +647,12 @@ export class Community extends Component< const blockCommunityRes = await HttpService.client.blockCommunity(form); if (blockCommunityRes.state == "success") { updateCommunityBlock(blockCommunityRes.data); + this.setState(s => { + if (s.communityRes.state == "success") { + s.communityRes.data.community_view.blocked = + blockCommunityRes.data.blocked; + } + }); } } diff --git a/src/shared/components/community/sidebar.tsx b/src/shared/components/community/sidebar.tsx index a5c620f3..57400f48 100644 --- a/src/shared/components/community/sidebar.tsx +++ b/src/shared/components/community/sidebar.tsx @@ -1,4 +1,5 @@ import { Component, InfernoNode, linkEvent } from "inferno"; +import { T } from "inferno-i18next-dess"; import { Link } from "inferno-router"; import { AddModToCommunity, @@ -63,7 +64,6 @@ interface SidebarState { removeCommunityLoading: boolean; leaveModTeamLoading: boolean; followCommunityLoading: boolean; - blockCommunityLoading: boolean; purgeCommunityLoading: boolean; } @@ -77,7 +77,6 @@ export class Sidebar extends Component { removeCommunityLoading: false, leaveModTeamLoading: false, followCommunityLoading: false, - blockCommunityLoading: false, purgeCommunityLoading: false, }; @@ -104,7 +103,6 @@ export class Sidebar extends Component { removeCommunityLoading: false, leaveModTeamLoading: false, followCommunityLoading: false, - blockCommunityLoading: false, purgeCommunityLoading: false, }); } @@ -144,10 +142,15 @@ export class Sidebar extends Component { {myUSerInfo && this.blockCommunity()} {!myUSerInfo && (
- {i18n.t("community_not_logged_in_alert", { - community: name, - instance: hostname(actor_id), - })} + + ### +
)} @@ -370,35 +373,18 @@ export class Sidebar extends Component { } blockCommunity() { - const community_view = this.props.community_view; - const blocked = this.props.community_view.blocked; + const { subscribed, blocked } = this.props.community_view; return (
- {community_view.subscribed == "NotSubscribed" && - (blocked ? ( - - ) : ( - - ))} + {subscribed == "NotSubscribed" && ( + + )}
); } @@ -662,10 +648,11 @@ export class Sidebar extends Component { } handleBlockCommunity(i: Sidebar) { - i.setState({ blockCommunityLoading: true }); + const { community, blocked } = i.props.community_view; + i.props.onBlockCommunity({ - community_id: 0, - block: !i.props.community_view.blocked, + community_id: community.id, + block: !blocked, auth: myAuthRequired(), }); } diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index 9b7256d0..302e96bd 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -39,6 +39,8 @@ interface AdminSettingsState { instancesRes: RequestState; bannedRes: RequestState; leaveAdminTeamRes: RequestState; + emojiLoading: boolean; + loading: boolean; themeList: string[]; isIsomorphic: boolean; } @@ -52,6 +54,8 @@ export class AdminSettings extends Component { bannedRes: { state: "empty" }, instancesRes: { state: "empty" }, leaveAdminTeamRes: { state: "empty" }, + emojiLoading: false, + loading: false, themeList: [], isIsomorphic: false, }; @@ -81,6 +85,7 @@ export class AdminSettings extends Component { bannedRes: { state: "loading" }, instancesRes: { state: "loading" }, themeList: [], + loading: true, }); const auth = myAuthRequired(); @@ -95,6 +100,7 @@ export class AdminSettings extends Component { bannedRes, instancesRes, themeList, + loading: false, }); } @@ -156,6 +162,7 @@ export class AdminSettings extends Component { onSaveSite={this.handleEditSite} siteRes={this.state.siteRes} themeList={this.state.themeList} + loading={this.state.loading} />
@@ -174,6 +181,7 @@ export class AdminSettings extends Component { this.state.siteRes.site_view.local_site_rate_limit } onSaveSite={this.handleEditSite} + loading={this.state.loading} /> ), }, @@ -185,6 +193,7 @@ export class AdminSettings extends Component {
), @@ -198,6 +207,7 @@ export class AdminSettings extends Component { onCreate={this.handleCreateEmoji} onDelete={this.handleDeleteEmoji} onEdit={this.handleEditEmoji} + loading={this.state.emojiLoading} /> ), @@ -266,6 +276,8 @@ export class AdminSettings extends Component { } async handleEditSite(form: EditSite) { + this.setState({ loading: true }); + const editRes = await HttpService.client.editSite(form); if (editRes.state === "success") { @@ -278,6 +290,8 @@ export class AdminSettings extends Component { toast(i18n.t("site_saved")); } + this.setState({ loading: false }); + return editRes; } @@ -300,23 +314,35 @@ export class AdminSettings extends Component { } async handleEditEmoji(form: EditCustomEmoji) { + this.setState({ emojiLoading: true }); + const res = await HttpService.client.editCustomEmoji(form); if (res.state === "success") { updateEmojiDataModel(res.data.custom_emoji); } + + this.setState({ emojiLoading: false }); } async handleDeleteEmoji(form: DeleteCustomEmoji) { + this.setState({ emojiLoading: true }); + const res = await HttpService.client.deleteCustomEmoji(form); if (res.state === "success") { removeFromEmojiDataModel(res.data.id); } + + this.setState({ emojiLoading: false }); } async handleCreateEmoji(form: CreateCustomEmoji) { + this.setState({ emojiLoading: true }); + const res = await HttpService.client.createCustomEmoji(form); if (res.state === "success") { updateEmojiDataModel(res.data.custom_emoji); } + + this.setState({ emojiLoading: false }); } } diff --git a/src/shared/components/home/emojis-form.tsx b/src/shared/components/home/emojis-form.tsx index 171b7c99..f77f5125 100644 --- a/src/shared/components/home/emojis-form.tsx +++ b/src/shared/components/home/emojis-form.tsx @@ -23,12 +23,12 @@ interface EmojiFormProps { onEdit(form: EditCustomEmoji): void; onCreate(form: CreateCustomEmoji): void; onDelete(form: DeleteCustomEmoji): void; + loading: boolean; } interface EmojiFormState { siteRes: GetSiteResponse; customEmojis: CustomEmojiViewForm[]; - loading: boolean; page: number; } @@ -47,7 +47,6 @@ export class EmojiForm extends Component { private isoData = setIsoData(this.context); private itemsPerPage = 15; private emptyState: EmojiFormState = { - loading: false, siteRes: this.isoData.site_res, customEmojis: this.isoData.site_res.custom_emojis.map((x, index) => ({ id: x.custom_emoji.id, @@ -223,7 +222,7 @@ export class EmojiForm extends Component { data-tippy-content={i18n.t("save")} aria-label={i18n.t("save")} disabled={ - this.state.loading || + this.props.loading || !this.canEdit(cv) || !cv.changed } @@ -243,7 +242,7 @@ export class EmojiForm extends Component { )} data-tippy-content={i18n.t("delete")} aria-label={i18n.t("delete")} - disabled={this.state.loading} + disabled={this.props.loading} title={i18n.t("delete")} > { state: RateLimitFormState = { - loading: false, form: this.props.rateLimits, }; constructor(props: RateLimitFormProps, context: any) { @@ -164,9 +162,9 @@ export default class RateLimitsForm extends Component<