1 import { Component } from "inferno";
2 import { RouteComponentProps } from "inferno-router/dist/Route";
4 CreatePost as CreatePostI,
8 ListCommunitiesResponse,
9 } from "lemmy-js-client";
10 import { i18n } from "../../i18next";
11 import { InitialFetchRequest, PostFormParams } from "../../interfaces";
12 import { FirstLoadService } from "../../services/FirstLoadService";
17 } from "../../services/HttpService";
29 import { HtmlTags } from "../common/html-tags";
30 import { Spinner } from "../common/icon";
31 import { PostForm } from "./post-form";
33 export interface CreatePostProps {
37 type CreatePostData = RouteDataResponse<{
38 communityResponse: GetCommunityResponse;
39 initialCommunitiesRes: ListCommunitiesResponse;
42 function getCreatePostQueryParams() {
43 return getQueryParams<CreatePostProps>({
44 communityId: getIdFromString,
48 function fetchCommunitiesForOptions(client: WrappedLemmyHttp) {
49 return client.listCommunities({ limit: 30, sort: "TopMonth", type_: "All" });
52 interface CreatePostState {
53 siteRes: GetSiteResponse;
55 selectedCommunityChoice?: Choice;
56 initialCommunitiesRes: RequestState<ListCommunitiesResponse>;
57 isIsomorphic: boolean;
60 export class CreatePost extends Component<
61 RouteComponentProps<Record<string, never>>,
64 private isoData = setIsoData<CreatePostData>(this.context);
65 state: CreatePostState = {
66 siteRes: this.isoData.site_res,
68 initialCommunitiesRes: { state: "empty" },
72 constructor(props: RouteComponentProps<Record<string, never>>, context: any) {
73 super(props, context);
75 this.handlePostCreate = this.handlePostCreate.bind(this);
76 this.handleSelectedCommunityChange =
77 this.handleSelectedCommunityChange.bind(this);
79 // Only fetch the data if coming from another route
80 if (FirstLoadService.isFirstLoad) {
81 const { communityResponse: communityRes, initialCommunitiesRes } =
82 this.isoData.routeData;
87 initialCommunitiesRes,
91 if (communityRes?.state === "success") {
92 const communityChoice: Choice = {
93 label: communityRes.data.community_view.community.title,
94 value: communityRes.data.community_view.community.id.toString(),
99 selectedCommunityChoice: communityChoice,
105 async fetchCommunity() {
106 const { communityId } = getCreatePostQueryParams();
107 const auth = myAuth();
110 const res = await HttpService.client.getCommunity({
114 if (res.state === "success") {
116 selectedCommunityChoice: {
117 label: res.data.community_view.community.name,
118 value: res.data.community_view.community.id.toString(),
126 async componentDidMount() {
128 if (!this.state.isIsomorphic) {
129 const { communityId } = getCreatePostQueryParams();
131 const initialCommunitiesRes = await fetchCommunitiesForOptions(
136 initialCommunitiesRes,
140 communityId?.toString() !== this.state.selectedCommunityChoice?.value
142 await this.fetchCommunity();
143 } else if (!communityId) {
145 selectedCommunityChoice: undefined,
152 get documentTitle(): string {
153 return `${i18n.t("create_post")} - ${
154 this.state.siteRes.site_view.site.name
159 const { selectedCommunityChoice } = this.state;
161 const locationState = this.props.history.location.state as
166 <div className="create-post container-lg">
168 title={this.documentTitle}
169 path={this.context.router.route.match.url}
171 {this.state.loading ? (
176 <div className="row">
179 className="col-12 col-lg-6 offset-lg-3 mb-4"
181 <h5>{i18n.t("create_post")}</h5>
183 onCreate={this.handlePostCreate}
184 params={locationState}
185 enableDownvotes={enableDownvotes(this.state.siteRes)}
186 enableNsfw={enableNsfw(this.state.siteRes)}
187 allLanguages={this.state.siteRes.all_languages}
188 siteLanguages={this.state.siteRes.discussion_languages}
189 selectedCommunityChoice={selectedCommunityChoice}
190 onSelectCommunity={this.handleSelectedCommunityChange}
192 this.state.initialCommunitiesRes.state === "success"
193 ? this.state.initialCommunitiesRes.data.communities
204 async updateUrl({ communityId }: Partial<CreatePostProps>) {
205 const { communityId: urlCommunityId } = getCreatePostQueryParams();
207 const locationState = this.props.history.location.state as
211 const url = new URL(location.href);
213 const newId = (communityId ?? urlCommunityId)?.toString();
215 if (newId !== undefined) {
216 url.searchParams.set("communityId", newId);
218 url.searchParams.delete("communityId");
221 history.replaceState(locationState, "", url);
223 await this.fetchCommunity();
226 handleSelectedCommunityChange(choice: Choice) {
228 communityId: getIdFromString(choice?.value),
232 async handlePostCreate(form: CreatePostI) {
233 const res = await HttpService.client.createPost(form);
235 if (res.state === "success") {
236 const postId = res.data.post_view.post.id;
237 this.props.history.replace(`/post/${postId}`);
245 static async fetchInitialData({
247 query: { communityId },
249 }: InitialFetchRequest<
250 QueryParams<CreatePostProps>
251 >): Promise<CreatePostData> {
252 const data: CreatePostData = {
253 initialCommunitiesRes: await fetchCommunitiesForOptions(client),
254 communityResponse: { state: "empty" },
258 const form: GetCommunity = {
260 id: getIdFromString(communityId),
263 data.communityResponse = await client.getCommunity(form);