fix : ArticleDetail Page Refactoring

This commit is contained in:
minseokkang
2022-12-01 16:20:35 +09:00
parent a55f0c28f8
commit ebf851d1c5
6 changed files with 203 additions and 116 deletions

View File

@@ -22,7 +22,7 @@ public class ProfileServiceImpl implements ProfileService {
@Override
public ProfileResponse getProfile(UserAuth userAuth, String username) {
Optional<User> wantFindUser = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> new CustomException(Error.USER_NOT_FOUND)));
Optional<User> wantFindUser = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> {throw new CustomException(Error.USER_NOT_FOUND);}));
Boolean followStatus = null;
if(userAuth == null){
followStatus = false;
@@ -34,7 +34,7 @@ public class ProfileServiceImpl implements ProfileService {
@Override
public ProfileResponse followUser(UserAuth userAuth, String username) {
Optional<User> follower = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> new CustomException(Error.USER_NOT_FOUND)));
Optional<User> follower = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> {throw new CustomException(Error.USER_NOT_FOUND);}));
Optional<User> followee = userRepository.findById(userAuth.getId());
profileRepository.findByFolloweeIdAndFollowerId(followee.get().getId(), follower.get().getId()).ifPresent(follow -> {
throw new CustomException(Error.ALREADY_FOLLOW);
@@ -46,7 +46,7 @@ public class ProfileServiceImpl implements ProfileService {
@Override
public ProfileResponse unfollowUser(UserAuth userAuth, String username) {
Optional<User> follower = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> new CustomException(Error.USER_NOT_FOUND)));
Optional<User> follower = Optional.ofNullable(userRepository.findByUsername(username).orElseThrow(() -> {throw new CustomException(Error.USER_NOT_FOUND);}));
Optional<User> followee = userRepository.findById(userAuth.getId());
Follow follow = profileRepository.findByFolloweeIdAndFollowerId(followee.get().getId(), follower.get().getId()).orElseThrow(() -> {
throw new CustomException(Error.ALREADY_UNFOLLOW);

View File

@@ -43,7 +43,7 @@ public class WebConfig {
.disable()
.requestMatchers((matchers) -> {
matchers.antMatchers("/h2-console/**");
matchers.antMatchers(HttpMethod.GET,"/api/articles/**","/**");
matchers.antMatchers(HttpMethod.GET,"/api/articles/:slug","/**");
matchers.mvcMatchers("/api/users/**");
})
.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll())

View File

@@ -31,4 +31,103 @@ const updateUser = async (user: object): Promise<AxiosResponse> => {
})
}
export { signUp, signIn, getCurrentUser, updateUser }
const getProfile = async (username: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
if(currentToken == null){
return axiosService.get('/api/profiles/' + username);
}else {
return axiosService.get('/api/profiles/' + username,{
headers:{
Authorization: "TOKEN " + currentToken,
}
})
}
}
const followUser = async (username: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
return axiosService.post('/api/profiles/' + username + "/follow",{},{
headers:{
Authorization : "TOKEN " + currentToken,
"Content-Type": `application/json`,
}
})
}
const unfollowUser = async (username: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
return axiosService.delete('/api/profiles/' + username + "/follow",{
headers:{
Authorization : "TOKEN " + currentToken,
}
})
}
const getArticle = async (slug: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
if(currentToken == null){
return axiosService.get('/api/articles/' + slug);
}else{
return axiosService.get('/api/articles/' + slug,{
headers:{
Authorization: "TOKEN " + currentToken,
}
});
}
}
const addCommentToArticle = async (slug: string | undefined, comment: object): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
return axiosService.post('/api/articles' + slug + '/comments',{
comment
},{
headers:{
Authorization : "TOKEN " + currentToken,
"Content-Type": `application/json`,
}
});
}
const getCommentsFromArticle = async (slug: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
if(currentToken == null){
return axiosService.get('/api/articles/' + slug + "/comments");
}else {
return axiosService.get('/api/articles/' + slug + "/comments",{
headers:{
Authorization: "TOKEN " + currentToken,
}
})
}
}
const favoriteArticle = async (slug: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
return axiosService.post('/api/articles/' + slug + '/favorite',{},
{
headers:{
Authorization : "TOKEN " + currentToken,
"Content-Type": `application/json`,
}
});
}
const unFavoriteArticle = async (slug: string | undefined): Promise<AxiosResponse> => {
let currentToken = localStorage.getItem("token");
return axiosService.delete('/api/articles/' + slug + '/favorite',{
headers:{
Authorization : "TOKEN " + currentToken,
"Content-Type": `application/json`,
}
});
}
export { signUp, signIn,
getCurrentUser, updateUser,
getProfile, followUser,
unfollowUser, getArticle,
addCommentToArticle, getCommentsFromArticle,
favoriteArticle, unFavoriteArticle
}

View File

@@ -6,4 +6,5 @@ import '@/assets/css/font.css'
import '@/assets/css/main.css'
const app = createApp(App);
app.config.performance=true;
app.use(router).use(store).mount('#app');

View File

@@ -7,6 +7,7 @@
<h1>{{ articleDetail.article.title }}</h1>
<div class="article-meta">
<a href=""><img :src="articleDetail.article.author.image"/></a>
<div class="info">
<a href="javascript:void(0)" class="author" @click="viewProfile">{{ articleDetail.article.author.username }}</a>
<span class="date">{{convertDate(articleDetail.article.createdAt)}}</span>
@@ -22,7 +23,7 @@
</div>
</button>
&nbsp;&nbsp;
<button class="btn btn-sm btn-outline-primary" @click="favoriteUpdate()">
<button class="btn btn-sm btn-outline-primary" @click="favoriteUpdate(articleDetail.article.favorited)">
<div v-if="articleDetail.article.favorited">
<i class="ion-heart"></i>
unFavorite Article (<span class="counter">{{articleDetail.article.favoritesCount}}</span>)
@@ -42,6 +43,7 @@
<div class="row article-content">
<div class="col-md-12">
{{articleDetail.article.body}}
{{articleDetail}}
</div>
</div>
@@ -49,12 +51,11 @@
<div class="article-actions">
<div class="article-meta">
<a href="javascript:void(0)"><img :src="articleDetail.article.author.image"></a>
<a href="javascript:void(0)"><img :src="articleDetail.article.author.image"/></a>
<div class="info">
<a href="javascript:void(0)" class="author" @click="viewProfile">{{ articleDetail.article.author.username }}</a>
<span class="date">{{convertDate(articleDetail.article.createdAt)}}</span>
</div>
<button class="btn btn-sm btn-outline-secondary" @click="followUpdate(articleDetail.article.author.following)">
<div v-if="articleDetail.article.author.following">
<i class="ion-minus-round"></i>
@@ -66,7 +67,7 @@
</div>
</button>
&nbsp;
<button class="btn btn-sm btn-outline-primary" @click="favoriteUpdate()">
<button class="btn btn-sm btn-outline-primary" @click="favoriteUpdate(articleDetail.article.favorited)">
<div v-if="articleDetail.article.favorited">
<i class="ion-heart"></i>
unFavorite Article (<span class="counter">{{articleDetail.article.favoritesCount}}</span>)
@@ -96,7 +97,8 @@
</form>
<comment-list v-for="(comment,index) in getCommentList.comment"
:key="comment.id"
:comment="comment">
:comment="comment"
:imgs="comment.author.image">
</comment-list>
</div>
@@ -108,12 +110,19 @@
</template>
<script lang="ts">
import {onMounted, defineComponent, reactive, ref} from "vue";
import { onMounted, defineComponent, reactive } from "vue";
import commentList from "@/components/commentList.vue";
import axios from "axios";
import router from "@/router";
import {useStore} from "vuex";
import { useStore } from "vuex";
import convertDate from "@/ts/common";
import {
addCommentToArticle,
favoriteArticle,
followUser,
getArticle,
getCommentsFromArticle, unFavoriteArticle,
unfollowUser
} from "@/api";
export default defineComponent({
name: "TheArticleDetail.vue",
@@ -124,7 +133,6 @@ export default defineComponent({
slug: String,
},
setup(props){
const url = import.meta.env.VITE_BASE_URL;
const store = useStore();
const token = store.state.token;
@@ -133,7 +141,7 @@ export default defineComponent({
})
const getCommentList = reactive({
comment: reactive([{id:0}])
comment: reactive([{id:0,author:{image:""}}])
})
const articleDetail = reactive({
@@ -162,85 +170,68 @@ export default defineComponent({
params: {username: articleDetail.article.author.username}})
}
const followUpdate = (followState : boolean) => {
const followUpdate = async (followState: boolean) => {
if(token == ''){
router.push({name:"Login"});
await router.push({name:"Login"});
return;
}
if(followState){
axios.delete(url + "/api/profiles/" + articleDetail.article.author.username + "/follow",{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
articleDetail.article.author.following = response.data.profile.following;
})
}else{
axios.post(url + "/api/profiles/" + articleDetail.article.author.username + "/follow",{},{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
articleDetail.article.author.following = response.data.profile.following;
})
try {
if(followState){
const { data } = await unfollowUser(articleDetail.article.author.username);
articleDetail.article.author.following = data.profile.following;
}else{
const { data } = await followUser(articleDetail.article.author.username);
articleDetail.article.author.following = data.profile.following;
}
}catch (error: any){
alert(error);
}
}
const favoriteUpdate = () => {
const favoriteUpdate = async (favoriteState: boolean) => {
if(token == ''){
router.push({name:"Login"});
await router.push({name:"Login"});
return;
}
const favoriteState: boolean = articleDetail.article.favorited;
if(favoriteState){
axios.delete(url + "/api/articles/" + articleDetail.article.slug + "/favorite",{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
articleDetail.article.favorited = response.data.article.favorited;
articleDetail.article.favoritesCount = response.data.article.favoritesCount;
})
}else{
axios.post(url + "/api/articles/" + articleDetail.article.slug + "/favorite",{},{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
articleDetail.article.favorited = response.data.article.favorited;
articleDetail.article.favoritesCount = response.data.article.favoritesCount;
})
try {
if (favoriteState) {
const {data} = await unFavoriteArticle(props.slug);
articleDetail.article = data.article;
} else {
const {data} = await favoriteArticle(props.slug);
articleDetail.article = data.article;
}
}catch (error: any){
alert(error);
}
}
const sendComment = () => {
axios.post(url + "/api/articles/"+ articleDetail.article.slug + "/comments",{
comment
},{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
comment.body="";
getCommentList.comment.push(response.data.comment);
})
const sendComment = async () => {
try{
const { data } = await addCommentToArticle(props.slug, comment);
comment.body = "";
getCommentList.comment.push(data.comment);
}catch (error: any){
alert(error);
}
}
onMounted(async ()=>{
try{
const { data } = await getArticle(props.slug);
articleDetail.article = data.article;
}catch (error: any){
alert(error);
}
onMounted(()=>{
axios.get(url + "/api/articles/" + props.slug,)
.then(response => {
articleDetail.article = response.data.article;
console.log(articleDetail.article);
})
axios.get(url + "/api/articles/" + props.slug + "/comments")
.then(response => {
getCommentList.comment = response.data.comments;
})
try{
const { data } = await getCommentsFromArticle(props.slug);
getCommentList.comment = data.comments;
}catch (error: any){
alert(error);
}
})
return { articleDetail, comment, getCommentList, convertDate, viewProfile, followUpdate, favoriteUpdate, sendComment }

View File

@@ -19,7 +19,7 @@
</div>
<div v-else>
<div v-if="profile.following">
<i class="ion-plus-round"></i>
<i class="ion-minus-round"></i>
unFollow {{profile.username}}
</div>
<div v-else>
@@ -101,9 +101,9 @@
<script lang="ts">
import {onMounted, reactive, ref} from "vue";
import { useStore } from "vuex";
import axios from "axios";
import { defineComponent } from 'vue';
import router from "@/router";
import {followUser, getProfile, unfollowUser} from "@/api";
export default defineComponent({
name: "TheProfile.vue",
@@ -114,7 +114,6 @@ export default defineComponent({
const url = import.meta.env.VITE_BASE_URL;
const store = useStore();
const token = store.state.token;
const isMe = ref(false);
const profile = reactive({
@@ -124,53 +123,50 @@ export default defineComponent({
following: false,
})
const setProfile = ( data: any ) => {
const setProfile = async ( data: any ) => {
profile.image = data.image;
profile.bio = data.bio;
profile.following = data.following;
profile.username = data.username;
}
const stateUpdate = () => {
const stateUpdate = async () => {
if(isMe.value){
router.push({name:"Settings"});
await router.push({name:"Settings"});
}else{
if(profile.following){
axios.delete(url + "/api/profiles/" + profile.username + "/follow",{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
setProfile(response.data.profile)
})
try {
const { data } = await unfollowUser(profile.username);
await setProfile(data.profile);
}catch (error: any){
alert("error");
}
}else{
axios.post(url + "/api/profiles/" + profile.username + "/follow",{},{
headers:{
Authorization : "TOKEN " + token,
"Content-Type": `application/json`,
}
}).then(response => {
setProfile(response.data.profile)
})
try {
const { data } = await followUser(profile.username);
await setProfile(data.profile);
}catch (error: any){
alert("error");
}
}
}
}
onMounted(() =>{
axios.get(url + "/api/profiles/" + props.username)
.then(response => {
const getProfile = response.data.profile;
setProfile(getProfile)
if(getProfile.username.localeCompare(store.state.username) == 0){
isMe.value = true;
}else{
isMe.value = false;
}
})
onMounted(async () =>{
try {
const { data } = await getProfile(props.username)
await setProfile(data.profile);
if(data.profile.username.localeCompare(store.state.username) == 0){
isMe.value = true;
}else{
isMe.value = false;
}
}catch (error: any){
const code = error.response.data.errors.code;
if(code == "USER_NOT_FOUND")
await router.push({name:"home"});
}
})
return { url, isMe, profile, stateUpdate }
}