X-Git-Url: http://these/git/?a=blobdiff_plain;f=src%2Fshared%2Fcomponents%2Fhome%2Fadmin-settings.tsx;h=4924508fbe9f23105bd18894da539700d5fd308b;hb=da4fd7e39e288dd9885466452498a0366aec5b9d;hp=d266db58d1f0474b84b39d4f8f2158ecd9e5afa6;hpb=2ca53fae5bac42fcd39e2cfb26c45ed93d37b288;p=lemmy-ui.git diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index d266db5..4924508 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -1,31 +1,28 @@ -import autosize from "autosize"; +import { + fetchThemeList, + myAuthRequired, + setIsoData, + showLocal, +} from "@utils/app"; +import { capitalizeFirstLetter } from "@utils/helpers"; +import { RouteDataResponse } from "@utils/types"; +import classNames from "classnames"; import { Component, linkEvent } from "inferno"; import { BannedPersonsResponse, - GetBannedPersons, + CreateCustomEmoji, + DeleteCustomEmoji, + EditCustomEmoji, + EditSite, GetFederatedInstancesResponse, GetSiteResponse, PersonView, - SiteResponse, - UserOperation, - wsJsonToRes, - wsUserOp, } from "lemmy-js-client"; -import { Subscription } from "rxjs"; -import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; -import { WebSocketService } from "../../services"; -import { - capitalizeFirstLetter, - isBrowser, - myAuth, - randomStr, - setIsoData, - showLocal, - toast, - wsClient, - wsSubscribe, -} from "../../utils"; +import { removeFromEmojiDataModel, updateEmojiDataModel } from "../../markdown"; +import { FirstLoadService, I18NextService } from "../../services"; +import { HttpService, RequestState } from "../../services/HttpService"; +import { toast } from "../../toast"; import { HtmlTags } from "../common/html-tags"; import { Spinner } from "../common/icon"; import Tabs from "../common/tabs"; @@ -35,164 +32,241 @@ import RateLimitForm from "./rate-limit-form"; import { SiteForm } from "./site-form"; import { TaglineForm } from "./tagline-form"; +type AdminSettingsData = RouteDataResponse<{ + bannedRes: BannedPersonsResponse; + instancesRes: GetFederatedInstancesResponse; +}>; + interface AdminSettingsState { siteRes: GetSiteResponse; - instancesRes?: GetFederatedInstancesResponse; banned: PersonView[]; + currentTab: string; + instancesRes: RequestState; + bannedRes: RequestState; + leaveAdminTeamRes: RequestState; loading: boolean; - leaveAdminTeamLoading: boolean; + themeList: string[]; + isIsomorphic: boolean; } export class AdminSettings extends Component { - private siteConfigTextAreaId = `site-config-${randomStr()}`; - private isoData = setIsoData(this.context); - private subscription?: Subscription; + private isoData = setIsoData(this.context); state: AdminSettingsState = { siteRes: this.isoData.site_res, banned: [], - loading: true, - leaveAdminTeamLoading: false, + currentTab: "site", + bannedRes: { state: "empty" }, + instancesRes: { state: "empty" }, + leaveAdminTeamRes: { state: "empty" }, + loading: false, + themeList: [], + isIsomorphic: false, }; constructor(props: any, context: any) { super(props, context); - this.parseMessage = this.parseMessage.bind(this); - this.subscription = wsSubscribe(this.parseMessage); + this.handleEditSite = this.handleEditSite.bind(this); + this.handleEditEmoji = this.handleEditEmoji.bind(this); + this.handleDeleteEmoji = this.handleDeleteEmoji.bind(this); + this.handleCreateEmoji = this.handleCreateEmoji.bind(this); // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (FirstLoadService.isFirstLoad) { + const { bannedRes, instancesRes } = this.isoData.routeData; + this.state = { ...this.state, - banned: (this.isoData.routeData[0] as BannedPersonsResponse).banned, - instancesRes: this.isoData - .routeData[1] as GetFederatedInstancesResponse, - loading: false, + bannedRes, + instancesRes, + isIsomorphic: true, }; - } else { - let cAuth = myAuth(); - if (cAuth) { - WebSocketService.Instance.send( - wsClient.getBannedPersons({ - auth: cAuth, - }) - ); - WebSocketService.Instance.send( - wsClient.getFederatedInstances({ auth: cAuth }) - ); - } - } - } - - static fetchInitialData(req: InitialFetchRequest): Promise[] { - let promises: Promise[] = []; - - let auth = req.auth; - if (auth) { - let bannedPersonsForm: GetBannedPersons = { auth }; - promises.push(req.client.getBannedPersons(bannedPersonsForm)); - promises.push(req.client.getFederatedInstances({ auth })); } - - return promises; } - componentDidMount() { - if (isBrowser()) { - var textarea: any = document.getElementById(this.siteConfigTextAreaId); - autosize(textarea); - } + static async fetchInitialData({ + auth, + client, + }: InitialFetchRequest): Promise { + return { + bannedRes: await client.getBannedPersons({ + auth: auth as string, + }), + instancesRes: await client.getFederatedInstances({ + auth: auth as string, + }), + }; } - componentWillUnmount() { - if (isBrowser()) { - this.subscription?.unsubscribe(); + async componentDidMount() { + if (!this.state.isIsomorphic) { + await this.fetchData(); } } get documentTitle(): string { - return `${i18n.t("admin_settings")} - ${ + return `${I18NextService.i18n.t("admin_settings")} - ${ this.state.siteRes.site_view.site.name }`; } render() { + const federationData = + this.state.instancesRes.state === "success" + ? this.state.instancesRes.data.federated_instances + : undefined; + return ( -
+
- {this.state.loading ? ( -
- -
- ) : ( - ( + ( +
+

+ {I18NextService.i18n.t("site_config")} +

-
- {this.admins()} - {this.bannedUsers()} -
+
{this.admins()}
- ), - }, - { - key: "rate_limiting", - label: "Rate Limiting", - getNode: () => ( +
+ ), + }, + { + key: "banned_users", + label: I18NextService.i18n.t("banned_users"), + getNode: isSelected => ( +
+ {this.bannedUsers()} +
+ ), + }, + { + key: "rate_limiting", + label: "Rate Limiting", + getNode: isSelected => ( +
- ), - }, - { - key: "taglines", - label: i18n.t("taglines"), - getNode: () => ( +
+ ), + }, + { + key: "taglines", + label: I18NextService.i18n.t("taglines"), + getNode: isSelected => ( +
- +
- ), - }, - { - key: "emojis", - label: i18n.t("emojis"), - getNode: () => ( +
+ ), + }, + { + key: "emojis", + label: I18NextService.i18n.t("emojis"), + getNode: isSelected => ( +
- +
- ), - }, - ]} - /> - )} +
+ ), + }, + ]} + />
); } + async fetchData() { + this.setState({ + bannedRes: { state: "loading" }, + instancesRes: { state: "loading" }, + themeList: [], + }); + + const auth = myAuthRequired(); + + const [bannedRes, instancesRes, themeList] = await Promise.all([ + HttpService.client.getBannedPersons({ auth }), + HttpService.client.getFederatedInstances({ auth }), + fetchThemeList(), + ]); + + this.setState({ + bannedRes, + instancesRes, + themeList, + }); + } + admins() { return ( <> -
{capitalizeFirstLetter(i18n.t("admins"))}
+

+ {capitalizeFirstLetter(I18NextService.i18n.t("admins"))} +

    {this.state.siteRes.admins.map(admin => (
  • @@ -211,62 +285,97 @@ export class AdminSettings extends Component { onClick={linkEvent(this, this.handleLeaveAdminTeam)} className="btn btn-danger mb-2" > - {this.state.leaveAdminTeamLoading ? ( + {this.state.leaveAdminTeamRes.state === "loading" ? ( ) : ( - i18n.t("leave_admin_team") + I18NextService.i18n.t("leave_admin_team") )} ); } bannedUsers() { - return ( - <> -
    {i18n.t("banned_users")}
    -
      - {this.state.banned.map(banned => ( -
    • - -
    • - ))} -
    - - ); + switch (this.state.bannedRes.state) { + case "loading": + return ( +
    + +
    + ); + case "success": { + const bans = this.state.bannedRes.data.banned; + return ( + <> +

    {I18NextService.i18n.t("banned_users")}

    +
      + {bans.map(banned => ( +
    • + +
    • + ))} +
    + + ); + } + } + } + + async handleEditSite(form: EditSite) { + this.setState({ loading: true }); + + const editRes = await HttpService.client.editSite(form); + + if (editRes.state === "success") { + this.setState(s => { + s.siteRes.site_view = editRes.data.site_view; + // TODO: Where to get taglines from? + s.siteRes.taglines = editRes.data.taglines; + return s; + }); + toast(I18NextService.i18n.t("site_saved")); + } + + this.setState({ loading: false }); + + return editRes; + } + + handleSwitchTab(i: { ctx: AdminSettings; tab: string }) { + i.ctx.setState({ currentTab: i.tab }); + } + + async handleLeaveAdminTeam(i: AdminSettings) { + i.setState({ leaveAdminTeamRes: { state: "loading" } }); + this.setState({ + leaveAdminTeamRes: await HttpService.client.leaveAdmin({ + auth: myAuthRequired(), + }), + }); + + if (this.state.leaveAdminTeamRes.state === "success") { + toast(I18NextService.i18n.t("left_admin_team")); + this.context.router.history.replace("/"); + } + } + + async handleEditEmoji(form: EditCustomEmoji) { + const res = await HttpService.client.editCustomEmoji(form); + if (res.state === "success") { + updateEmojiDataModel(res.data.custom_emoji); + } } - handleLeaveAdminTeam(i: AdminSettings) { - let auth = myAuth(); - if (auth) { - i.setState({ leaveAdminTeamLoading: true }); - WebSocketService.Instance.send(wsClient.leaveAdmin({ auth })); + async handleDeleteEmoji(form: DeleteCustomEmoji) { + const res = await HttpService.client.deleteCustomEmoji(form); + if (res.state === "success") { + removeFromEmojiDataModel(res.data.id); } } - parseMessage(msg: any) { - let op = wsUserOp(msg); - console.log(msg); - if (msg.error) { - toast(i18n.t(msg.error), "danger"); - this.context.router.history.push("/"); - this.setState({ loading: false }); - return; - } else if (op == UserOperation.EditSite) { - let data = wsJsonToRes(msg); - this.setState(s => ((s.siteRes.site_view = data.site_view), s)); - toast(i18n.t("site_saved")); - } else if (op == UserOperation.GetBannedPersons) { - let data = wsJsonToRes(msg); - this.setState({ banned: data.banned, loading: false }); - } else if (op == UserOperation.LeaveAdmin) { - let data = wsJsonToRes(msg); - this.setState(s => ((s.siteRes.site_view = data.site_view), s)); - this.setState({ leaveAdminTeamLoading: false }); - toast(i18n.t("left_admin_team")); - this.context.router.history.push("/"); - } else if (op == UserOperation.GetFederatedInstances) { - let data = wsJsonToRes(msg); - this.setState({ instancesRes: data }); + async handleCreateEmoji(form: CreateCustomEmoji) { + const res = await HttpService.client.createCustomEmoji(form); + if (res.state === "success") { + updateEmojiDataModel(res.data.custom_emoji); } } }