fix : ArticleDetail Page Refactoring
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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');
|
||||
@@ -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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 }
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user