@@ -5,6 +5,7 @@ import {
|
||||
toAdminPostStoredTitle
|
||||
} from '../../lib/admin-post-title.js'
|
||||
import { normalizeMarkdownContent } from '../../lib/markdown-content-normalizer.js'
|
||||
import { DEFAULT_POST_TAG_LIMIT, normalizePostTagLimit } from '../../lib/post-tag-limit.js'
|
||||
|
||||
const props = defineProps({
|
||||
initialPost: {
|
||||
@@ -83,6 +84,9 @@ const publishModalExpandedSection = ref(null)
|
||||
const { data: adminTags } = useFetch('/admin/api/tags', {
|
||||
default: () => []
|
||||
})
|
||||
const { data: siteSettings } = useFetch('/admin/api/settings', {
|
||||
default: () => ({ postTagLimit: DEFAULT_POST_TAG_LIMIT })
|
||||
})
|
||||
|
||||
const defaultTagColor = '#15171a'
|
||||
/** @type {number} 한국어 본문 예상 읽기 속도(분당 공백 제외 문자 수) */
|
||||
@@ -459,6 +463,10 @@ const selectedTags = computed(() => parseTags(form.tagsText))
|
||||
|
||||
const selectedTagKeys = computed(() => new Set(selectedTags.value.map((tag) => tag.toLowerCase())))
|
||||
|
||||
const postTagLimit = computed(() => normalizePostTagLimit(siteSettings.value?.postTagLimit))
|
||||
|
||||
const canAddMoreTags = computed(() => selectedTags.value.length < postTagLimit.value)
|
||||
|
||||
const availableAdminTags = computed(() => Array.isArray(adminTags.value) ? adminTags.value : [])
|
||||
|
||||
const managedTagOptions = computed(() => availableAdminTags.value.filter((tag) => tag.tagType === 'managed'))
|
||||
@@ -469,6 +477,9 @@ const tagSuggestionOptions = computed(() => {
|
||||
|
||||
return sourceTags
|
||||
.filter((tag) => {
|
||||
if (!canAddMoreTags.value) {
|
||||
return false
|
||||
}
|
||||
if (!tag?.slug || selectedTagKeys.value.has(tag.slug.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
@@ -794,6 +805,12 @@ const addTagToken = (value) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (!selectedTagKeys.value.has(nextTag.toLowerCase()) && !canAddMoreTags.value) {
|
||||
tagInput.value = ''
|
||||
isTagSuggestionsOpen.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const nextTags = [...selectedTags.value]
|
||||
if (!selectedTagKeys.value.has(nextTag.toLowerCase())) {
|
||||
nextTags.push(nextTag)
|
||||
@@ -872,6 +889,11 @@ const getTagSuggestionMeta = (tag) => {
|
||||
* @returns {void}
|
||||
*/
|
||||
const openTagSuggestions = () => {
|
||||
if (!canAddMoreTags.value) {
|
||||
isTagSuggestionsOpen.value = false
|
||||
return
|
||||
}
|
||||
|
||||
isTagSuggestionsOpen.value = true
|
||||
activeTagSuggestionIndex.value = 0
|
||||
tagInputRef.value?.focus()
|
||||
@@ -882,6 +904,11 @@ const openTagSuggestions = () => {
|
||||
* @returns {void}
|
||||
*/
|
||||
const toggleTagSuggestions = () => {
|
||||
if (!canAddMoreTags.value) {
|
||||
isTagSuggestionsOpen.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (isTagSuggestionsOpen.value) {
|
||||
isTagSuggestionsOpen.value = false
|
||||
return
|
||||
@@ -1829,7 +1856,10 @@ defineExpose({
|
||||
<div class="admin-post-form__field grid gap-1 text-sm">
|
||||
<span class="admin-post-form__label h-[22px] font-bold text-[#15171a]">Tags</span>
|
||||
<div class="admin-post-form__tag-combobox relative">
|
||||
<div class="admin-post-form__tag-editor flex min-h-[38px] w-full flex-wrap items-center gap-2 rounded border border-[#e3e6e8] bg-[#eff1f2] px-3 py-1 transition-colors hover:border-[#c8ced3] focus-within:border-[#8e9cac]">
|
||||
<div
|
||||
class="admin-post-form__tag-editor flex min-h-[38px] w-full flex-wrap items-center gap-2 rounded border border-[#e3e6e8] bg-[#eff1f2] px-3 py-1 transition-colors hover:border-[#c8ced3] focus-within:border-[#8e9cac]"
|
||||
:class="!canAddMoreTags ? 'opacity-85' : ''"
|
||||
>
|
||||
<span
|
||||
v-for="tag in selectedTags"
|
||||
:key="tag"
|
||||
@@ -1853,7 +1883,8 @@ defineExpose({
|
||||
v-model="tagInput"
|
||||
class="admin-post-form__tag-input min-w-0 flex-1 border-0 bg-transparent p-0 text-sm text-black outline-none placeholder:text-[#8e9cac]"
|
||||
type="text"
|
||||
placeholder="태그 입력"
|
||||
:placeholder="canAddMoreTags ? '태그 입력' : `최대 ${postTagLimit}개까지 선택됨`"
|
||||
:disabled="!canAddMoreTags"
|
||||
role="combobox"
|
||||
:aria-expanded="hasTagSuggestions"
|
||||
aria-autocomplete="list"
|
||||
@@ -1868,6 +1899,7 @@ defineExpose({
|
||||
class="admin-post-form__tag-dropdown-trigger ml-auto inline-flex size-8 shrink-0 items-center justify-center rounded text-[#15171a] transition-colors hover:bg-[#e3e6e8] focus-visible:outline focus-visible:ring-2 focus-visible:ring-[#8e9cac]"
|
||||
type="button"
|
||||
:aria-expanded="hasTagSuggestions"
|
||||
:disabled="!canAddMoreTags"
|
||||
aria-label="메인 태그 목록 열기"
|
||||
@mousedown.prevent="toggleTagSuggestions"
|
||||
>
|
||||
@@ -1877,6 +1909,9 @@ defineExpose({
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-[#8e9cac]">
|
||||
{{ selectedTags.length }} / {{ postTagLimit }}개 선택됨
|
||||
</p>
|
||||
<div
|
||||
v-if="hasTagSuggestions"
|
||||
class="admin-post-form__tag-suggestions absolute left-0 right-0 top-full z-40 mt-1 max-h-64 overflow-y-auto rounded-lg border border-[#d7dce0] bg-white py-1 text-sm shadow-[0_18px_50px_rgba(15,23,42,0.14)]"
|
||||
|
||||
Reference in New Issue
Block a user