✨ Post & Comment Editors
This commit is contained in:
parent
f9438b4d89
commit
3300e46e88
@ -25,15 +25,15 @@ func createArticle(c *fiber.Ctx) error {
|
||||
user := c.Locals("principal").(models.Account)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias"`
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
RealmID *uint `json:"realm_id"`
|
||||
Alias string `json:"alias" form:"alias"`
|
||||
Title string `json:"title" form:"title" validate:"required"`
|
||||
Description string `json:"description" form:"description"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
RealmID *uint `json:"realm_id" form:"realm_id"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
@ -78,14 +78,14 @@ func editArticle(c *fiber.Ctx) error {
|
||||
id, _ := c.ParamsInt("articleId", 0)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias" validate:"required"`
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
Alias string `json:"alias" form:"alias" validate:"required"`
|
||||
Title string `json:"title" form:"title" validate:"required"`
|
||||
Description string `json:"description" form:"description"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
|
@ -56,13 +56,13 @@ func createComment(c *fiber.Ctx) error {
|
||||
user := c.Locals("principal").(models.Account)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
ReplyTo uint `json:"reply_to"`
|
||||
Alias string `json:"alias" form:"alias"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
ReplyTo uint `json:"reply_to" form:"reply_to"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
@ -133,12 +133,12 @@ func editComment(c *fiber.Ctx) error {
|
||||
id, _ := c.ParamsInt("commentId", 0)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
Alias string `json:"alias" form:"alias" validate:"required"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
|
@ -25,14 +25,14 @@ func createMoment(c *fiber.Ctx) error {
|
||||
user := c.Locals("principal").(models.Account)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
RealmID *uint `json:"realm_id"`
|
||||
RepostTo uint `json:"repost_to"`
|
||||
Alias string `json:"alias" form:"alias"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
RealmID *uint `json:"realm_id" form:"realm_id"`
|
||||
RepostTo uint `json:"repost_to" form:"repost_to"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
@ -88,12 +88,12 @@ func editMoment(c *fiber.Ctx) error {
|
||||
id, _ := c.ParamsInt("momentId", 0)
|
||||
|
||||
var data struct {
|
||||
Alias string `json:"alias" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags"`
|
||||
Categories []models.Category `json:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments"`
|
||||
Alias string `json:"alias" form:"alias" validate:"required"`
|
||||
Content string `json:"content" form:"content" validate:"required"`
|
||||
PublishedAt *time.Time `json:"published_at" form:"published_at"`
|
||||
Hashtags []models.Tag `json:"hashtags" form:"hashtags"`
|
||||
Categories []models.Category `json:"categories" form:"categories"`
|
||||
Attachments []models.Attachment `json:"attachments" form:"attachments"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
|
@ -97,8 +97,8 @@ func reactPost(c *fiber.Ctx) error {
|
||||
user := c.Locals("principal").(models.Account)
|
||||
|
||||
var data struct {
|
||||
Symbol string `json:"symbol" validate:"required"`
|
||||
Attitude models.ReactionAttitude `json:"attitude" validate:"required"`
|
||||
Symbol string `json:"symbol" form:"symbol" validate:"required"`
|
||||
Attitude models.ReactionAttitude `json:"attitude" form:"attitude" validate:"required"`
|
||||
}
|
||||
|
||||
if err := BindAndValidate(c, &data); err != nil {
|
||||
|
@ -80,7 +80,7 @@ func NewServer() {
|
||||
posts.Post("/:postId/comments", authMiddleware, createComment)
|
||||
}
|
||||
|
||||
moments := api.Group("/moments").Name("Moments API")
|
||||
moments := api.Group("/p/moments").Name("Moments API")
|
||||
{
|
||||
moments.Post("/", authMiddleware, createMoment)
|
||||
moments.Put("/:momentId", authMiddleware, editMoment)
|
||||
|
@ -77,6 +77,7 @@ func (v *PostTypeContext) GetViaAlias(alias string) (models.Feed, error) {
|
||||
table := viper.GetString("database.prefix") + v.TableName
|
||||
if err := v.Tx.
|
||||
Table(table).
|
||||
Select("*, ? as model_type", v.ColumnName).
|
||||
Where("alias = ?", alias).
|
||||
First(&item).Error; err != nil {
|
||||
return item, err
|
||||
|
@ -1,5 +1,6 @@
|
||||
html, body, #app, .v-application {
|
||||
overflow: auto !important;
|
||||
font-family: "Roboto Sans", ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
.no-scrollbar {
|
||||
|
@ -5,20 +5,28 @@
|
||||
|
||||
<div v-else class="flex flex-col gap-2 mt-3">
|
||||
<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>
|
||||
|
||||
<v-divider class="mt-2 mb-3 border-opacity-50 mx-[-1rem]" />
|
||||
|
||||
<v-btn block prepend-icon="mdi-pencil" variant="plain" @click="leaveComment">Leave your comment</v-btn>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { request } from "@/scripts/request"
|
||||
import { reactive, ref } from "vue"
|
||||
import { reactive, ref, watch } from "vue"
|
||||
import { useEditor } from "@/stores/editor"
|
||||
import PostItem from "@/components/posts/PostItem.vue"
|
||||
|
||||
const editor = useEditor()
|
||||
|
||||
const props = defineProps<{
|
||||
comments: any[]
|
||||
model: any
|
||||
alias: any
|
||||
item: any
|
||||
}>()
|
||||
const emits = defineEmits(["update:comments"])
|
||||
|
||||
@ -50,8 +58,20 @@ async function readComments() {
|
||||
readComments()
|
||||
|
||||
function updateItem(idx: number, data: any) {
|
||||
const comments = JSON.parse(JSON.stringify(props.comments));
|
||||
comments[idx] = data;
|
||||
emits("update:comments", comments);
|
||||
const comments = JSON.parse(JSON.stringify(props.comments))
|
||||
comments[idx] = data
|
||||
emits("update:comments", comments)
|
||||
}
|
||||
|
||||
watch(editor, (val) => {
|
||||
if (val.done) {
|
||||
readComments().then(() => (val.done = false))
|
||||
}
|
||||
})
|
||||
|
||||
function leaveComment() {
|
||||
editor.related.comment_to = props.item
|
||||
editor.related.comment_to.model_type += "s"
|
||||
editor.show.comment = true
|
||||
}
|
||||
</script>
|
||||
|
@ -12,9 +12,7 @@
|
||||
|
||||
<v-menu v-if="!props.readonly" location="bottom center">
|
||||
<template v-slot:activator="{ props: binding }">
|
||||
<v-chip v-bind="binding" :size="props.size" prepend-icon="mdi-emoticon-plus">
|
||||
React
|
||||
</v-chip>
|
||||
<v-chip v-bind="binding" :size="props.size" prepend-icon="mdi-emoticon-plus"> React </v-chip>
|
||||
</template>
|
||||
|
||||
<v-list density="compact" lines="one">
|
||||
@ -30,52 +28,53 @@
|
||||
<v-snackbar v-model="status.added" :timeout="3000">Your react has been added into post.</v-snackbar>
|
||||
<v-snackbar v-model="status.removed" :timeout="3000">Your react has been removed from post.</v-snackbar>
|
||||
|
||||
<!-- @vue-ignore -->
|
||||
<v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { request } from "@/scripts/request";
|
||||
import { getAtk } from "@/stores/userinfo";
|
||||
import { reactive, ref } from "vue";
|
||||
import { request } from "@/scripts/request"
|
||||
import { getAtk } from "@/stores/userinfo"
|
||||
import { reactive, ref } from "vue"
|
||||
|
||||
const emits = defineEmits(["update"]);
|
||||
const emits = defineEmits(["update"])
|
||||
const props = defineProps<{
|
||||
size?: string,
|
||||
readonly?: boolean,
|
||||
model: any,
|
||||
item: any,
|
||||
size?: string
|
||||
readonly?: boolean
|
||||
model: any
|
||||
item: any
|
||||
reactions: { [id: string]: number }
|
||||
}>();
|
||||
}>()
|
||||
|
||||
const emojis: { [id: string]: { icon: string, attitude: number } } = {
|
||||
const emojis: { [id: string]: { icon: string; attitude: number } } = {
|
||||
thumb_up: { icon: "👍", attitude: 1 },
|
||||
clap: { icon: "👏", attitude: 1 }
|
||||
};
|
||||
|
||||
function pickColor(): string {
|
||||
const colors = ["blue", "green", "purple"];
|
||||
const randomIndex = Math.floor(Math.random() * colors.length);
|
||||
return colors[randomIndex];
|
||||
}
|
||||
|
||||
const status = reactive({ added: false, removed: false });
|
||||
const error = ref<string | null>(null);
|
||||
function pickColor(): string {
|
||||
const colors = ["blue", "green", "purple"]
|
||||
const randomIndex = Math.floor(Math.random() * colors.length)
|
||||
return colors[randomIndex]
|
||||
}
|
||||
|
||||
const status = reactive({ added: false, removed: false })
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
async function reactPost(symbol: string, attitude: number) {
|
||||
const res = await request(`/api/p/${props.model}/${props.item?.id}/react`, {
|
||||
method: "POST",
|
||||
headers: { "Authorization": `Bearer ${getAtk()}`, "Content-Type": "application/json" },
|
||||
headers: { Authorization: `Bearer ${getAtk()}`, "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ symbol, attitude })
|
||||
});
|
||||
})
|
||||
if (res.status === 201) {
|
||||
status.added = true;
|
||||
emits("update", symbol, 1);
|
||||
status.added = true
|
||||
emits("update", symbol, 1)
|
||||
} else if (res.status === 204) {
|
||||
status.removed = true;
|
||||
emits("update", symbol, -1);
|
||||
status.removed = true
|
||||
emits("update", symbol, -1)
|
||||
} else {
|
||||
error.value = await res.text();
|
||||
error.value = await res.text()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
65
pkg/views/src/components/publish/CommentEditor.vue
Normal file
65
pkg/views/src/components/publish/CommentEditor.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<v-card title="Leave your comment" :loading="loading">
|
||||
<v-form @submit.prevent="postComment">
|
||||
<v-card-text>
|
||||
<v-textarea required hide-details name="content" variant="outlined" label="What do you want to say?" />
|
||||
|
||||
<p class="px-2 mt-1 text-body-2 opacity-80">Your comment will leave below {{ postIdentifier }}</p>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn type="reset" color="grey-darken-3" @click="editor.show.comment = false">Cancel</v-btn>
|
||||
<v-btn type="submit" :disabled="loading">Publish</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
|
||||
<v-snackbar v-model="success" :timeout="3000">Your comment has been published.</v-snackbar>
|
||||
|
||||
<!-- @vue-ignore -->
|
||||
<v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { request } from "@/scripts/request"
|
||||
import { useEditor } from "@/stores/editor"
|
||||
import { getAtk } from "@/stores/userinfo"
|
||||
import { computed, ref } from "vue"
|
||||
|
||||
const editor = useEditor()
|
||||
|
||||
const target = computed<any>(() => editor.related.comment_to)
|
||||
const postIdentifier = computed(() => {
|
||||
if (editor.related.comment_to?.title) {
|
||||
return `${editor.related.comment_to.title}`
|
||||
} else {
|
||||
return `#${editor.related.comment_to?.alias}`
|
||||
}
|
||||
})
|
||||
|
||||
const error = ref<string | null>(null)
|
||||
const success = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
async function postComment(evt: SubmitEvent) {
|
||||
const data = new FormData(evt.target as HTMLFormElement)
|
||||
if (!data.has("content")) return
|
||||
|
||||
loading.value = true
|
||||
const res = await request(`/api/p/${target.value?.model_type}/${target.value?.alias}/comments`, {
|
||||
method: "POST",
|
||||
headers: { Authorization: `Bearer ${getAtk()}` },
|
||||
body: data
|
||||
})
|
||||
if (res.status === 200) {
|
||||
success.value = true
|
||||
} else {
|
||||
error.value = await res.text()
|
||||
}
|
||||
loading.value = false
|
||||
editor.show.comment = false
|
||||
editor.done = true
|
||||
}
|
||||
</script>
|
123
pkg/views/src/components/publish/MomentEditor.vue
Normal file
123
pkg/views/src/components/publish/MomentEditor.vue
Normal file
@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<v-card title="Record a moment" :loading="loading">
|
||||
<v-form @submit.prevent="postMoment">
|
||||
<v-card-text>
|
||||
<v-textarea required hide-details name="content" variant="outlined" label="What's happened?!" />
|
||||
|
||||
<div class="flex mt-1">
|
||||
<v-tooltip text="Planned publish" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
type="button"
|
||||
variant="text"
|
||||
icon="mdi-calendar"
|
||||
size="small"
|
||||
@click="dialogs.plan = true"
|
||||
/>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip text="Categories" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
type="button"
|
||||
variant="text"
|
||||
icon="mdi-shape"
|
||||
size="small"
|
||||
@click="dialogs.categories = true"
|
||||
/>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip text="Media" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
type="button"
|
||||
variant="text"
|
||||
icon="mdi-camera"
|
||||
size="small"
|
||||
@click="dialogs.media = true"
|
||||
/>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn type="reset" color="grey-darken-3" @click="editor.show.moment = false">Cancel</v-btn>
|
||||
<v-btn type="submit" :disabled="loading">Publish</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
|
||||
<v-dialog eager v-model="dialogs.plan" class="max-w-[540px]">
|
||||
<v-card title="Plan your publish">
|
||||
<template #text>
|
||||
<v-text-field
|
||||
v-model="extras.publishedAt"
|
||||
class="mt-2"
|
||||
label="Publish date"
|
||||
hint="Your post will hidden for public before this time. Leave blank will publish immediately"
|
||||
variant="outlined"
|
||||
type="datetime-local"
|
||||
clearable
|
||||
/>
|
||||
</template>
|
||||
<template #actions>
|
||||
<v-btn class="ms-auto" text="Ok" @click="dialogs.plan = false"></v-btn>
|
||||
</template>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-snackbar v-model="success" :timeout="3000">Your post has been published.</v-snackbar>
|
||||
|
||||
<!-- @vue-ignore -->
|
||||
<v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { request } from "@/scripts/request"
|
||||
import { useEditor } from "@/stores/editor"
|
||||
import { getAtk } from "@/stores/userinfo"
|
||||
import { reactive, ref } from "vue"
|
||||
|
||||
const editor = useEditor()
|
||||
|
||||
const dialogs = reactive({
|
||||
plan: false,
|
||||
categories: false,
|
||||
media: false
|
||||
})
|
||||
|
||||
const extras = reactive({
|
||||
publishedAt: null
|
||||
})
|
||||
|
||||
const error = ref<string | null>(null)
|
||||
const success = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
async function postMoment(evt: SubmitEvent) {
|
||||
const data = new FormData(evt.target as HTMLFormElement)
|
||||
if (!data.has("content")) return
|
||||
if (!extras.publishedAt) data.set("published_at", new Date().toISOString())
|
||||
else data.set("published_at", extras.publishedAt)
|
||||
|
||||
loading.value = true
|
||||
const res = await request("/api/p/moments", {
|
||||
method: "POST",
|
||||
headers: { Authorization: `Bearer ${getAtk()}` },
|
||||
body: data
|
||||
})
|
||||
if (res.status === 200) {
|
||||
success.value = true
|
||||
} else {
|
||||
error.value = await res.text()
|
||||
}
|
||||
loading.value = false
|
||||
editor.show.moment = false
|
||||
}
|
||||
</script>
|
16
pkg/views/src/components/publish/PostAction.vue
Normal file
16
pkg/views/src/components/publish/PostAction.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<v-dialog v-model="editor.show.moment" class="max-w-[540px]">
|
||||
<moment-editor />
|
||||
</v-dialog>
|
||||
<v-dialog v-model="editor.show.comment" class="max-w-[540px]">
|
||||
<comment-editor />
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useEditor } from "@/stores/editor"
|
||||
import MomentEditor from "@/components/publish/MomentEditor.vue"
|
||||
import CommentEditor from "@/components/publish/CommentEditor.vue";
|
||||
|
||||
const editor = useEditor()
|
||||
</script>
|
@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<v-dialog v-model="editor.show.moment" class="max-w-[540px]">
|
||||
<v-card title="Record a moment">
|
||||
<v-form>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
required
|
||||
hide-details
|
||||
variant="outlined"
|
||||
label="What's happened?!"
|
||||
/>
|
||||
|
||||
<div class="flex mt-1">
|
||||
<v-tooltip text="Planned publish" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn v-bind="props" type="button" variant="text" icon="mdi-calendar" size="small" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip text="Categories" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn v-bind="props" type="button" variant="text" icon="mdi-shape" size="small" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip text="Media" location="start">
|
||||
<template #activator="{ props }">
|
||||
<v-btn v-bind="props" type="button" variant="text" icon="mdi-camera" size="small" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<v-btn type="reset" color="grey-darken-3" @click="editor.show.moment = false">Cancel</v-btn>
|
||||
<v-btn type="submit" @click.prevent>Publish</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useEditor } from "@/stores/editor";
|
||||
|
||||
const editor = useEditor();
|
||||
</script>
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<v-navigation-drawer v-model="drawerOpen" color="grey-lighten-5" floating>
|
||||
<v-list density="compact" nav>
|
||||
</v-list>
|
||||
<v-list density="compact" nav> </v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<v-app-bar height="64" color="primary" scroll-behavior="elevate" flat>
|
||||
@ -35,14 +34,7 @@
|
||||
transition="scroll-y-reverse-transition"
|
||||
>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-fab
|
||||
v-bind="props"
|
||||
class="editor-fab"
|
||||
icon="mdi-pencil"
|
||||
color="primary"
|
||||
size="64"
|
||||
appear
|
||||
/>
|
||||
<v-fab v-bind="props" class="editor-fab" icon="mdi-pencil" color="primary" size="64" appear />
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col items-center gap-4 mb-4">
|
||||
@ -51,23 +43,21 @@
|
||||
</div>
|
||||
</v-menu>
|
||||
|
||||
<post-editor />
|
||||
<post-action />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useEditor } from "@/stores/editor";
|
||||
import PostEditor from "@/components/publish/PostEditor.vue";
|
||||
import { ref } from "vue"
|
||||
import { useEditor } from "@/stores/editor"
|
||||
import PostAction from "@/components/publish/PostAction.vue"
|
||||
|
||||
const editor = useEditor();
|
||||
const navigationMenu = [
|
||||
{ name: "Explore", icon: "mdi-compass", to: "explore" }
|
||||
];
|
||||
const editor = useEditor()
|
||||
const navigationMenu = [{ name: "Explore", icon: "mdi-compass", to: "explore" }]
|
||||
|
||||
const drawerOpen = ref(true);
|
||||
const drawerOpen = ref(true)
|
||||
|
||||
function toggleDrawer() {
|
||||
drawerOpen.value = !drawerOpen.value;
|
||||
drawerOpen.value = !drawerOpen.value
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,11 +1,20 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { reactive, ref } from "vue";
|
||||
import { defineStore } from "pinia"
|
||||
import { reactive, ref } from "vue"
|
||||
|
||||
export const useEditor = defineStore("editor", () => {
|
||||
const done = ref(false)
|
||||
|
||||
const show = reactive({
|
||||
moment: false,
|
||||
article: false,
|
||||
});
|
||||
comment: false
|
||||
})
|
||||
|
||||
return { show };
|
||||
});
|
||||
const related = reactive<{ comment_to: any; reply_to: any; repost_to: any }>({
|
||||
comment_to: null,
|
||||
reply_to: null,
|
||||
repost_to: null
|
||||
})
|
||||
|
||||
return { show, related, done }
|
||||
})
|
||||
|
@ -30,7 +30,12 @@
|
||||
<div class="aside sticky top-0 w-full h-fit md:min-w-[280px]">
|
||||
<v-card title="Comments">
|
||||
<div class="px-[1rem] pb-[0.825rem] mt-[-12px]">
|
||||
<comment-list v-model:comments="comments" :model="route.params.postType" :alias="route.params.alias" />
|
||||
<comment-list
|
||||
v-model:comments="comments"
|
||||
:item="post"
|
||||
:model="route.params.postType"
|
||||
:alias="route.params.alias"
|
||||
/>
|
||||
</div>
|
||||
</v-card>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user