import classNames from "classnames"; import { Component, linkEvent } from "inferno"; import { BannedPersonsResponse, CreateCustomEmoji, DeleteCustomEmoji, EditCustomEmoji, EditSite, GetFederatedInstancesResponse, GetSiteResponse, PersonView, } from "lemmy-js-client"; import { i18n } from "../../i18next"; import { InitialFetchRequest } from "../../interfaces"; import { FirstLoadService } from "../../services/FirstLoadService"; import { HttpService, RequestState } from "../../services/HttpService"; import { RouteDataResponse, capitalizeFirstLetter, fetchThemeList, myAuthRequired, removeFromEmojiDataModel, setIsoData, showLocal, toast, updateEmojiDataModel, } from "../../utils"; import { HtmlTags } from "../common/html-tags"; import { Spinner } from "../common/icon"; import Tabs from "../common/tabs"; import { PersonListing } from "../person/person-listing"; import { EmojiForm } from "./emojis-form"; 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; banned: PersonView[]; currentTab: string; instancesRes: RequestState; bannedRes: RequestState; leaveAdminTeamRes: RequestState; emojiLoading: boolean; loading: boolean; themeList: string[]; isIsomorphic: boolean; } export class AdminSettings extends Component { private isoData = setIsoData(this.context); state: AdminSettingsState = { siteRes: this.isoData.site_res, banned: [], currentTab: "site", bannedRes: { state: "empty" }, instancesRes: { state: "empty" }, leaveAdminTeamRes: { state: "empty" }, emojiLoading: false, loading: false, themeList: [], isIsomorphic: false, }; constructor(props: any, context: any) { super(props, context); 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 (FirstLoadService.isFirstLoad) { const { bannedRes, instancesRes } = this.isoData.routeData; this.state = { ...this.state, bannedRes, instancesRes, isIsomorphic: true, }; } } static async fetchInitialData({ auth, client, }: InitialFetchRequest): Promise { return { bannedRes: await client.getBannedPersons({ auth: auth as string, }), instancesRes: await client.getFederatedInstances({ auth: auth as string, }), }; } async componentDidMount() { if (!this.state.isIsomorphic) { await this.fetchData(); } } get documentTitle(): string { return `${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.admins()} {this.bannedUsers()}
), }, { key: "rate_limiting", label: "Rate Limiting", getNode: isSelected => (
), }, { key: "taglines", label: i18n.t("taglines"), getNode: isSelected => (
), }, { key: "emojis", label: 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"))}
    {this.state.siteRes.admins.map(admin => (
  • ))}
{this.leaveAdmin()} ); } leaveAdmin() { return ( ); } bannedUsers() { switch (this.state.bannedRes.state) { case "loading": return (
); case "success": { const bans = this.state.bannedRes.data.banned; return ( <>
{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(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(i18n.t("left_admin_team")); this.context.router.history.replace("/"); } } 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 }); } }