Add slugs for Posts, Boards and OAuths (#321)

This commit is contained in:
Riccardo Graziosi
2024-04-05 18:23:31 +02:00
committed by GitHub
parent e887bca9cf
commit 09fb156a4e
30 changed files with 262 additions and 25 deletions

View File

@@ -62,8 +62,12 @@ export const deleteBoard = (
} else {
dispatch(boardDeleteFailure(json.error));
}
return Promise.resolve(res);
} catch (e) {
dispatch(boardDeleteFailure(e));
return Promise.resolve(null);
}
}
);

View File

@@ -48,6 +48,7 @@ export const updateBoard = (
id: number,
name: string,
description: string,
slug: string,
authenticityToken: string,
): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
dispatch(boardUpdateStart());
@@ -60,6 +61,7 @@ export const updateBoard = (
board: {
name,
description,
slug,
},
}),
});

View File

@@ -107,7 +107,7 @@ class NewPost extends React.Component<Props, State> {
});
const json = await res.json();
this.setState({isLoading: false});
if (res.status === HttpStatus.Created) {
this.setState({
success: I18n.t('board.new_post.submit_success'),
@@ -117,7 +117,7 @@ class NewPost extends React.Component<Props, State> {
});
setTimeout(() => (
window.location.href = `/posts/${json.id}`
window.location.href = `/posts/${json.slug || json.id}`
), 1000);
} else {
this.setState({error: json.error});

View File

@@ -55,6 +55,7 @@ const PostList = ({
<PostListItem
id={post.id}
title={post.title}
slug={post.slug}
description={post.description}
postStatus={postStatuses.find(postStatus => postStatus.id === post.postStatusId)}
likeCount={post.likeCount}

View File

@@ -10,6 +10,7 @@ import IPostStatus from '../../interfaces/IPostStatus';
interface Props {
id: number;
title: string;
slug?: string;
description?: string;
postStatus: IPostStatus;
likeCount: number;
@@ -25,6 +26,7 @@ interface Props {
const PostListItem = ({
id,
title,
slug,
description,
postStatus,
likeCount,
@@ -36,7 +38,7 @@ const PostListItem = ({
isLoggedIn,
authenticityToken,
}: Props) => (
<div onClick={() => window.location.href = `/posts/${id}`} className="postListItem">
<div onClick={() => window.location.href = `/posts/${slug || id}`} className="postListItem">
<LikeButton
postId={id}
likeCount={likeCount}
@@ -46,7 +48,7 @@ const PostListItem = ({
isLoggedIn={isLoggedIn}
authenticityToken={authenticityToken}
/>
<div className="postContainer">
<span className="postTitle">{title}</span>
<ReactMarkdown className="descriptionText" allowedTypes={['text']} unwrapDisallowed>

View File

@@ -14,13 +14,15 @@ interface Props {
id: number;
name: string;
description?: string;
slug?: string;
index: number;
settingsAreUpdating: boolean;
handleUpdate(
id: number,
description: string,
name: string,
description: string,
slug: string,
onSuccess: Function,
): void;
handleDelete(id: number): void;
@@ -46,11 +48,12 @@ class BoardsEditable extends React.Component<Props, State> {
this.setState({editMode: !this.state.editMode});
}
handleUpdate(id: number, name: string, description: string) {
handleUpdate(id: number, name: string, description: string, slug: string) {
this.props.handleUpdate(
id,
name,
description,
slug,
() => this.setState({editMode: false}),
);
}
@@ -60,6 +63,7 @@ class BoardsEditable extends React.Component<Props, State> {
id,
name,
description,
slug,
index,
settingsAreUpdating,
handleDelete,
@@ -108,6 +112,7 @@ class BoardsEditable extends React.Component<Props, State> {
id={id}
name={name}
description={description}
slug={slug}
handleUpdate={this.handleUpdate}
/>

View File

@@ -3,6 +3,7 @@ import { useForm, SubmitHandler } from 'react-hook-form';
import I18n from 'i18n-js';
import Button from '../../common/Button';
import { DangerText } from '../../common/CustomTexts';
interface Props {
mode: 'create' | 'update';
@@ -10,6 +11,7 @@ interface Props {
id?: number;
name?: string;
description?: string;
slug?: string;
handleCreate?(
name: string,
@@ -20,12 +22,14 @@ interface Props {
id: number,
name: string,
description?: string,
slug?: string,
): void;
}
interface IBoardForm {
name: string;
description: string;
slug?: string;
}
const BoardForm = ({
@@ -33,6 +37,7 @@ const BoardForm = ({
id,
name,
description,
slug,
handleCreate,
handleUpdate,
}: Props) => {
@@ -40,15 +45,19 @@ const BoardForm = ({
register,
handleSubmit,
reset,
formState: { isValid },
formState: { isValid, errors },
watch,
} = useForm<IBoardForm>({
mode: 'onChange',
defaultValues: {
name: name || '',
description: description || '',
slug: slug || undefined,
},
});
const formBoardName = watch('name');
const onSubmit: SubmitHandler<IBoardForm> = data => {
if (mode === 'create') {
handleCreate(
@@ -57,7 +66,7 @@ const BoardForm = ({
() => reset({ name: '', description: '' })
);
} else {
handleUpdate(id, data.name, data.description);
handleUpdate(id, data.name, data.description, data.slug);
}
}
@@ -91,6 +100,25 @@ const BoardForm = ({
placeholder={I18n.t('site_settings.boards.form.description')}
className="formControl"
/>
{mode === 'update' && (
<>
<div className="input-group">
<div className="input-group-prepend">
<div className="input-group-text">boards/</div>
</div>
<input
{...register('slug', { pattern: /^[a-zA-Z0-9-]+$/ })}
type="text"
placeholder={formBoardName.trim().replace(/\s/g, '-').toLowerCase()}
className="formControl"
/>
</div>
<DangerText>
{errors.slug?.type === 'pattern' && I18n.t('common.validations.url')}
</DangerText>
</>
)}
</form>
);
}

View File

@@ -30,6 +30,7 @@ interface Props {
id: number,
name: string,
description: string,
slug: string,
onSuccess: Function,
authenticityToken: string,
): void;
@@ -61,8 +62,8 @@ class BoardsSiteSettingsP extends React.Component<Props> {
this.props.submitBoard(name, description, onSuccess, this.props.authenticityToken);
}
handleUpdate(id: number, name: string, description: string, onSuccess: Function) {
this.props.updateBoard(id, name, description, onSuccess, this.props.authenticityToken);
handleUpdate(id: number, name: string, description: string, slug: string, onSuccess: Function) {
this.props.updateBoard(id, name, description, slug, onSuccess, this.props.authenticityToken);
}
handleDragEnd(result) {
@@ -105,6 +106,7 @@ class BoardsSiteSettingsP extends React.Component<Props> {
id={board.id}
name={board.name}
description={board.description}
slug={board.slug}
index={i}
settingsAreUpdating={settingsAreUpdating}

View File

@@ -28,7 +28,10 @@ const mapDispatchToProps = (dispatch: any) => ({
authenticityToken: string,
) {
dispatch(submitBoard(name, description, authenticityToken)).then(res => {
if (res && res.status === HttpStatus.Created) onSuccess();
if (res && res.status === HttpStatus.Created) {
onSuccess();
window.location.reload();
}
});
},
@@ -36,11 +39,15 @@ const mapDispatchToProps = (dispatch: any) => ({
id: number,
name: string,
description: string,
slug: string,
onSuccess: Function,
authenticityToken: string,
) {
dispatch(updateBoard(id, name, description, authenticityToken)).then(res => {
if (res && res.status === HttpStatus.OK) onSuccess();
dispatch(updateBoard(id, name, description, slug, authenticityToken)).then(res => {
if (res && res.status === HttpStatus.OK) {
onSuccess();
window.location.reload();
}
});
},
@@ -54,7 +61,12 @@ const mapDispatchToProps = (dispatch: any) => ({
},
deleteBoard(id: number, authenticityToken: string) {
dispatch(deleteBoard(id, authenticityToken));
dispatch(deleteBoard(id, authenticityToken)).then(res => {
console.log(res);
if (res && res.status === HttpStatus.Accepted) {
window.location.reload();
}
});
},
});

View File

@@ -2,6 +2,7 @@ interface IBoard {
id: number;
name: string;
description?: string;
slug?: string;
}
export default IBoard;

View File

@@ -1,6 +1,7 @@
interface IPost {
id: number;
title: string;
slug?: string;
description?: string;
boardId: number;
postStatusId?: number;

View File

@@ -2,6 +2,7 @@ interface IBoardJSON {
id: number;
name: string;
description?: string;
slug?: string;
}
export default IBoardJSON;

View File

@@ -1,6 +1,7 @@
interface IPostJSON {
id: number;
title: string;
slug?: string;
description?: string;
board_id: number;
post_status_id?: number;

View File

@@ -63,6 +63,7 @@ const boardsReducer = (
id: board.id,
name: board.name,
description: board.description,
slug: board.slug,
})),
areLoading: false,
error: '',

View File

@@ -13,6 +13,7 @@ import IPost from '../interfaces/IPost';
const initialState: IPost = {
id: 0,
title: '',
slug: null,
description: null,
boardId: 0,
postStatusId: null,
@@ -37,6 +38,7 @@ const postReducer = (
return {
id: action.post.id,
title: action.post.title,
slug: action.post.slug,
description: action.post.description,
boardId: action.post.board_id,
postStatusId: action.post.post_status_id,