forked from Mirrors/elk
feat: support showing publish failed messages (#1209)
This commit is contained in:
parent
0b2b9a713b
commit
85e163a0ad
7 changed files with 93 additions and 17 deletions
23
components/publish/PublishErrMessage.vue
Normal file
23
components/publish/PublishErrMessage.vue
Normal file
|
@ -0,0 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
describedBy: string
|
||||
}>()
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
role="alert"
|
||||
:aria-describedby="describedBy"
|
||||
flex="~ col"
|
||||
gap-1 text-sm
|
||||
pt-1 ps-2 pe-1 pb-2
|
||||
text-red-600 dark:text-red-400
|
||||
border="~ base rounded red-600 dark:red-400"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
|
@ -34,7 +34,7 @@ const {
|
|||
dropZoneRef,
|
||||
} = $(useUploadMediaAttachment($$(draft)))
|
||||
|
||||
let { shouldExpanded, isExpanded, isSending, isPublishDisabled, publishDraft } = $(usePublish(
|
||||
let { shouldExpanded, isExpanded, isSending, isPublishDisabled, publishDraft, failedMessages } = $(usePublish(
|
||||
{
|
||||
draftState,
|
||||
...$$({ expanded, isUploading, initialDraft: initial }),
|
||||
|
@ -160,6 +160,29 @@ defineExpose({
|
|||
>
|
||||
</div>
|
||||
|
||||
<PublishErrMessage v-if="failedMessages.length > 0" described-by="publish-failed">
|
||||
<head id="publish-failed" flex justify-between>
|
||||
<div flex items-center gap-x-2 font-bold>
|
||||
<div aria-hidden="true" i-ri:error-warning-fill />
|
||||
<p>{{ $t('state.publish_failed') }}</p>
|
||||
</div>
|
||||
<CommonTooltip placement="bottom" :content="$t('action.clear_publish_failed')">
|
||||
<button
|
||||
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="$t('action.clear_publish_failed')"
|
||||
@click="failedMessages = []"
|
||||
>
|
||||
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||
</button>
|
||||
</CommonTooltip>
|
||||
</head>
|
||||
<ol ps-2 sm:ps-1>
|
||||
<li v-for="(error, i) in failedMessages" :key="i" flex="~ col sm:row" gap-y-1 sm:gap-x-2>
|
||||
<strong>{{ i + 1 }}.</strong>
|
||||
<span>{{ error }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</PublishErrMessage>
|
||||
|
||||
<div relative flex-1 flex flex-col>
|
||||
<EditorContent
|
||||
:editor="editor"
|
||||
|
@ -174,15 +197,9 @@ defineExpose({
|
|||
</div>
|
||||
{{ $t('state.uploading') }}
|
||||
</div>
|
||||
<div
|
||||
<PublishErrMessage
|
||||
v-else-if="failedAttachments.length > 0"
|
||||
role="alert"
|
||||
:aria-describedby="isExceedingAttachmentLimit ? 'upload-failed uploads-per-post' : 'upload-failed'"
|
||||
flex="~ col"
|
||||
gap-1 text-sm
|
||||
pt-1 ps-2 pe-1 pb-2
|
||||
text-red-600 dark:text-red-400
|
||||
border="~ base rounded red-600 dark:red-400"
|
||||
:described-by="isExceedingAttachmentLimit ? 'upload-failed uploads-per-post' : 'upload-failed'"
|
||||
>
|
||||
<head id="upload-failed" flex justify-between>
|
||||
<div flex items-center gap-x-2 font-bold>
|
||||
|
@ -191,10 +208,8 @@ defineExpose({
|
|||
</div>
|
||||
<CommonTooltip placement="bottom" :content="$t('action.clear_upload_failed')">
|
||||
<button
|
||||
flex rounded-4 p1
|
||||
hover:bg-active cursor-pointer transition-100
|
||||
:aria-label="$t('action.clear_upload_failed')"
|
||||
@click="failedAttachments = []"
|
||||
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100
|
||||
:aria-label="$t('action.clear_upload_failed')" @click="failedAttachments = []"
|
||||
>
|
||||
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||
</button>
|
||||
|
@ -209,7 +224,7 @@ defineExpose({
|
|||
<span>{{ error[0] }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</PublishErrMessage>
|
||||
|
||||
<div v-if="draft.attachments.length" flex="~ col gap-2" overflow-auto>
|
||||
<PublishAttachment
|
||||
|
@ -291,7 +306,18 @@ defineExpose({
|
|||
</template>
|
||||
</PublishVisibilityPicker>
|
||||
|
||||
<CommonTooltip id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!isPublishDisabled">
|
||||
<CommonTooltip v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top" :content="$t('tooltip.publish_failed')">
|
||||
<button
|
||||
btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit aria-describedby="publish-failed-tooltip"
|
||||
>
|
||||
<span block>
|
||||
<div block i-carbon:face-dizzy-filled />
|
||||
</span>
|
||||
<span>{{ $t('state.publish_failed') }}</span>
|
||||
</button>
|
||||
</CommonTooltip>
|
||||
|
||||
<CommonTooltip v-else id="publish-tooltip" placement="top" :content="$t('tooltip.add_publishable_content')" :disabled="!isPublishDisabled">
|
||||
<button
|
||||
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center
|
||||
md:w-fit
|
||||
|
@ -303,6 +329,9 @@ defineExpose({
|
|||
<span v-if="isSending" block animate-spin preserve-3d>
|
||||
<div block i-ri:loader-2-fill />
|
||||
</span>
|
||||
<span v-if="failedMessages.length" block>
|
||||
<div block i-carbon:face-dizzy-filled />
|
||||
</span>
|
||||
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>
|
||||
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</span>
|
||||
<span v-else>{{ !isSending ? $t('action.publish') : $t('state.publishing') }}</span>
|
||||
|
|
|
@ -16,12 +16,18 @@ export const usePublish = (options: {
|
|||
|
||||
let isSending = $ref(false)
|
||||
const isExpanded = $ref(false)
|
||||
const failedMessages = $ref<string[]>([])
|
||||
|
||||
const shouldExpanded = $computed(() => expanded || isExpanded || !isEmpty)
|
||||
const isPublishDisabled = $computed(() => {
|
||||
return isEmpty || isUploading || isSending || (draft.attachments.length === 0 && !draft.params.status)
|
||||
return isEmpty || isUploading || isSending || (draft.attachments.length === 0 && !draft.params.status) || failedMessages.length > 0
|
||||
})
|
||||
|
||||
watch(() => draft, () => {
|
||||
if (failedMessages.length > 0)
|
||||
failedMessages.length = 0
|
||||
}, { deep: true })
|
||||
|
||||
async function publishDraft() {
|
||||
let content = htmlToText(draft.params.status || '')
|
||||
if (draft.mentions?.length)
|
||||
|
@ -63,6 +69,7 @@ export const usePublish = (options: {
|
|||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
failedMessages.push((err as Error).message)
|
||||
}
|
||||
finally {
|
||||
isSending = false
|
||||
|
@ -74,6 +81,7 @@ export const usePublish = (options: {
|
|||
isExpanded,
|
||||
shouldExpanded,
|
||||
isPublishDisabled,
|
||||
failedMessages,
|
||||
|
||||
publishDraft,
|
||||
})
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"boost": "Boost",
|
||||
"boost_count": "{0}",
|
||||
"boosted": "Boosted",
|
||||
"clear_publish_failed": "Clear publish errors",
|
||||
"clear_upload_failed": "Clear file upload errors",
|
||||
"close": "Close",
|
||||
"compose": "Compose",
|
||||
|
@ -400,6 +401,7 @@
|
|||
"edited": "(Edited)",
|
||||
"editing": "Editing",
|
||||
"loading": "Loading...",
|
||||
"publish_failed": "Publish failed",
|
||||
"publishing": "Publishing",
|
||||
"upload_failed": "Upload failed",
|
||||
"uploading": "Uploading..."
|
||||
|
@ -499,6 +501,7 @@
|
|||
"explore_links_intro": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||
"explore_posts_intro": "These posts from this and other servers in the decentralized network are gaining traction on this server right now.",
|
||||
"explore_tags_intro": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
||||
"toggle_code_block": "Toggle code block"
|
||||
},
|
||||
"user": {
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
"bookmarked": "已收藏",
|
||||
"boost": "转发",
|
||||
"boosted": "已转发",
|
||||
"clear_upload_failed": "清除上传失败",
|
||||
"clear_publish_failed": "清除发布失败信息",
|
||||
"clear_upload_failed": "清除上传失败信息",
|
||||
"close": "关闭",
|
||||
"compose": "撰写",
|
||||
"confirm": "确认",
|
||||
|
@ -374,6 +375,8 @@
|
|||
"edited": "(已编辑)",
|
||||
"editing": "编辑中",
|
||||
"loading": "加载中...",
|
||||
"publish_failed": "发布失败",
|
||||
"publishing": "发布中...",
|
||||
"upload_failed": "上传失败",
|
||||
"uploading": "上传中..."
|
||||
},
|
||||
|
@ -472,6 +475,7 @@
|
|||
"explore_links_intro": "这些新闻故事正被本站和分布式网络上其他站点的用户谈论。",
|
||||
"explore_posts_intro": "来自本站和分布式网络上其他站点的这些嘟文正在本站引起关注。",
|
||||
"explore_tags_intro": "这些标签正在本站和分布式网络上其他站点的用户中引起关注。",
|
||||
"publish_failed": "关闭编辑器上方的错误信息以重新发布帖文。",
|
||||
"toggle_code_block": "切换代码块"
|
||||
},
|
||||
"user": {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
:root {
|
||||
--c-border: #eee;
|
||||
--c-border-dark: #dccfcf;
|
||||
--c-danger: #FF3C1B;
|
||||
--c-danger-active: #B50900;
|
||||
|
||||
--rgb-bg-base: 250, 250, 250;
|
||||
|
||||
|
@ -32,6 +34,8 @@
|
|||
--c-primary-active: var(--c-dark-primary-active);
|
||||
--c-primary-light: var(--c-dark-primary-light);
|
||||
--c-primary-fade: var(--c-dark-primary-fade);
|
||||
--c-danger: #FF2810;
|
||||
--c-danger-active: #E02F00;
|
||||
|
||||
--c-border: #222;
|
||||
--c-border-dark: #545251;
|
||||
|
|
|
@ -41,6 +41,7 @@ export default defineConfig({
|
|||
'btn-outline': 'btn-base px-4 py-2 rounded text-$c-primary border border-$c-primary hover:bg-$c-primary hover:text-inverted',
|
||||
'btn-text': 'btn-base px-4 py-2 text-$c-primary hover:text-$c-primary-active',
|
||||
'btn-action-icon': 'btn-base hover:bg-active rounded-full h9 w9 flex items-center justify-center disabled:bg-transparent disabled:text-$c-text-secondary',
|
||||
'btn-danger': 'btn-base px-4 py-2 rounded text-white bg-$c-danger hover:bg-$c-danger-active',
|
||||
|
||||
// input
|
||||
'input-base-focus': 'focus:outline-none focus:border-$c-primary',
|
||||
|
@ -95,6 +96,10 @@ export default defineConfig({
|
|||
DEFAULT: 'var(--c-primary)',
|
||||
active: 'var(--c-primary-active)',
|
||||
},
|
||||
danger: {
|
||||
DEFAULT: 'var(--c-danger)',
|
||||
active: 'var(--c-danger-active)',
|
||||
},
|
||||
},
|
||||
},
|
||||
rules: [
|
||||
|
|
Loading…
Reference in a new issue