Optimize Tagline Form page (#972)

* Move taglines to its own tab. Optimize for editing.

* Small fix

* null -> undefined
This commit is contained in:
Anon 2023-03-30 15:36:57 -05:00 committed by GitHub
parent 4499579380
commit 16cb506147
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 211 additions and 51 deletions

View file

@ -30,6 +30,7 @@ import { Spinner } from "../common/icon";
import { PersonListing } from "../person/person-listing";
import { EmojiForm } from "./emojis-form";
import { SiteForm } from "./site-form";
import { TaglineForm } from "./tagline-form";
interface AdminSettingsState {
siteRes: GetSiteResponse;
@ -134,6 +135,19 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
{i18n.t("site")}
</button>
</li>
<li className="nav-item">
<button
className={`nav-link btn ${
this.state.currentTab == "taglines" && "active"
}`}
onClick={linkEvent(
{ ctx: this, tab: "taglines" },
this.handleSwitchTab
)}
>
{i18n.t("taglines")}
</button>
</li>
<li className="nav-item">
<button
className={`nav-link btn ${
@ -162,6 +176,11 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
</div>
</div>
)}
{this.state.currentTab == "taglines" && (
<div className="row">
<TaglineForm siteRes={this.state.siteRes}></TaglineForm>
</div>
)}
{this.state.currentTab == "emojis" && (
<div className="row">
<EmojiForm></EmojiForm>

View file

@ -15,7 +15,7 @@ import {
myAuth,
wsClient,
} from "../../utils";
import { Icon, Spinner } from "../common/icon";
import { Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select";
import { ListingTypeSelect } from "../common/listing-type-select";
@ -106,7 +106,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
captcha_difficulty: ls.captcha_difficulty,
allowed_instances: this.props.siteRes.federated_instances?.allowed,
blocked_instances: this.props.siteRes.federated_instances?.blocked,
taglines: this.props.siteRes.taglines?.map(x => x.content),
auth: "TODO",
},
};
@ -908,54 +907,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
/>
</div>
</div>
<div className="form-group row">
<h5 className="col-12">{i18n.t("taglines")}</h5>
<div className="table-responsive col-12">
<table id="taglines_table" className="table table-sm table-hover">
<thead className="pointer"></thead>
<tbody>
{this.state.siteForm.taglines?.map((cv, index) => (
<tr key={index}>
<td>
<MarkdownTextArea
initialContent={cv}
onContentChange={s =>
this.handleTaglineChange(this, index, s)
}
hideNavigationWarnings
allLanguages={this.props.siteRes.all_languages}
siteLanguages={
this.props.siteRes.discussion_languages
}
/>
</td>
<td className="text-right">
<button
className="btn btn-link btn-animate text-muted"
onClick={e =>
this.handleDeleteTaglineClick(this, index, e)
}
data-tippy-content={i18n.t("delete")}
aria-label={i18n.t("delete")}
>
<Icon
icon="trash"
classes={`icon-inline text-danger`}
/>
</button>
</td>
</tr>
))}
</tbody>
</table>
<button
className="btn btn-sm btn-secondary mr-2"
onClick={e => this.handleAddTaglineClick(this, e)}
>
{i18n.t("add_tagline")}
</button>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<button
@ -1027,7 +979,6 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
allowed_instances: sForm.allowed_instances,
blocked_instances: sForm.blocked_instances,
discussion_languages: sForm.discussion_languages,
taglines: sForm.taglines,
auth,
};
WebSocketService.Instance.send(wsClient.createSite(form));

View file

@ -0,0 +1,190 @@
import { Component, InfernoMouseEvent, linkEvent } from "inferno";
import { EditSite, GetSiteResponse } from "lemmy-js-client";
import { i18n } from "../../i18next";
import { WebSocketService } from "../../services";
import { capitalizeFirstLetter, myAuth, wsClient } from "../../utils";
import { HtmlTags } from "../common/html-tags";
import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
interface TaglineFormProps {
siteRes: GetSiteResponse;
}
interface TaglineFormState {
siteRes: GetSiteResponse;
siteForm: EditSite;
loading: boolean;
editingRow?: number;
}
export class TaglineForm extends Component<TaglineFormProps, TaglineFormState> {
state: TaglineFormState = {
loading: false,
siteRes: this.props.siteRes,
editingRow: undefined,
siteForm: {
taglines: this.props.siteRes.taglines?.map(x => x.content),
auth: "TODO",
},
};
constructor(props: any, context: any) {
super(props, context);
}
get documentTitle(): string {
return i18n.t("taglines");
}
componentWillReceiveProps() {
this.setState({ loading: false });
}
render() {
return (
<div className="col-12">
<HtmlTags
title={this.documentTitle}
path={this.context.router.route.match.url}
/>
<h5 className="col-12">{i18n.t("taglines")}</h5>
<div className="table-responsive col-12">
<table id="taglines_table" className="table table-sm table-hover">
<thead className="pointer">
<th></th>
<th style="width:121px"></th>
</thead>
<tbody>
{this.state.siteForm.taglines?.map((cv, index) => (
<tr key={index}>
<td>
{this.state.editingRow == index && (
<MarkdownTextArea
initialContent={cv}
onContentChange={s =>
this.handleTaglineChange(this, index, s)
}
hideNavigationWarnings
allLanguages={this.state.siteRes.all_languages}
siteLanguages={this.state.siteRes.discussion_languages}
/>
)}
{this.state.editingRow != index && <div>{cv}</div>}
</td>
<td className="text-right">
<button
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
{ form: this, index: index },
this.handleEditTaglineClick
)}
data-tippy-content={i18n.t("edit")}
aria-label={i18n.t("edit")}
>
<Icon icon="edit" classes={`icon-inline`} />
</button>
<button
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(
{ form: this, index: index },
this.handleDeleteTaglineClick
)}
data-tippy-content={i18n.t("delete")}
aria-label={i18n.t("delete")}
>
<Icon icon="trash" classes={`icon-inline text-danger`} />
</button>
</td>
</tr>
))}
</tbody>
</table>
<div className="form-group row">
<div className="col-12">
<button
className="btn btn-sm btn-secondary mr-2"
onClick={linkEvent(this, this.handleAddTaglineClick)}
>
{i18n.t("add_tagline")}
</button>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<button
onClick={linkEvent(this, this.handleSaveClick)}
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t("save"))
)}
</button>
</div>
</div>
</div>
</div>
);
}
handleTaglineChange(i: TaglineForm, index: number, val: string) {
let taglines = i.state.siteForm.taglines;
if (taglines) {
taglines[index] = val;
i.setState(i.state);
}
}
handleDeleteTaglineClick(
props: { form: TaglineForm; index: number },
event: any
) {
event.preventDefault();
let taglines = props.form.state.siteForm.taglines;
if (taglines) {
taglines.splice(props.index, 1);
props.form.state.siteForm.taglines = undefined;
props.form.setState(props.form.state);
props.form.state.siteForm.taglines = taglines;
props.form.setState({ ...props.form.state, editingRow: undefined });
}
}
handleEditTaglineClick(
props: { form: TaglineForm; index: number },
event: any
) {
event.preventDefault();
if (this.state.editingRow == props.index) {
props.form.setState({ editingRow: undefined });
} else {
props.form.setState({ editingRow: props.index });
}
}
handleSaveClick(i: TaglineForm) {
i.setState({ loading: true });
let auth = myAuth() ?? "TODO";
i.setState(s => ((s.siteForm.auth = auth), s));
WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
i.setState({ ...i.state, editingRow: undefined });
}
handleAddTaglineClick(
i: TaglineForm,
event: InfernoMouseEvent<HTMLButtonElement>
) {
event.preventDefault();
if (!i.state.siteForm.taglines) {
i.state.siteForm.taglines = [];
}
i.state.siteForm.taglines.push("");
i.setState({
...i.state,
editingRow: i.state.siteForm.taglines.length - 1,
});
}
}