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 mb-4">
174 {I18NextService.i18n.t("create_post")}
177 onCreate={this.handlePostCreate}
178 params={locationState}
179 enableDownvotes={enableDownvotes(this.state.siteRes)}
180 enableNsfw={enableNsfw(this.state.siteRes)}
181 allLanguages={this.state.siteRes.all_languages}
182 siteLanguages={this.state.siteRes.discussion_languages}
183 selectedCommunityChoice={selectedCommunityChoice}
184 onSelectCommunity={this.handleSelectedCommunityChange}
186 this.state.initialCommunitiesRes.state === "success"
187 ? this.state.initialCommunitiesRes.data.communities
198 async updateUrl({ communityId }: Partial<CreatePostProps>) {
199 const { communityId: urlCommunityId } = getCreatePostQueryParams();
201 const locationState = this.props.history.location.state as
205 const url = new URL(location.href);
207 const newId = (communityId ?? urlCommunityId)?.toString();
209 if (newId !== undefined) {
210 url.searchParams.set("communityId", newId);
212 url.searchParams.delete("communityId");
215 history.replaceState(locationState, "", url);
217 await this.fetchCommunity();
220 handleSelectedCommunityChange(choice: Choice) {
222 communityId: getIdFromString(choice?.value),
226 async handlePostCreate(form: CreatePostI) {
227 const res = await HttpService.client.createPost(form);
229 if (res.state === "success") {
230 const postId = res.data.post_view.post.id;
231 this.props.history.replace(`/post/${postId}`);
239 static async fetchInitialData({
241 query: { communityId },
243 }: InitialFetchRequest<
244 QueryParams<CreatePostProps>
245 >): Promise<CreatePostData> {
246 const data: CreatePostData = {
247 initialCommunitiesRes: await fetchCommunitiesForOptions(client),
248 communityResponse: { state: "empty" },
252 const form: GetCommunity = {
254 id: getIdFromString(communityId),
257 data.communityResponse = await client.getCommunity(form);