✨ Deletion
This commit is contained in:
parent
7b2a6c3709
commit
f5ebc1748a
@ -3,7 +3,7 @@
|
|||||||
<v-progress-circular indeterminate />
|
<v-progress-circular indeterminate />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="flex flex-col gap-2 mt-3">
|
<div v-else class="flex flex-col gap-5 mt-3">
|
||||||
<div v-for="(item, idx) in props.comments" class="text-sm">
|
<div v-for="(item, idx) in props.comments" class="text-sm">
|
||||||
<post-item :item="item" @update:item="(val) => updateItem(idx, val)" />
|
<post-item :item="item" @update:item="(val) => updateItem(idx, val)" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<v-list density="compact" lines="one">
|
<v-list density="compact" lines="one">
|
||||||
<v-list-item disabled append-icon="mdi-flag" title="Report" />
|
<v-list-item disabled append-icon="mdi-flag" title="Report" />
|
||||||
<v-list-item v-if="isOwned" append-icon="mdi-pencil" title="Edit" @click="editPost" />
|
<v-list-item v-if="isOwned" append-icon="mdi-pencil" title="Edit" @click="editPost" />
|
||||||
<v-list-item v-if="isOwned" append-icon="mdi-delete" title="Delete" />
|
<v-list-item v-if="isOwned" append-icon="mdi-delete" title="Delete" @click="deletePost" />
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</div>
|
</div>
|
||||||
@ -81,10 +81,19 @@ const isOwned = computed(() => props.item?.author_id === id.userinfo.data.id)
|
|||||||
|
|
||||||
function editPost() {
|
function editPost() {
|
||||||
editor.related.edit_to = props.item
|
editor.related.edit_to = props.item
|
||||||
if(editor.show.hasOwnProperty(props.item.model_type)) {
|
if (editor.show.hasOwnProperty(props.item.model_type)) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
editor.show[props.item.model_type] = true
|
editor.show[props.item.model_type] = true
|
||||||
}
|
}
|
||||||
|
if (props.item.model_type === "comment") {
|
||||||
|
editor.related.comment_to = props.item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deletePost() {
|
||||||
|
editor.related.delete_to = JSON.parse(JSON.stringify(props.item))
|
||||||
|
editor.related.delete_to.model_type = props.item.model_type + "s"
|
||||||
|
editor.show.delete = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateReactions(symbol: string, num: number) {
|
function updateReactions(symbol: string, num: number) {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-container class="article-container">
|
<v-container class="article-container">
|
||||||
<v-alert v-if="editor.related.edit_to" class="mb-3" type="info" variant="tonal">
|
<v-alert v-if="editor.related.edit_to" class="mb-5" type="info" variant="tonal">
|
||||||
You are editing a post with alias <b class="font-mono">{{ editor.related.edit_to?.alias }}</b>
|
You are editing a post with alias <b class="font-mono">{{ editor.related.edit_to?.alias }}</b>
|
||||||
</v-alert>
|
</v-alert>
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
<v-card title="Leave your comment" :loading="loading">
|
<v-card title="Leave your comment" :loading="loading">
|
||||||
<v-form @submit.prevent="postComment">
|
<v-form @submit.prevent="postComment">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-textarea required hide-details name="content" variant="outlined" label="What do you want to say?" />
|
<v-alert v-if="editor.related.edit_to" class="mb-5" type="info" variant="tonal">
|
||||||
|
You are editing a comment with alias <b class="font-mono">{{ editor.related.edit_to?.alias }}</b>
|
||||||
|
</v-alert>
|
||||||
|
|
||||||
|
<v-textarea required hide-details variant="outlined" label="What do you want to say?" v-model="data.content" />
|
||||||
|
|
||||||
<p class="px-2 mt-1 text-body-2 opacity-80">Your comment will leave below {{ postIdentifier }}</p>
|
<p class="px-2 mt-1 text-body-2 opacity-80">Your comment will leave below {{ postIdentifier }}</p>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
@ -26,7 +30,7 @@
|
|||||||
import { request } from "@/scripts/request"
|
import { request } from "@/scripts/request"
|
||||||
import { useEditor } from "@/stores/editor"
|
import { useEditor } from "@/stores/editor"
|
||||||
import { getAtk } from "@/stores/userinfo"
|
import { getAtk } from "@/stores/userinfo"
|
||||||
import { computed, ref } from "vue"
|
import { computed, ref, watch } from "vue"
|
||||||
|
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
|
|
||||||
@ -43,16 +47,26 @@ const error = ref<string | null>(null)
|
|||||||
const success = ref(false)
|
const success = ref(false)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const data = ref<any>({
|
||||||
|
content: ""
|
||||||
|
})
|
||||||
|
|
||||||
async function postComment(evt: SubmitEvent) {
|
async function postComment(evt: SubmitEvent) {
|
||||||
const form = evt.target as HTMLFormElement
|
const form = evt.target as HTMLFormElement
|
||||||
const data = new FormData(form)
|
const payload = data.value
|
||||||
if (!data.has("content")) return
|
|
||||||
|
if (!payload.content) return
|
||||||
|
|
||||||
|
const url = editor.related.edit_to
|
||||||
|
? `/api/p/comments/${editor.related.edit_to?.id}`
|
||||||
|
: `/api/p/${target.value?.model_type}/${target.value?.alias}/comments`
|
||||||
|
const method = editor.related.edit_to ? "PUT" : "POST"
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const res = await request(`/api/p/${target.value?.model_type}/${target.value?.alias}/comments`, {
|
const res = await request(url, {
|
||||||
method: "POST",
|
method: method,
|
||||||
headers: { Authorization: `Bearer ${getAtk()}` },
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${getAtk()}` },
|
||||||
body: data
|
body: JSON.stringify(payload)
|
||||||
})
|
})
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
form.reset()
|
form.reset()
|
||||||
@ -64,4 +78,10 @@ async function postComment(evt: SubmitEvent) {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
editor.done = true
|
editor.done = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(editor.related, (val) => {
|
||||||
|
if (val.edit_to && val.edit_to.model_type === "comment") {
|
||||||
|
data.value = val.edit_to
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<v-card title="Record a moment" :loading="loading">
|
<v-card title="Record a moment" :loading="loading">
|
||||||
<v-form @submit.prevent="postMoment">
|
<v-form @submit.prevent="postMoment">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-alert v-if="editor.related.edit_to" class="mb-3" type="info" variant="tonal">
|
<v-alert v-if="editor.related.edit_to" class="mb-5" type="info" variant="tonal">
|
||||||
You are editing a post with alias <b class="font-mono">{{ editor.related.edit_to?.alias }}</b>
|
You are editing a post with alias <b class="font-mono">{{ editor.related.edit_to?.alias }}</b>
|
||||||
</v-alert>
|
</v-alert>
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ async function postMoment(evt: SubmitEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(editor.related, (val) => {
|
watch(editor.related, (val) => {
|
||||||
if (val.edit_to) {
|
if (val.edit_to && val.edit_to.model_type === "moment") {
|
||||||
data.value = val.edit_to
|
data.value = val.edit_to
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -8,13 +8,18 @@
|
|||||||
<v-dialog v-model="editor.show.article" transition="dialog-bottom-transition" fullscreen eager>
|
<v-dialog v-model="editor.show.article" transition="dialog-bottom-transition" fullscreen eager>
|
||||||
<article-editor />
|
<article-editor />
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-dialog v-model="editor.show.delete" class="max-w-[540px]" eager>
|
||||||
|
<post-deletion />
|
||||||
|
</v-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useEditor } from "@/stores/editor"
|
import { useEditor } from "@/stores/editor"
|
||||||
import MomentEditor from "@/components/publish/MomentEditor.vue"
|
import MomentEditor from "@/components/publish/MomentEditor.vue"
|
||||||
import CommentEditor from "@/components/publish/CommentEditor.vue";
|
import CommentEditor from "@/components/publish/CommentEditor.vue"
|
||||||
import ArticleEditor from "@/components/publish/ArticleEditor.vue";
|
import ArticleEditor from "@/components/publish/ArticleEditor.vue"
|
||||||
|
import PostDeletion from "@/components/publish/PostDeletion.vue"
|
||||||
|
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
</script>
|
</script>
|
||||||
|
51
pkg/views/src/components/publish/PostDeletion.vue
Normal file
51
pkg/views/src/components/publish/PostDeletion.vue
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<v-card title="Delete a post" :loading="loading">
|
||||||
|
<template #text>
|
||||||
|
You are deleting a post with alias
|
||||||
|
<b class="font-mono">{{ editor.related.delete_to?.alias }}</b>
|
||||||
|
Are you confirm?
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<div class="w-full flex justify-end">
|
||||||
|
<v-btn color="grey-darken-3" @click="editor.show.delete = false">Not really</v-btn>
|
||||||
|
<v-btn color="error" :disabled="loading" @click="deletePost">Yes</v-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<v-snackbar v-model="success" :timeout="3000">The post has been deleted.</v-snackbar>
|
||||||
|
|
||||||
|
<!-- @vue-ignore -->
|
||||||
|
<v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useEditor } from "@/stores/editor"
|
||||||
|
import { getAtk } from "@/stores/userinfo"
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
const editor = useEditor()
|
||||||
|
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
const success = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
async function deletePost() {
|
||||||
|
const target = editor.related.delete_to
|
||||||
|
const url = `/api/p/${target.model_type}/${target.id}`
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: { Authorization: `Bearer ${getAtk()}` }
|
||||||
|
})
|
||||||
|
if (res.status !== 200) {
|
||||||
|
error.value = await res.text()
|
||||||
|
} else {
|
||||||
|
success.value = true
|
||||||
|
editor.show.delete = false
|
||||||
|
editor.related.delete_to = null
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from "pinia"
|
import { defineStore } from "pinia"
|
||||||
import { reactive, ref } from "vue"
|
import { reactive, ref } from "vue"
|
||||||
|
import { getAtk } from "@/stores/userinfo"
|
||||||
|
|
||||||
export const useEditor = defineStore("editor", () => {
|
export const useEditor = defineStore("editor", () => {
|
||||||
const done = ref(false)
|
const done = ref(false)
|
||||||
@ -7,14 +8,22 @@ export const useEditor = defineStore("editor", () => {
|
|||||||
const show = reactive({
|
const show = reactive({
|
||||||
moment: false,
|
moment: false,
|
||||||
article: false,
|
article: false,
|
||||||
comment: false
|
comment: false,
|
||||||
|
delete: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const related = reactive<{ edit_to: any; comment_to: any; reply_to: any; repost_to: any }>({
|
const related = reactive<{
|
||||||
|
edit_to: any
|
||||||
|
comment_to: any
|
||||||
|
reply_to: any
|
||||||
|
repost_to: any
|
||||||
|
delete_to: any
|
||||||
|
}>({
|
||||||
edit_to: null,
|
edit_to: null,
|
||||||
comment_to: null,
|
comment_to: null,
|
||||||
reply_to: null,
|
reply_to: null,
|
||||||
repost_to: null
|
repost_to: null,
|
||||||
|
delete_to: null
|
||||||
})
|
})
|
||||||
|
|
||||||
return { show, related, done }
|
return { show, related, done }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container class="flex max-md:flex-col gap-3 overflow-auto max-h-[calc(100vh-64px)] no-scrollbar">
|
<v-container class="flex max-md:flex-col gap-3 overflow-auto max-h-[calc(100vh-64px)] no-scrollbar">
|
||||||
<div class="timeline flex-grow-1">
|
<div class="content flex-grow-1">
|
||||||
<v-card :loading="loading">
|
<v-card :loading="loading">
|
||||||
<article>
|
<article>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="aside sticky top-0 w-full h-fit md:max-w-[360px] md:min-w-[280px]">
|
<div class="aside sticky top-0 w-full h-fit w-full md:max-w-[380px] md:min-w-[360px]">
|
||||||
<v-card title="Comments">
|
<v-card title="Comments">
|
||||||
<div class="px-[1rem] pb-[0.825rem] mt-[-12px]">
|
<div class="px-[1rem] pb-[0.825rem] mt-[-12px]">
|
||||||
<comment-list
|
<comment-list
|
||||||
|
Loading…
Reference in New Issue
Block a user