mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-21 14:17:11 +00:00
Create post query params (#2515)
* Allow create post page form inputs to be populated from query params * Fix issue with cross post params. --------- Co-authored-by: Dessalines <tyhou13@gmx.com>
This commit is contained in:
parent
06b5925e85
commit
7003b564a3
|
@ -77,8 +77,6 @@ export class ImageUploadForm extends Component<
|
|||
i.setState({ loading: true });
|
||||
|
||||
HttpService.client.uploadImage({ image }).then(res => {
|
||||
console.log("pictrs upload:");
|
||||
console.log(res);
|
||||
if (res.state === "success") {
|
||||
if (res.data.msg === "ok") {
|
||||
i.props.onUpload(res.data.url as string);
|
||||
|
|
|
@ -47,6 +47,7 @@ interface MarkdownTextAreaProps {
|
|||
showLanguage?: boolean;
|
||||
hideNavigationWarnings?: boolean;
|
||||
onContentChange?(val: string): void;
|
||||
onContentBlur?(val: string): void;
|
||||
onReplyCancel?(): void;
|
||||
onSubmit?(content: string, languageId?: number): Promise<boolean>;
|
||||
allLanguages: Language[]; // TODO should probably be nullable
|
||||
|
@ -215,6 +216,7 @@ export class MarkdownTextArea extends Component<
|
|||
)}
|
||||
value={this.state.content}
|
||||
onInput={linkEvent(this, this.handleContentChange)}
|
||||
onBlur={linkEvent(this, this.handleContentBlur)}
|
||||
onPaste={linkEvent(this, this.handlePaste)}
|
||||
onKeyDown={linkEvent(this, this.handleKeyBinds)}
|
||||
required
|
||||
|
@ -457,8 +459,6 @@ export class MarkdownTextArea extends Component<
|
|||
|
||||
async uploadSingleImage(i: MarkdownTextArea, image: File) {
|
||||
const res = await HttpService.client.uploadImage({ image });
|
||||
console.log("pictrs upload:");
|
||||
console.log(res);
|
||||
if (res.state === "success") {
|
||||
if (res.data.msg === "ok") {
|
||||
const imageMarkdown = `![](${res.data.url})`;
|
||||
|
@ -496,6 +496,10 @@ export class MarkdownTextArea extends Component<
|
|||
i.contentChange();
|
||||
}
|
||||
|
||||
handleContentBlur(i: MarkdownTextArea, event: any) {
|
||||
i.props.onContentBlur?.(event.target.value);
|
||||
}
|
||||
|
||||
// Keybind handler
|
||||
// Keybinds inspired by github comment area
|
||||
handleKeyBinds(i: MarkdownTextArea, event: KeyboardEvent) {
|
||||
|
|
|
@ -497,8 +497,6 @@ export class EmojiForm extends Component<EmojiFormProps, EmojiFormState> {
|
|||
}));
|
||||
|
||||
HttpService.client.uploadImage({ image: file }).then(res => {
|
||||
console.log("pictrs upload:");
|
||||
console.log(res);
|
||||
if (res.state === "success") {
|
||||
if (res.data.msg === "ok") {
|
||||
pictrsDeleteToast(file.name, res.data.delete_url as string);
|
||||
|
|
|
@ -930,7 +930,6 @@ export class Home extends Component<HomeRouteProps, HomeState> {
|
|||
}
|
||||
|
||||
handleShowHiddenChange(show?: StringBoolean) {
|
||||
console.log(`Got ${show}`);
|
||||
this.updateUrl({
|
||||
showHidden: show,
|
||||
pageCursor: undefined,
|
||||
|
|
|
@ -5,8 +5,18 @@ import {
|
|||
setIsoData,
|
||||
voteDisplayMode,
|
||||
} from "@utils/app";
|
||||
import { getIdFromString, getQueryParams } from "@utils/helpers";
|
||||
import { Choice, RouteDataResponse } from "@utils/types";
|
||||
import {
|
||||
getIdFromString,
|
||||
getQueryParams,
|
||||
getQueryString,
|
||||
} from "@utils/helpers";
|
||||
import {
|
||||
Choice,
|
||||
CrossPostParams,
|
||||
QueryParams,
|
||||
RouteDataResponse,
|
||||
StringBoolean,
|
||||
} from "@utils/types";
|
||||
import { Component } from "inferno";
|
||||
import { RouteComponentProps } from "inferno-router/dist/Route";
|
||||
import {
|
||||
|
@ -36,6 +46,13 @@ import { isBrowser } from "@utils/browser";
|
|||
|
||||
export interface CreatePostProps {
|
||||
communityId?: number;
|
||||
url?: string;
|
||||
title?: string;
|
||||
body?: string;
|
||||
languageId?: number;
|
||||
nsfw?: StringBoolean;
|
||||
customThumbnailUrl?: string;
|
||||
altText?: string;
|
||||
}
|
||||
|
||||
type CreatePostData = RouteDataResponse<{
|
||||
|
@ -47,6 +64,13 @@ export function getCreatePostQueryParams(source?: string): CreatePostProps {
|
|||
return getQueryParams<CreatePostProps>(
|
||||
{
|
||||
communityId: getIdFromString,
|
||||
url: (url?: string) => url,
|
||||
body: (body?: string) => body,
|
||||
languageId: getIdFromString,
|
||||
nsfw: (nsfw?: StringBoolean) => nsfw,
|
||||
customThumbnailUrl: (customThumbnailUrl?: string) => customThumbnailUrl,
|
||||
title: (title?: string) => title,
|
||||
altText: (altText?: string) => altText,
|
||||
},
|
||||
source,
|
||||
);
|
||||
|
@ -92,8 +116,15 @@ export class CreatePost extends Component<
|
|||
this.handlePostCreate = this.handlePostCreate.bind(this);
|
||||
this.handleSelectedCommunityChange =
|
||||
this.handleSelectedCommunityChange.bind(this);
|
||||
this.handleTitleBlur = this.handleTitleBlur.bind(this);
|
||||
this.handleUrlBlur = this.handleUrlBlur.bind(this);
|
||||
this.handleBodyBlur = this.handleBodyBlur.bind(this);
|
||||
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
||||
this.handleNsfwChange = this.handleNsfwChange.bind(this);
|
||||
this.handleThumbnailUrlBlur = this.handleThumbnailUrlBlur.bind(this);
|
||||
this.handleAltTextBlur = this.handleAltTextBlur.bind(this);
|
||||
|
||||
// Only fetch the data if coming from another route
|
||||
// Only fetch the data if coming from another routeupdate
|
||||
if (FirstLoadService.isFirstLoad) {
|
||||
const { communityResponse: communityRes, initialCommunitiesRes } =
|
||||
this.isoData.routeData;
|
||||
|
@ -166,11 +197,31 @@ export class CreatePost extends Component<
|
|||
|
||||
render() {
|
||||
const { selectedCommunityChoice, siteRes, loading } = this.state;
|
||||
const {
|
||||
body,
|
||||
communityId,
|
||||
customThumbnailUrl,
|
||||
languageId,
|
||||
title,
|
||||
nsfw,
|
||||
url,
|
||||
} = this.props;
|
||||
|
||||
// Only use the name, url, and body from this
|
||||
const locationState = this.props.history.location.state as
|
||||
| PostFormParams
|
||||
| CrossPostParams
|
||||
| undefined;
|
||||
|
||||
const params: PostFormParams = {
|
||||
name: title || locationState?.name,
|
||||
url: url || locationState?.url,
|
||||
body: body || locationState?.body,
|
||||
community_id: communityId,
|
||||
custom_thumbnail: customThumbnailUrl,
|
||||
language_id: languageId,
|
||||
nsfw: nsfw === "true",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="create-post container-lg">
|
||||
<HtmlTags
|
||||
|
@ -182,7 +233,7 @@ export class CreatePost extends Component<
|
|||
<h1 className="h4 mb-4">{I18NextService.i18n.t("create_post")}</h1>
|
||||
<PostForm
|
||||
onCreate={this.handlePostCreate}
|
||||
params={locationState}
|
||||
params={params}
|
||||
enableDownvotes={enableDownvotes(siteRes)}
|
||||
voteDisplayMode={voteDisplayMode(siteRes)}
|
||||
enableNsfw={enableNsfw(siteRes)}
|
||||
|
@ -196,6 +247,12 @@ export class CreatePost extends Component<
|
|||
: []
|
||||
}
|
||||
loading={loading}
|
||||
onBodyBlur={this.handleBodyBlur}
|
||||
onLanguageChange={this.handleLanguageChange}
|
||||
onTitleBlur={this.handleTitleBlur}
|
||||
onUrlBlur={this.handleUrlBlur}
|
||||
onThumbnailUrlBlur={this.handleThumbnailUrlBlur}
|
||||
onNsfwChange={this.handleNsfwChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -203,23 +260,36 @@ export class CreatePost extends Component<
|
|||
);
|
||||
}
|
||||
|
||||
async updateUrl({ communityId }: Partial<CreatePostProps>) {
|
||||
const locationState = this.props.history.location.state as
|
||||
| PostFormParams
|
||||
| undefined;
|
||||
async updateUrl(props: Partial<CreatePostProps>) {
|
||||
const {
|
||||
body,
|
||||
communityId,
|
||||
customThumbnailUrl,
|
||||
languageId,
|
||||
nsfw,
|
||||
url,
|
||||
title,
|
||||
altText,
|
||||
} = {
|
||||
...this.props,
|
||||
...props,
|
||||
};
|
||||
|
||||
const url = new URL(location.href);
|
||||
const createPostQueryParams: QueryParams<CreatePostProps> = {
|
||||
body,
|
||||
communityId: communityId?.toString(),
|
||||
customThumbnailUrl,
|
||||
languageId: languageId?.toString(),
|
||||
title,
|
||||
nsfw,
|
||||
url,
|
||||
altText,
|
||||
};
|
||||
|
||||
const newId = communityId?.toString();
|
||||
|
||||
if (newId !== undefined) {
|
||||
url.searchParams.set("communityId", newId);
|
||||
} else {
|
||||
url.searchParams.delete("communityId");
|
||||
}
|
||||
|
||||
// This bypasses the router and doesn't update the query props.
|
||||
window.history.replaceState(locationState, "", url);
|
||||
this.props.history.replace({
|
||||
pathname: "/create_post",
|
||||
search: getQueryString(createPostQueryParams),
|
||||
});
|
||||
|
||||
await this.fetchCommunity({ communityId });
|
||||
}
|
||||
|
@ -230,6 +300,34 @@ export class CreatePost extends Component<
|
|||
});
|
||||
}
|
||||
|
||||
handleTitleBlur(title: string) {
|
||||
this.updateUrl({ title });
|
||||
}
|
||||
|
||||
handleUrlBlur(url: string) {
|
||||
this.updateUrl({ url });
|
||||
}
|
||||
|
||||
handleBodyBlur(body: string) {
|
||||
this.updateUrl({ body });
|
||||
}
|
||||
|
||||
handleLanguageChange(languageId: number) {
|
||||
this.updateUrl({ languageId });
|
||||
}
|
||||
|
||||
handleNsfwChange(nsfw: StringBoolean) {
|
||||
this.updateUrl({ nsfw });
|
||||
}
|
||||
|
||||
handleThumbnailUrlBlur(customThumbnailUrl: string) {
|
||||
this.updateUrl({ customThumbnailUrl });
|
||||
}
|
||||
|
||||
handleAltTextBlur(altText: string) {
|
||||
this.updateUrl({ altText });
|
||||
}
|
||||
|
||||
async handlePostCreate(form: CreatePostI, bypassNavWarning: () => void) {
|
||||
this.setState({ loading: true });
|
||||
const res = await HttpService.client.createPost(form);
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
validURL,
|
||||
} from "@utils/helpers";
|
||||
import { isImage } from "@utils/media";
|
||||
import { Choice } from "@utils/types";
|
||||
import { Choice, StringBoolean } from "@utils/types";
|
||||
import autosize from "autosize";
|
||||
import { Component, InfernoNode, createRef, linkEvent } from "inferno";
|
||||
import { Prompt } from "inferno-router";
|
||||
|
@ -63,6 +63,13 @@ interface PostFormProps {
|
|||
onSelectCommunity?: (choice: Choice) => void;
|
||||
initialCommunities?: CommunityView[];
|
||||
loading: boolean;
|
||||
onTitleBlur?: (title: string) => void;
|
||||
onUrlBlur?: (url: string) => void;
|
||||
onBodyBlur?: (body: string) => void;
|
||||
onLanguageChange?: (languageId?: number) => void;
|
||||
onNsfwChange?: (nsfw: StringBoolean) => void;
|
||||
onThumbnailUrlBlur?: (thumbnailUrl: string) => void;
|
||||
onAltTextBlur?: (altText: string) => void;
|
||||
}
|
||||
|
||||
interface PostFormState {
|
||||
|
@ -167,8 +174,18 @@ function handlePostUrlChange(i: PostForm, event: any) {
|
|||
i.fetchPageTitle();
|
||||
}
|
||||
|
||||
function handlePostUrlBlur(i: PostForm, event: any) {
|
||||
i.setState({ bypassNavWarning: true });
|
||||
i.props.onUrlBlur?.(event.target.value);
|
||||
i.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
function handlePostNsfwChange(i: PostForm, event: any) {
|
||||
i.setState(s => ((s.form.nsfw = event.target.checked), s));
|
||||
|
||||
i.setState({ bypassNavWarning: true });
|
||||
i.props.onNsfwChange?.(event.target.checked ? "true" : "false");
|
||||
i.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
function handleHoneyPotChange(i: PostForm, event: any) {
|
||||
|
@ -179,10 +196,22 @@ function handleAltTextChange(i: PostForm, event: any) {
|
|||
i.setState(s => ((s.form.alt_text = event.target.value), s));
|
||||
}
|
||||
|
||||
function handleAltTextBlur(i: PostForm, event: any) {
|
||||
i.setState({ bypassNavWarning: true });
|
||||
i.props.onAltTextBlur?.(event.target.value);
|
||||
i.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
function handleCustomThumbnailChange(i: PostForm, event: any) {
|
||||
i.setState(s => ((s.form.custom_thumbnail = event.target.value), s));
|
||||
}
|
||||
|
||||
function handleCustomThumbnailBlur(i: PostForm, event: any) {
|
||||
i.setState({ bypassNavWarning: true });
|
||||
i.props.onThumbnailUrlBlur?.(event.target.value);
|
||||
i.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
function handleCancel(i: PostForm) {
|
||||
i.props.onCancel?.();
|
||||
}
|
||||
|
@ -206,8 +235,6 @@ function handleImageUpload(i: PostForm, event: any) {
|
|||
i.setState({ imageLoading: true });
|
||||
|
||||
HttpService.client.uploadImage({ image: file }).then(res => {
|
||||
console.log("pictrs upload:");
|
||||
console.log(res);
|
||||
if (res.state === "success") {
|
||||
if (res.data.msg === "ok") {
|
||||
i.state.form.url = res.data.url;
|
||||
|
@ -233,6 +260,12 @@ function handlePostNameChange(i: PostForm, event: any) {
|
|||
i.fetchSimilarPosts();
|
||||
}
|
||||
|
||||
function handlePostNameBlur(i: PostForm, event: any) {
|
||||
i.setState({ bypassNavWarning: true });
|
||||
i.props.onTitleBlur?.(event.target.value);
|
||||
i.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
function handleImageDelete(i: PostForm) {
|
||||
const { imageDeleteUrl } = i.state;
|
||||
|
||||
|
@ -270,6 +303,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
this.fetchSimilarPosts = debounce(this.fetchSimilarPosts.bind(this));
|
||||
this.fetchPageTitle = debounce(this.fetchPageTitle.bind(this));
|
||||
this.handlePostBodyChange = this.handlePostBodyChange.bind(this);
|
||||
this.handlePostBodyBlur = this.handlePostBodyBlur.bind(this);
|
||||
this.handleLanguageChange = this.handleLanguageChange.bind(this);
|
||||
this.handleCommunitySelect = this.handleCommunitySelect.bind(this);
|
||||
|
||||
|
@ -393,6 +427,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
value={this.state.form.name}
|
||||
id="post-title"
|
||||
onInput={linkEvent(this, handlePostNameChange)}
|
||||
onBlur={linkEvent(this, handlePostNameBlur)}
|
||||
className={`form-control ${
|
||||
!validTitle(this.state.form.name) && "is-invalid"
|
||||
}`}
|
||||
|
@ -423,6 +458,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
className="form-control mb-3"
|
||||
value={url}
|
||||
onInput={linkEvent(this, handlePostUrlChange)}
|
||||
onBlur={linkEvent(this, handlePostUrlBlur)}
|
||||
onPaste={linkEvent(this, handleImageUploadPaste)}
|
||||
/>
|
||||
{this.renderSuggestedTitleCopy()}
|
||||
|
@ -538,6 +574,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
className="form-control mb-3"
|
||||
value={this.state.form.custom_thumbnail}
|
||||
onInput={linkEvent(this, handleCustomThumbnailChange)}
|
||||
onBlur={linkEvent(this, handleCustomThumbnailBlur)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -552,6 +589,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
initialContent={this.state.form.body}
|
||||
placeholder={I18NextService.i18n.t("optional")}
|
||||
onContentChange={this.handlePostBodyChange}
|
||||
onContentBlur={this.handlePostBodyBlur}
|
||||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
hideNavigationWarnings
|
||||
|
@ -581,6 +619,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
id="post-alt-text"
|
||||
value={this.state.form.alt_text}
|
||||
onInput={linkEvent(this, handleAltTextChange)}
|
||||
onBlur={linkEvent(this, handleAltTextBlur)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -776,8 +815,18 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
this.setState(s => ((s.form.body = val), s));
|
||||
}
|
||||
|
||||
handlePostBodyBlur(val: string) {
|
||||
this.setState({ bypassNavWarning: true });
|
||||
this.props.onBodyBlur?.(val);
|
||||
this.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
handleLanguageChange(val: number[]) {
|
||||
this.setState(s => ((s.form.language_id = val.at(0)), s));
|
||||
|
||||
this.setState({ bypassNavWarning: true });
|
||||
this.props.onLanguageChange?.(val.at(0));
|
||||
this.setState({ bypassNavWarning: false });
|
||||
}
|
||||
|
||||
handleCommunitySearch = debounce(async (text: string) => {
|
||||
|
@ -804,8 +853,8 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
|||
});
|
||||
|
||||
handleCommunitySelect(choice: Choice) {
|
||||
if (this.props.onSelectCommunity) {
|
||||
this.props.onSelectCommunity(choice);
|
||||
}
|
||||
this.setState({ bypassNavWarning: true });
|
||||
this.props.onSelectCommunity?.(choice);
|
||||
this.setState({ bypassNavWarning: false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ export interface PostFormParams {
|
|||
name?: string;
|
||||
url?: string;
|
||||
body?: string;
|
||||
nsfw?: boolean;
|
||||
language_id?: number;
|
||||
community_id?: number;
|
||||
custom_thumbnail?: string;
|
||||
alt_text?: string;
|
||||
}
|
||||
|
||||
export enum CommentViewType {
|
||||
|
|
Loading…
Reference in a new issue