1 import { enableDownvotes, enableNsfw, myAuth, setIsoData } from "@utils/app";
2 import { getIdFromString, getQueryParams } from "@utils/helpers";
3 import type { QueryParams } from "@utils/types";
4 import { Choice, RouteDataResponse } from "@utils/types";
5 import { Component } from "inferno";
6 import { RouteComponentProps } from "inferno-router/dist/Route";
8 CreatePost as CreatePostI,
12 ListCommunitiesResponse,
13 } from "lemmy-js-client";
14 import { InitialFetchRequest, PostFormParams } from "../../interfaces";
15 import { FirstLoadService, I18NextService } from "../../services";
20 } from "../../services/HttpService";
21 import { HtmlTags } from "../common/html-tags";
22 import { Spinner } from "../common/icon";
23 import { PostForm } from "./post-form";
25 export interface CreatePostProps {
29 type CreatePostData = RouteDataResponse<{
30 communityResponse: GetCommunityResponse;
31 initialCommunitiesRes: ListCommunitiesResponse;
34 function getCreatePostQueryParams() {
35 return getQueryParams<CreatePostProps>({
36 communityId: getIdFromString,
40 function fetchCommunitiesForOptions(client: WrappedLemmyHttp) {
41 return client.listCommunities({ limit: 30, sort: "TopMonth", type_: "All" });
44 interface CreatePostState {
45 siteRes: GetSiteResponse;
47 selectedCommunityChoice?: Choice;
48 initialCommunitiesRes: RequestState<ListCommunitiesResponse>;
49 isIsomorphic: boolean;
52 export class CreatePost extends Component<
53 RouteComponentProps<Record<string, never>>,
56 private isoData = setIsoData<CreatePostData>(this.context);
57 state: CreatePostState = {
58 siteRes: this.isoData.site_res,
60 initialCommunitiesRes: { state: "empty" },
64 constructor(props: RouteComponentProps<Record<string, never>>, context: any) {
65 super(props, context);
67 this.handlePostCreate = this.handlePostCreate.bind(this);
68 this.handleSelectedCommunityChange =
69 this.handleSelectedCommunityChange.bind(this);
71 // Only fetch the data if coming from another route
72 if (FirstLoadService.isFirstLoad) {
73 const { communityResponse: communityRes, initialCommunitiesRes } =
74 this.isoData.routeData;
79 initialCommunitiesRes,
83 if (communityRes?.state === "success") {
84 const communityChoice: Choice = {
85 label: communityRes.data.community_view.community.title,
86 value: communityRes.data.community_view.community.id.toString(),
91 selectedCommunityChoice: communityChoice,
97 async fetchCommunity() {
98 const { communityId } = getCreatePostQueryParams();
99 const auth = myAuth();
102 const res = await HttpService.client.getCommunity({
106 if (res.state === "success") {
108 selectedCommunityChoice: {
109 label: res.data.community_view.community.title,
110 value: res.data.community_view.community.id.toString(),
118 async componentDidMount() {
120 if (!this.state.isIsomorphic) {
121 const { communityId } = getCreatePostQueryParams();
123 const initialCommunitiesRes = await fetchCommunitiesForOptions(
128 initialCommunitiesRes,
132 communityId?.toString() !== this.state.selectedCommunityChoice?.value
134 await this.fetchCommunity();
135 } else if (!communityId) {
137 selectedCommunityChoice: undefined,
144 get documentTitle(): string {
145 return `${I18NextService.i18n.t("create_post")} - ${
146 this.state.siteRes.site_view.site.name
151 const { selectedCommunityChoice } = this.state;
153 const locationState = this.props.history.location.state as
158 <div className="create-post container-lg">
160 title={this.documentTitle}
161 path={this.context.router.route.match.url}
163 {this.state.loading ? (
168 <div className="row">
171 className="col-12 col-lg-6 offset-lg-3 mb-4"
173 <h1 className="h4">{I18NextService.i18n.t("create_post")}</h1>
175 onCreate={this.handlePostCreate}
176 params={locationState}
177 enableDownvotes={enableDownvotes(this.state.siteRes)}
178 enableNsfw={enableNsfw(this.state.siteRes)}
179 allLanguages={this.state.siteRes.all_languages}
180 siteLanguages={this.state.siteRes.discussion_languages}
181 selectedCommunityChoice={selectedCommunityChoice}
182 onSelectCommunity={this.handleSelectedCommunityChange}
184 this.state.initialCommunitiesRes.state === "success"
185 ? this.state.initialCommunitiesRes.data.communities
196 async updateUrl({ communityId }: Partial<CreatePostProps>) {
197 const { communityId: urlCommunityId } = getCreatePostQueryParams();
199 const locationState = this.props.history.location.state as
203 const url = new URL(location.href);
205 const newId = (communityId ?? urlCommunityId)?.toString();
207 if (newId !== undefined) {
208 url.searchParams.set("communityId", newId);
210 url.searchParams.delete("communityId");
213 history.replaceState(locationState, "", url);
215 await this.fetchCommunity();
218 handleSelectedCommunityChange(choice: Choice) {
220 communityId: getIdFromString(choice?.value),
224 async handlePostCreate(form: CreatePostI) {
225 const res = await HttpService.client.createPost(form);
227 if (res.state === "success") {
228 const postId = res.data.post_view.post.id;
229 this.props.history.replace(`/post/${postId}`);
237 static async fetchInitialData({
239 query: { communityId },
241 }: InitialFetchRequest<
242 QueryParams<CreatePostProps>
243 >): Promise<CreatePostData> {
244 const data: CreatePostData = {
245 initialCommunitiesRes: await fetchCommunitiesForOptions(client),
246 communityResponse: { state: "empty" },
250 const form: GetCommunity = {
252 id: getIdFromString(communityId),
255 data.communityResponse = await client.getCommunity(form);