mirror of
https://github.com/astuto/astuto.git
synced 2025-12-15 19:27:52 +01:00
Improve Post component
This commit is contained in:
@@ -39,8 +39,9 @@ class PostsController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
post = Post.find(params[:id])
|
post = Post.find(params[:id])
|
||||||
|
|
||||||
if current_user.role == :user && current_user.id != post.user_id
|
if current_user.role == 'user' && current_user.id != post.user_id
|
||||||
render json: I18n.t('errors.unauthorized'), status: :unauthorized
|
render json: I18n.t('errors.unauthorized'), status: :unauthorized
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
post.post_status_id = params[:post][:post_status_id]
|
post.post_status_id = params[:post][:post_status_id]
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import PostStatusLabel from '../shared/PostStatusLabel';
|
||||||
|
|
||||||
import IPostStatus from '../../interfaces/IPostStatus';
|
import IPostStatus from '../../interfaces/IPostStatus';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -26,15 +28,7 @@ const PostListItem = ({ id, title, description, postStatus}: Props) => (
|
|||||||
<span className="comment icon"></span>
|
<span className="comment icon"></span>
|
||||||
<span>0 comments</span>
|
<span>0 comments</span>
|
||||||
</div>
|
</div>
|
||||||
{
|
{ postStatus ? <PostStatusLabel {...postStatus} /> : null }
|
||||||
postStatus ?
|
|
||||||
<div className="postDetailsStatus">
|
|
||||||
<div className="dot" style={{backgroundColor: postStatus.color}}></div>
|
|
||||||
<span className="postStatusName">{postStatus.name}</span>
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
null
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import PostStatusLabel from '../shared/PostStatusLabel';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name: string;
|
name: string;
|
||||||
color: string;
|
color: string;
|
||||||
@@ -19,8 +21,7 @@ const PostStatusListItem = ({
|
|||||||
<div className={"postStatusListItemContainer " + `postStatus${name.replace(/ /g, '')}`}>
|
<div className={"postStatusListItemContainer " + `postStatus${name.replace(/ /g, '')}`}>
|
||||||
<a onClick={handleClick} className="postStatusListItemLink">
|
<a onClick={handleClick} className="postStatusListItemLink">
|
||||||
<div className="postStatusListItem">
|
<div className="postStatusListItem">
|
||||||
<div className="dot" style={{backgroundColor: color}}></div>
|
<PostStatusLabel id={undefined} name={name} color={color} />
|
||||||
<span className="postStatusName">{name}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import IPost from '../../interfaces/IPost';
|
|||||||
import IPostStatus from '../../interfaces/IPostStatus';
|
import IPostStatus from '../../interfaces/IPostStatus';
|
||||||
|
|
||||||
import PostStatusSelect from './PostStatusSelect';
|
import PostStatusSelect from './PostStatusSelect';
|
||||||
|
import PostStatusLabel from '../shared/PostStatusLabel';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
postId: number;
|
postId: number;
|
||||||
@@ -39,9 +40,9 @@ class PostP extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>{post.title}</h1>
|
<h2>{post.title}</h2>
|
||||||
{
|
{
|
||||||
isPowerUser ?
|
isPowerUser && post ?
|
||||||
<PostStatusSelect
|
<PostStatusSelect
|
||||||
postStatuses={postStatuses}
|
postStatuses={postStatuses}
|
||||||
selectedPostStatusId={post.postStatusId}
|
selectedPostStatusId={post.postStatusId}
|
||||||
@@ -50,7 +51,9 @@ class PostP extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
:
|
:
|
||||||
<span>LLL</span>
|
<PostStatusLabel
|
||||||
|
{...postStatuses.find(postStatus => postStatus.id === post.postStatusId)}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<p>{post.description}</p>
|
<p>{post.description}</p>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const PostStatusSelect = ({
|
|||||||
handleChange,
|
handleChange,
|
||||||
}: Props) => (
|
}: Props) => (
|
||||||
<select
|
<select
|
||||||
value={selectedPostStatusId || ''}
|
value={selectedPostStatusId || 'none'}
|
||||||
onChange={
|
onChange={
|
||||||
(e: FormEvent) => (
|
(e: FormEvent) => (
|
||||||
handleChange(parseInt((e.target as HTMLSelectElement).value))
|
handleChange(parseInt((e.target as HTMLSelectElement).value))
|
||||||
@@ -30,7 +30,7 @@ const PostStatusSelect = ({
|
|||||||
{postStatus.name}
|
{postStatus.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
<option>None</option>
|
<option value="none">None</option>
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
16
app/javascript/components/shared/PostStatusLabel.tsx
Normal file
16
app/javascript/components/shared/PostStatusLabel.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import IPostStatus from '../../interfaces/IPostStatus';
|
||||||
|
|
||||||
|
const PostStatusLabel = ({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
color,
|
||||||
|
}: IPostStatus) => (
|
||||||
|
<div style={{display: 'flex'}}>
|
||||||
|
<div className="dot" style={{backgroundColor: color}}></div>
|
||||||
|
<span className="postStatusName">{name}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default PostStatusLabel;
|
||||||
@@ -17,6 +17,8 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
changePostStatus(postId: number, newPostStatusId: number, authenticityToken: string) {
|
changePostStatus(postId: number, newPostStatusId: number, authenticityToken: string) {
|
||||||
|
if (isNaN(newPostStatusId)) newPostStatusId = null;
|
||||||
|
|
||||||
dispatch(changePostStatus(postId, newPostStatusId, authenticityToken));
|
dispatch(changePostStatus(postId, newPostStatusId, authenticityToken));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,4 +9,14 @@
|
|||||||
|
|
||||||
.gravatar {
|
.gravatar {
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 100%;
|
||||||
|
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
@@ -199,16 +199,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 100%;
|
|
||||||
|
|
||||||
margin-top: auto;
|
|
||||||
margin-bottom: auto;
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.infoText {
|
.infoText {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -34,12 +34,6 @@
|
|||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.infoText {
|
.infoText {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -47,7 +41,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.columnTitle {
|
.columnTitle {
|
||||||
margin: 0 8px;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ RSpec.describe 'posts routing', :aggregate_failures, type: :routing do
|
|||||||
expect(post: '/posts').to route_to(
|
expect(post: '/posts').to route_to(
|
||||||
controller: 'posts', action: 'create'
|
controller: 'posts', action: 'create'
|
||||||
)
|
)
|
||||||
|
expect(get: '/posts/1').to route_to(
|
||||||
|
controller: 'posts', action: 'show', id: '1'
|
||||||
|
)
|
||||||
|
expect(patch: '/posts/1').to route_to(
|
||||||
|
controller: 'posts', action: 'update', id: '1'
|
||||||
|
)
|
||||||
|
|
||||||
expect(get: '/posts/1').not_to be_routable
|
|
||||||
expect(get: '/posts/1/edit').not_to be_routable
|
expect(get: '/posts/1/edit').not_to be_routable
|
||||||
expect(patch: '/posts/1').not_to be_routable
|
|
||||||
expect(delete: '/posts/1').not_to be_routable
|
expect(delete: '/posts/1').not_to be_routable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user