@tager/admin-blog 0.3.43 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/paths.d.ts +6 -14
- package/dist/constants/routes.d.ts +5 -5
- package/dist/dev/App.vue.d.ts +5 -0
- package/dist/dev/config.d.ts +2 -0
- package/dist/dev/env.d.ts +1 -0
- package/dist/dev/main.d.ts +3 -0
- package/dist/hooks/index.d.ts +4 -4
- package/dist/hooks/useFetchCategories.d.ts +3 -6
- package/dist/hooks/useFetchCategory.d.ts +7 -8
- package/dist/hooks/useFetchModuleConfig.d.ts +3 -6
- package/dist/hooks/useFetchPosts.d.ts +3 -6
- package/dist/index.mjs +2355 -0
- package/dist/locales/apply.d.ts +1 -0
- package/dist/locales/en.d.ts +92 -86
- package/dist/locales/ru.d.ts +3 -3
- package/dist/main.d.ts +3 -4
- package/dist/services/requests.d.ts +60 -59
- package/dist/style.css +1 -0
- package/dist/typings/common.d.ts +1 -1
- package/dist/typings/model.d.ts +106 -106
- package/dist/utils/common.d.ts +2 -2
- package/dist/utils/paths.d.ts +8 -0
- package/dist/views/Categories/CategoryForm/CategoryForm.helpers.d.ts +7 -7
- package/dist/views/Categories/CategoryForm/CategoryForm.vue.d.ts +53 -116
- package/dist/views/Categories/CategoryForm/index.d.ts +1 -1
- package/dist/views/Categories/CategoryList/CategoryList.helpers.d.ts +7 -7
- package/dist/views/Categories/CategoryList/CategoryList.vue.d.ts +26 -57
- package/dist/views/Categories/CategoryList/hooks/index.d.ts +1 -1
- package/dist/views/Categories/CategoryList/hooks/useAdvancedSearch.d.ts +19 -16
- package/dist/views/Categories/CategoryList/index.d.ts +1 -1
- package/dist/views/Posts/PostForm/PostForm.helpers.d.ts +32 -32
- package/dist/views/Posts/PostForm/PostForm.vue.d.ts +2768 -9398
- package/dist/views/Posts/PostForm/index.d.ts +1 -1
- package/dist/views/Posts/PostList/PostList.helpers.d.ts +8 -7
- package/dist/views/Posts/PostList/PostList.vue.d.ts +40 -78
- package/dist/views/Posts/PostList/hooks/index.d.ts +1 -1
- package/dist/views/Posts/PostList/hooks/useAdvancedSearch.d.ts +27 -24
- package/dist/views/Posts/PostList/index.d.ts +1 -1
- package/package.json +51 -49
- package/src/constants/paths.ts +0 -22
- package/src/constants/routes.ts +9 -9
- package/src/dev/App.vue +56 -0
- package/src/dev/config.ts +23 -0
- package/src/dev/env.ts +17 -0
- package/src/dev/main.ts +49 -0
- package/src/hooks/useFetchCategories.ts +2 -7
- package/src/hooks/useFetchCategory.ts +3 -6
- package/src/hooks/useFetchModuleConfig.ts +2 -7
- package/src/hooks/useFetchPosts.ts +4 -6
- package/src/locales/apply.ts +9 -0
- package/src/locales/en.ts +10 -4
- package/src/locales/ru.ts +11 -3
- package/src/main.ts +3 -8
- package/src/services/requests.ts +1 -0
- package/src/utils/paths.ts +23 -0
- package/src/views/Categories/CategoryForm/CategoryForm.vue +81 -65
- package/src/views/Categories/CategoryList/CategoryList.helpers.ts +1 -1
- package/src/views/Categories/CategoryList/CategoryList.vue +86 -58
- package/src/views/Categories/CategoryList/hooks/useAdvancedSearch.ts +9 -12
- package/src/views/Posts/PostForm/PostForm.vue +265 -225
- package/src/views/Posts/PostList/PostList.helpers.ts +27 -2
- package/src/views/Posts/PostList/PostList.vue +203 -192
- package/src/views/Posts/PostList/hooks/useAdvancedSearch.ts +22 -30
- package/CHANGELOG.md +0 -13
- package/dist/constants/menu.d.ts +0 -5
- package/dist/dev.d.ts +0 -1
- package/dist/index.esm.js +0 -5294
- package/dist/index.umd.js +0 -5321
- package/dist/router/index.d.ts +0 -4
- package/dist/views/Posts/PostForm/components/TabList/TabList.types.d.ts +0 -5
- package/dist/views/Posts/PostForm/components/TabList/index.d.ts +0 -2
- package/src/constants/menu.ts +0 -31
- package/src/dev.ts +0 -34
- package/src/router/index.ts +0 -40
- package/src/typings/sfc.d.ts +0 -12
- package/src/typings/shims-tsx.d.ts +0 -13
- package/src/typings/shims-vue.d.ts +0 -11
- package/src/typings/translate.d.ts +0 -10
- package/src/views/App.vue +0 -22
- package/src/views/Home.vue +0 -31
- package/src/views/Posts/PostForm/components/TabList/TabList.types.ts +0 -5
- package/src/views/Posts/PostForm/components/TabList/TabList.vue +0 -92
- package/src/views/Posts/PostForm/components/TabList/index.ts +0 -2
|
@@ -1,223 +1,242 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
:title="
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
:
|
|
2
|
+
<Page
|
|
3
|
+
:title="
|
|
4
|
+
isCreation ? $i18n.t('blog:createPost') : $i18n.t('blog:updatePost')
|
|
5
|
+
"
|
|
6
|
+
:is-content-loading="isContentLoading"
|
|
7
|
+
:header-buttons="headerButtonList"
|
|
8
|
+
:footer="{
|
|
7
9
|
backHref: postListUrl,
|
|
8
10
|
onSubmit: submitForm,
|
|
9
11
|
isSubmitting: isSubmitting,
|
|
10
|
-
}
|
|
12
|
+
}"
|
|
11
13
|
>
|
|
12
|
-
<template
|
|
13
|
-
<form novalidate @submit.prevent=
|
|
14
|
-
<tab-list
|
|
15
|
-
:tab-list='tabList'
|
|
16
|
-
:selected-tab-id='selectedTabId'
|
|
17
|
-
@tab:update='selectedTabId = $event.tabId'
|
|
18
|
-
/>
|
|
14
|
+
<template #content>
|
|
15
|
+
<form novalidate @submit.prevent="submitForm">
|
|
16
|
+
<TabList v-model:tab-id="selectedTabId" :tab-list="tabList" />
|
|
19
17
|
|
|
20
18
|
<template v-if="selectedTabId === 'common'">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
v-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
:
|
|
27
|
-
:
|
|
28
|
-
:error='errors.language'
|
|
19
|
+
<FormFieldSelect
|
|
20
|
+
v-if="isCreation && isLangSpecific"
|
|
21
|
+
v-model:value="values.language"
|
|
22
|
+
name="language"
|
|
23
|
+
:label="$i18n.t('blog:language')"
|
|
24
|
+
:options="languageOptionList"
|
|
25
|
+
:error="errors.language"
|
|
29
26
|
/>
|
|
30
27
|
|
|
31
|
-
<
|
|
32
|
-
v-model=
|
|
33
|
-
name=
|
|
34
|
-
:label="$t('blog:title')"
|
|
35
|
-
:error=
|
|
36
|
-
@input=
|
|
28
|
+
<FormField
|
|
29
|
+
v-model:value="values.title"
|
|
30
|
+
name="title"
|
|
31
|
+
:label="$i18n.t('blog:title')"
|
|
32
|
+
:error="errors.title"
|
|
33
|
+
@input="handleTitleChange"
|
|
37
34
|
/>
|
|
38
35
|
|
|
39
|
-
<
|
|
40
|
-
id=
|
|
41
|
-
v-model=
|
|
42
|
-
name=
|
|
43
|
-
:label="$t('blog:link')"
|
|
44
|
-
:url-template=
|
|
45
|
-
:error=
|
|
46
|
-
@change=
|
|
36
|
+
<FormFieldUrlAliasInput
|
|
37
|
+
id="urlAlias"
|
|
38
|
+
v-model:value="values.urlAlias"
|
|
39
|
+
name="urlAlias"
|
|
40
|
+
:label="$i18n.t('blog:link')"
|
|
41
|
+
:url-template="urlAliasTemplate"
|
|
42
|
+
:error="errors.urlAlias"
|
|
43
|
+
@change="handleAliasChange"
|
|
47
44
|
/>
|
|
48
45
|
|
|
49
|
-
<div class=
|
|
50
|
-
<div class=
|
|
51
|
-
<
|
|
52
|
-
v-model=
|
|
53
|
-
name=
|
|
54
|
-
:error=
|
|
55
|
-
:label="$t('blog:status')"
|
|
56
|
-
:no-options-message="$t('blog:noTemplates')"
|
|
57
|
-
:options=
|
|
46
|
+
<div class="status">
|
|
47
|
+
<div class="status-value">
|
|
48
|
+
<FormFieldSelect
|
|
49
|
+
v-model:value="values.status"
|
|
50
|
+
name="status"
|
|
51
|
+
:error="errors.status"
|
|
52
|
+
:label="$i18n.t('blog:status')"
|
|
53
|
+
:no-options-message="$i18n.t('blog:noTemplates')"
|
|
54
|
+
:options="statusOptions"
|
|
58
55
|
/>
|
|
59
56
|
</div>
|
|
60
|
-
<div
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
<div
|
|
58
|
+
v-if="
|
|
59
|
+
values.status.value === 'PUBLISHED' ||
|
|
60
|
+
values.status.value === 'DRAFT'
|
|
61
|
+
"
|
|
62
|
+
class="status-checkbox"
|
|
63
|
+
>
|
|
64
|
+
<FormFieldCheckbox
|
|
65
|
+
v-model:checked="values.statusDateEnabled"
|
|
66
|
+
name="statusDateEnabled"
|
|
67
|
+
:label="
|
|
68
|
+
$i18n.t(
|
|
69
|
+
values.status.value === 'PUBLISHED'
|
|
70
|
+
? 'blog:scheduleArchive'
|
|
71
|
+
: 'blog:schedulePublish'
|
|
72
|
+
)
|
|
73
|
+
"
|
|
74
|
+
:error="errors.status"
|
|
66
75
|
/>
|
|
67
76
|
</div>
|
|
68
|
-
<div
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
<div
|
|
78
|
+
v-if="
|
|
79
|
+
values.statusDateEnabled &&
|
|
80
|
+
(values.status.value === 'PUBLISHED' ||
|
|
81
|
+
values.status.value === 'DRAFT')
|
|
82
|
+
"
|
|
83
|
+
class="status-date"
|
|
84
|
+
>
|
|
85
|
+
<FormField
|
|
86
|
+
v-model:value="values.statusDate"
|
|
87
|
+
name="statusDate"
|
|
88
|
+
type="date"
|
|
89
|
+
:label="
|
|
90
|
+
$i18n.t(
|
|
91
|
+
values.status.value === 'PUBLISHED'
|
|
92
|
+
? 'blog:archiveAt'
|
|
93
|
+
: 'blog:publishAt'
|
|
94
|
+
)
|
|
95
|
+
"
|
|
96
|
+
:error="errors.statusDate"
|
|
76
97
|
/>
|
|
77
98
|
</div>
|
|
78
99
|
</div>
|
|
79
100
|
|
|
80
|
-
<
|
|
81
|
-
v-model=
|
|
82
|
-
name=
|
|
83
|
-
:label="$t('blog:date')"
|
|
84
|
-
type=
|
|
85
|
-
:error=
|
|
101
|
+
<FormField
|
|
102
|
+
v-model:value="values.datetime"
|
|
103
|
+
name="datetime"
|
|
104
|
+
:label="$i18n.t('blog:date')"
|
|
105
|
+
type="date"
|
|
106
|
+
:error="errors.datetime"
|
|
86
107
|
/>
|
|
87
108
|
|
|
88
|
-
<
|
|
89
|
-
v-model=
|
|
90
|
-
name=
|
|
91
|
-
:label="$t('blog:excerpt')"
|
|
92
|
-
type=
|
|
93
|
-
:error=
|
|
109
|
+
<FormField
|
|
110
|
+
v-model:value="values.excerpt"
|
|
111
|
+
name="excerpt"
|
|
112
|
+
:label="$i18n.t('blog:excerpt')"
|
|
113
|
+
type="textarea"
|
|
114
|
+
:error="errors.excerpt"
|
|
94
115
|
/>
|
|
95
116
|
|
|
96
|
-
<
|
|
97
|
-
v-model=
|
|
98
|
-
name=
|
|
99
|
-
:label="$t('blog:body')"
|
|
100
|
-
:error=
|
|
101
|
-
:get-upload-adapter-options=
|
|
117
|
+
<FormFieldRichTextInput
|
|
118
|
+
v-model:value="values.body"
|
|
119
|
+
name="body"
|
|
120
|
+
:label="$i18n.t('blog:body')"
|
|
121
|
+
:error="errors.body"
|
|
122
|
+
:get-upload-adapter-options="getUploadAdapterOptions"
|
|
102
123
|
/>
|
|
103
124
|
|
|
104
125
|
<ShortCodeConstructor
|
|
105
|
-
:short-code-config-list=
|
|
126
|
+
:short-code-config-list="
|
|
106
127
|
moduleConfig ? moduleConfig.shortcodes : []
|
|
107
|
-
|
|
128
|
+
"
|
|
108
129
|
/>
|
|
109
130
|
</template>
|
|
110
131
|
|
|
111
132
|
<template v-if="selectedTabId === 'images'">
|
|
112
|
-
<
|
|
113
|
-
v-model=
|
|
114
|
-
:label="$t('blog:coverImage')"
|
|
115
|
-
name=
|
|
116
|
-
file-type=
|
|
117
|
-
:scenario=
|
|
133
|
+
<FormFieldFileInput
|
|
134
|
+
v-model:value="values.coverImage"
|
|
135
|
+
:label="$i18n.t('blog:coverImage')"
|
|
136
|
+
name="coverImage"
|
|
137
|
+
file-type="image"
|
|
138
|
+
:scenario="moduleConfig ? moduleConfig.fileScenarios.cover : null"
|
|
118
139
|
/>
|
|
119
140
|
|
|
120
|
-
<
|
|
121
|
-
v-model=
|
|
122
|
-
name=
|
|
123
|
-
:label="$t('blog:innerImage')"
|
|
124
|
-
file-type=
|
|
125
|
-
:scenario=
|
|
141
|
+
<FormFieldFileInput
|
|
142
|
+
v-model:value="values.image"
|
|
143
|
+
name="image"
|
|
144
|
+
:label="$i18n.t('blog:innerImage')"
|
|
145
|
+
file-type="image"
|
|
146
|
+
:scenario="moduleConfig ? moduleConfig.fileScenarios.image : null"
|
|
126
147
|
/>
|
|
127
148
|
|
|
128
|
-
<
|
|
129
|
-
v-model=
|
|
130
|
-
name=
|
|
131
|
-
:label="$t('blog:innerImageMobile')"
|
|
132
|
-
file-type=
|
|
133
|
-
:scenario=
|
|
149
|
+
<FormFieldFileInput
|
|
150
|
+
v-model:value="values.imageMobile"
|
|
151
|
+
name="imageMobile"
|
|
152
|
+
:label="$i18n.t('blog:innerImageMobile')"
|
|
153
|
+
file-type="image"
|
|
154
|
+
:scenario="
|
|
134
155
|
moduleConfig ? moduleConfig.fileScenarios.imageMobile : null
|
|
135
|
-
|
|
156
|
+
"
|
|
136
157
|
/>
|
|
137
158
|
</template>
|
|
138
159
|
|
|
139
160
|
<template v-if="selectedTabId === 'relations'">
|
|
140
|
-
<
|
|
141
|
-
v-model=
|
|
142
|
-
name=
|
|
143
|
-
:label="$t('blog:tags')"
|
|
144
|
-
:error=
|
|
161
|
+
<FormField
|
|
162
|
+
v-model:value="values.tags"
|
|
163
|
+
name="tags"
|
|
164
|
+
:label="$i18n.t('blog:tags')"
|
|
165
|
+
:error="errors.tags"
|
|
145
166
|
/>
|
|
146
167
|
|
|
147
|
-
<
|
|
148
|
-
:selected-options=
|
|
149
|
-
name=
|
|
150
|
-
:label="$t('blog:categories')"
|
|
151
|
-
:options=
|
|
152
|
-
:error=
|
|
153
|
-
@change=
|
|
168
|
+
<FormFieldMultiSelect
|
|
169
|
+
v-model:selected-options="values.categories"
|
|
170
|
+
name="categories"
|
|
171
|
+
:label="$i18n.t('blog:categories')"
|
|
172
|
+
:options="categoryOptionList"
|
|
173
|
+
:error="errors.categories"
|
|
174
|
+
@change="handleCategoriesChange"
|
|
154
175
|
/>
|
|
155
176
|
|
|
156
|
-
<
|
|
157
|
-
v-model=
|
|
158
|
-
name=
|
|
159
|
-
:label="$t('blog:relatedPosts')"
|
|
160
|
-
:options=
|
|
161
|
-
:error=
|
|
162
|
-
:searchable=
|
|
177
|
+
<FormFieldMultiSelect
|
|
178
|
+
v-model:selected-options="values.relatedPosts"
|
|
179
|
+
name="relatedPosts"
|
|
180
|
+
:label="$i18n.t('blog:relatedPosts')"
|
|
181
|
+
:options="postOptionList"
|
|
182
|
+
:error="errors.relatedPosts"
|
|
183
|
+
:searchable="true"
|
|
163
184
|
/>
|
|
164
185
|
</template>
|
|
165
186
|
|
|
166
187
|
<template v-if="selectedTabId === 'additional'">
|
|
167
188
|
<DynamicField
|
|
168
|
-
v-for=
|
|
169
|
-
:key=
|
|
170
|
-
:field=
|
|
189
|
+
v-for="field of values.additionalFields"
|
|
190
|
+
:key="field.name"
|
|
191
|
+
:field="field"
|
|
171
192
|
/>
|
|
172
193
|
</template>
|
|
173
194
|
|
|
174
195
|
<template v-if="selectedTabId === 'seo'">
|
|
175
|
-
<
|
|
176
|
-
:title=
|
|
177
|
-
:title-error-message=
|
|
178
|
-
:title-label="$t('blog:pageTitle')"
|
|
179
|
-
:description=
|
|
180
|
-
:description-error-message=
|
|
181
|
-
:description-label="$t('blog:pageDescription')"
|
|
182
|
-
:image=
|
|
183
|
-
:image-error-message=
|
|
184
|
-
:image-label="$t('blog:openGraphImage')"
|
|
185
|
-
:image-scenario=
|
|
196
|
+
<SeoFieldGroup
|
|
197
|
+
:title="values.pageTitle"
|
|
198
|
+
:title-error-message="errors.pageTitle"
|
|
199
|
+
:title-label="$i18n.t('blog:pageTitle')"
|
|
200
|
+
:description="values.pageDescription"
|
|
201
|
+
:description-error-message="errors.pageDescription"
|
|
202
|
+
:description-label="$i18n.t('blog:pageDescription')"
|
|
203
|
+
:image="values.openGraphImage"
|
|
204
|
+
:image-error-message="errors.openGraphImage"
|
|
205
|
+
:image-label="$i18n.t('blog:openGraphImage')"
|
|
206
|
+
:image-scenario="
|
|
186
207
|
moduleConfig ? moduleConfig.fileScenarios.openGraph : null
|
|
187
|
-
|
|
188
|
-
@change=
|
|
208
|
+
"
|
|
209
|
+
@change="handleSeoFieldGroupChange"
|
|
189
210
|
/>
|
|
190
211
|
</template>
|
|
191
212
|
</form>
|
|
192
213
|
</template>
|
|
193
214
|
|
|
194
|
-
<template
|
|
215
|
+
<template #footer>
|
|
195
216
|
<FormFooter
|
|
196
|
-
:back-href=
|
|
197
|
-
:
|
|
198
|
-
:is-
|
|
199
|
-
:
|
|
200
|
-
|
|
217
|
+
:back-href="postListUrl"
|
|
218
|
+
:is-submitting="isSubmitting"
|
|
219
|
+
:is-creation="isCreation"
|
|
220
|
+
:can-create-another="isCreation"
|
|
221
|
+
@submit="submitForm"
|
|
201
222
|
/>
|
|
202
223
|
</template>
|
|
203
|
-
</
|
|
224
|
+
</Page>
|
|
204
225
|
</template>
|
|
205
226
|
|
|
206
|
-
<script lang=
|
|
207
|
-
import {
|
|
208
|
-
|
|
209
|
-
defineComponent,
|
|
210
|
-
onMounted,
|
|
211
|
-
ref,
|
|
212
|
-
watch
|
|
213
|
-
} from '@vue/composition-api';
|
|
227
|
+
<script lang="ts">
|
|
228
|
+
import { computed, defineComponent, onMounted, ref, watch } from 'vue';
|
|
229
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
214
230
|
|
|
215
231
|
import {
|
|
216
232
|
convertRequestErrorToMap,
|
|
217
233
|
isNotNullish,
|
|
218
234
|
Nullable,
|
|
219
235
|
useResource,
|
|
220
|
-
urlTranslit
|
|
236
|
+
urlTranslit,
|
|
237
|
+
useI18n,
|
|
238
|
+
useToast,
|
|
239
|
+
navigateBack,
|
|
221
240
|
} from '@tager/admin-services';
|
|
222
241
|
import {
|
|
223
242
|
createTabErrorFinder,
|
|
@@ -226,24 +245,31 @@ import {
|
|
|
226
245
|
ShortCodeConstructor,
|
|
227
246
|
SeoChangeEvent,
|
|
228
247
|
FormFooter,
|
|
229
|
-
TagerFormSubmitEvent
|
|
248
|
+
TagerFormSubmitEvent,
|
|
249
|
+
FormFieldSelect,
|
|
250
|
+
FormField,
|
|
251
|
+
FormFieldUrlAliasInput,
|
|
252
|
+
FormFieldCheckbox,
|
|
253
|
+
FormFieldRichTextInput,
|
|
254
|
+
FormFieldFileInput,
|
|
255
|
+
FormFieldMultiSelect,
|
|
256
|
+
SeoFieldGroup,
|
|
257
|
+
TabList, formatDateTime, formatDate,
|
|
230
258
|
} from '@tager/admin-ui';
|
|
231
259
|
import { DynamicField } from '@tager/admin-dynamic-field';
|
|
260
|
+
import { Page } from '@tager/admin-layout';
|
|
232
261
|
|
|
233
|
-
import {
|
|
234
|
-
getBlogPostFormUrl,
|
|
235
|
-
getBlogPostListUrl
|
|
236
|
-
} from '../../../constants/paths';
|
|
262
|
+
import { getBlogPostFormUrl, getBlogPostListUrl } from '../../../utils/paths';
|
|
237
263
|
import {
|
|
238
264
|
createBlogPost,
|
|
239
265
|
getPost,
|
|
240
|
-
updateBlogPost
|
|
266
|
+
updateBlogPost,
|
|
241
267
|
} from '../../../services/requests';
|
|
242
268
|
import { Language, PostFull } from '../../../typings/model';
|
|
243
269
|
import {
|
|
244
270
|
useFetchModuleConfig,
|
|
245
271
|
useFetchCategories,
|
|
246
|
-
useFetchPosts
|
|
272
|
+
useFetchPosts,
|
|
247
273
|
} from '../../../hooks';
|
|
248
274
|
|
|
249
275
|
import {
|
|
@@ -252,28 +278,43 @@ import {
|
|
|
252
278
|
convertFormValuesToUpdatePayload,
|
|
253
279
|
convertPostToFormValues,
|
|
254
280
|
FormValues,
|
|
255
|
-
getStatusOptions
|
|
281
|
+
getStatusOptions,
|
|
256
282
|
} from './PostForm.helpers';
|
|
257
283
|
|
|
258
284
|
export default defineComponent({
|
|
259
285
|
name: 'BlogPostForm',
|
|
260
|
-
components: {
|
|
261
|
-
|
|
262
|
-
|
|
286
|
+
components: {
|
|
287
|
+
SeoFieldGroup,
|
|
288
|
+
FormFieldMultiSelect,
|
|
289
|
+
FormFieldFileInput,
|
|
290
|
+
FormFieldRichTextInput,
|
|
291
|
+
FormFieldCheckbox,
|
|
292
|
+
FormFieldUrlAliasInput,
|
|
293
|
+
FormField,
|
|
294
|
+
FormFieldSelect,
|
|
295
|
+
TabList,
|
|
296
|
+
Page,
|
|
297
|
+
DynamicField,
|
|
298
|
+
ShortCodeConstructor,
|
|
299
|
+
FormFooter,
|
|
300
|
+
},
|
|
301
|
+
setup() {
|
|
302
|
+
const route = useRoute();
|
|
303
|
+
const router = useRouter();
|
|
304
|
+
const toast = useToast();
|
|
305
|
+
const { t } = useI18n();
|
|
306
|
+
|
|
307
|
+
const postId = computed<string>(() => route.params.postId as string);
|
|
263
308
|
const isCreation = computed<boolean>(() => postId.value === 'create');
|
|
264
309
|
|
|
265
310
|
const urlAliasChanged = ref<boolean>(false);
|
|
266
311
|
|
|
267
|
-
const statusOptions = computed<OptionType[]>(() =>
|
|
268
|
-
getStatusOptions(context.root.$t)
|
|
269
|
-
);
|
|
312
|
+
const statusOptions = computed<OptionType[]>(() => getStatusOptions(t));
|
|
270
313
|
|
|
271
314
|
/** Fetch module config **/
|
|
272
315
|
|
|
273
|
-
const {
|
|
274
|
-
|
|
275
|
-
loading: isModuleConfigLoading
|
|
276
|
-
} = useFetchModuleConfig({ context });
|
|
316
|
+
const { data: moduleConfig, loading: isModuleConfigLoading } =
|
|
317
|
+
useFetchModuleConfig();
|
|
277
318
|
|
|
278
319
|
const languageList = computed<Language[]>(
|
|
279
320
|
() => moduleConfig.value?.languages ?? []
|
|
@@ -282,7 +323,7 @@ export default defineComponent({
|
|
|
282
323
|
const languageOptionList = computed<OptionType[]>(() =>
|
|
283
324
|
languageList.value.map(({ id, name }) => ({
|
|
284
325
|
value: id,
|
|
285
|
-
label: name
|
|
326
|
+
label: name,
|
|
286
327
|
}))
|
|
287
328
|
);
|
|
288
329
|
|
|
@@ -290,18 +331,18 @@ export default defineComponent({
|
|
|
290
331
|
|
|
291
332
|
/** Fetch category list */
|
|
292
333
|
|
|
293
|
-
const {
|
|
294
|
-
|
|
295
|
-
loading: isCategoryListLoading
|
|
296
|
-
} = useFetchCategories({ context });
|
|
334
|
+
const { data: categoryList, loading: isCategoryListLoading } =
|
|
335
|
+
useFetchCategories();
|
|
297
336
|
|
|
298
337
|
/** Fetch Post */
|
|
299
338
|
|
|
300
|
-
const [fetchPost, { data: post, loading: isPostLoading }] = useResource<
|
|
301
|
-
|
|
339
|
+
const [fetchPost, { data: post, loading: isPostLoading }] = useResource<
|
|
340
|
+
Nullable<PostFull>
|
|
341
|
+
>({
|
|
342
|
+
fetchResource: () =>
|
|
343
|
+
postId.value ? getPost(postId.value) : new Promise(() => null),
|
|
302
344
|
initialValue: null,
|
|
303
|
-
|
|
304
|
-
resourceName: 'Post'
|
|
345
|
+
resourceName: 'Post',
|
|
305
346
|
});
|
|
306
347
|
|
|
307
348
|
onMounted(() => {
|
|
@@ -317,18 +358,21 @@ export default defineComponent({
|
|
|
317
358
|
});
|
|
318
359
|
|
|
319
360
|
/** Fetch post list */
|
|
320
|
-
const { data: postList, loading: isPostListLoading } = useFetchPosts(
|
|
321
|
-
context
|
|
322
|
-
});
|
|
361
|
+
const { data: postList, loading: isPostListLoading } = useFetchPosts();
|
|
323
362
|
|
|
324
363
|
const postOptionList = computed<OptionType<number>[]>(() =>
|
|
325
364
|
postList.value
|
|
326
365
|
.filter((relatedPost) => relatedPost.id !== post.value?.id)
|
|
327
366
|
.map((post) => ({
|
|
328
367
|
value: post.id,
|
|
329
|
-
label:
|
|
368
|
+
label:
|
|
369
|
+
(post.status === 'ARCHIVED'
|
|
370
|
+
? `${t('blog:statusArchived')} - `
|
|
371
|
+
: post.status === 'DRAFT'
|
|
372
|
+
? `${t('blog:statusDraft')} - `
|
|
373
|
+
: (post.datetime ? formatDate(new Date(post.datetime)) + ' - ' : '')) + post.title,
|
|
330
374
|
}))
|
|
331
|
-
)
|
|
375
|
+
)
|
|
332
376
|
|
|
333
377
|
/** Form State **/
|
|
334
378
|
const isSubmitting = ref<boolean>(false);
|
|
@@ -368,17 +412,11 @@ export default defineComponent({
|
|
|
368
412
|
errors.value = {};
|
|
369
413
|
|
|
370
414
|
if (event.type === 'create') {
|
|
371
|
-
|
|
372
|
-
getBlogPostFormUrl({ postId: String(data.id) })
|
|
373
|
-
);
|
|
415
|
+
router.push(getBlogPostFormUrl({ postId: String(data.id) }));
|
|
374
416
|
}
|
|
375
417
|
|
|
376
418
|
if (event.type === 'create_exit' || event.type === 'save_exit') {
|
|
377
|
-
|
|
378
|
-
context.root.$router.back();
|
|
379
|
-
} else {
|
|
380
|
-
context.root.$router.push(getBlogPostListUrl());
|
|
381
|
-
}
|
|
419
|
+
navigateBack(router, getBlogPostListUrl());
|
|
382
420
|
}
|
|
383
421
|
|
|
384
422
|
if (event.type === 'create_create-another') {
|
|
@@ -391,23 +429,23 @@ export default defineComponent({
|
|
|
391
429
|
);
|
|
392
430
|
}
|
|
393
431
|
|
|
394
|
-
|
|
432
|
+
toast.show({
|
|
395
433
|
variant: 'success',
|
|
396
|
-
title:
|
|
434
|
+
title: t('blog:success'),
|
|
397
435
|
body: isCreation.value
|
|
398
|
-
?
|
|
399
|
-
:
|
|
436
|
+
? t('blog:blogPostWasSuccessfullyCreated')
|
|
437
|
+
: t('blog:blogPostWasSuccessfullyUpdated'),
|
|
400
438
|
});
|
|
401
439
|
})
|
|
402
440
|
.catch((error) => {
|
|
403
441
|
console.error(error);
|
|
404
442
|
errors.value = convertRequestErrorToMap(error);
|
|
405
|
-
|
|
443
|
+
toast.show({
|
|
406
444
|
variant: 'danger',
|
|
407
|
-
title:
|
|
445
|
+
title: t('blog:error'),
|
|
408
446
|
body: isCreation.value
|
|
409
|
-
?
|
|
410
|
-
:
|
|
447
|
+
? t('blog:blogPostCreationWasFailed')
|
|
448
|
+
: t('blog:blogPostUpdateWasFailed'),
|
|
411
449
|
});
|
|
412
450
|
})
|
|
413
451
|
.finally(() => {
|
|
@@ -473,32 +511,32 @@ export default defineComponent({
|
|
|
473
511
|
return [
|
|
474
512
|
{
|
|
475
513
|
id: 'common',
|
|
476
|
-
label:
|
|
514
|
+
label: t('blog:common'),
|
|
477
515
|
hasErrors: hasErrors([
|
|
478
516
|
'title',
|
|
479
517
|
'language',
|
|
480
518
|
'urlAlias',
|
|
481
519
|
'excerpt',
|
|
482
520
|
'body',
|
|
483
|
-
'date'
|
|
484
|
-
])
|
|
521
|
+
'date',
|
|
522
|
+
]),
|
|
485
523
|
},
|
|
486
524
|
{
|
|
487
525
|
id: 'images',
|
|
488
|
-
label:
|
|
489
|
-
hasErrors: hasErrors(['coverImage', 'image'])
|
|
526
|
+
label: t('blog:images'),
|
|
527
|
+
hasErrors: hasErrors(['coverImage', 'image']),
|
|
490
528
|
},
|
|
491
529
|
{
|
|
492
530
|
id: 'relations',
|
|
493
|
-
label:
|
|
494
|
-
hasErrors: hasErrors(['categories', 'relatedPosts', 'tags'])
|
|
531
|
+
label: t('blog:relations'),
|
|
532
|
+
hasErrors: hasErrors(['categories', 'relatedPosts', 'tags']),
|
|
495
533
|
},
|
|
496
534
|
values.value.additionalFields.length > 0
|
|
497
535
|
? {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
536
|
+
id: 'additional',
|
|
537
|
+
label: t('blog:additionalFields'),
|
|
538
|
+
hasErrors: hasErrors([]),
|
|
539
|
+
}
|
|
502
540
|
: null,
|
|
503
541
|
{
|
|
504
542
|
id: 'seo',
|
|
@@ -506,31 +544,33 @@ export default defineComponent({
|
|
|
506
544
|
hasErrors: hasErrors([
|
|
507
545
|
'pageTitle',
|
|
508
546
|
'pageDescription',
|
|
509
|
-
'openGraphImage'
|
|
510
|
-
])
|
|
511
|
-
}
|
|
547
|
+
'openGraphImage',
|
|
548
|
+
]),
|
|
549
|
+
},
|
|
512
550
|
].filter(isNotNullish);
|
|
513
551
|
});
|
|
514
552
|
|
|
515
553
|
const selectedTabId = ref<string>(tabList.value[0].id);
|
|
516
554
|
|
|
517
|
-
const headerButtonList = computed<
|
|
555
|
+
const headerButtonList = computed<
|
|
556
|
+
{ text: string; href: string; target?: string }[]
|
|
557
|
+
>(() =>
|
|
518
558
|
[
|
|
519
559
|
post.value
|
|
520
560
|
? {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
: null
|
|
561
|
+
text: t('blog:viewPost'),
|
|
562
|
+
href: process.env.VUE_APP_WEBSITE_URL + post.value.url,
|
|
563
|
+
target: '_blank',
|
|
564
|
+
}
|
|
565
|
+
: null,
|
|
526
566
|
].filter(isNotNullish)
|
|
527
567
|
);
|
|
528
568
|
|
|
529
569
|
function handleSeoFieldGroupChange({
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
570
|
+
title,
|
|
571
|
+
description,
|
|
572
|
+
image,
|
|
573
|
+
}: SeoChangeEvent) {
|
|
534
574
|
values.value.pageTitle = title;
|
|
535
575
|
values.value.pageDescription = description;
|
|
536
576
|
values.value.openGraphImage = image;
|
|
@@ -579,7 +619,7 @@ export default defineComponent({
|
|
|
579
619
|
|
|
580
620
|
const newSelectedOption: OptionType<number> = {
|
|
581
621
|
value: foundSelectedCategory.id,
|
|
582
|
-
label: foundSelectedCategory.name
|
|
622
|
+
label: foundSelectedCategory.name,
|
|
583
623
|
};
|
|
584
624
|
|
|
585
625
|
if (
|
|
@@ -626,13 +666,13 @@ export default defineComponent({
|
|
|
626
666
|
urlAliasTemplate,
|
|
627
667
|
handleCategoriesChange,
|
|
628
668
|
|
|
629
|
-
statusOptions
|
|
669
|
+
statusOptions,
|
|
630
670
|
};
|
|
631
|
-
}
|
|
671
|
+
},
|
|
632
672
|
});
|
|
633
673
|
</script>
|
|
634
674
|
|
|
635
|
-
<style scoped lang=
|
|
675
|
+
<style scoped lang="scss">
|
|
636
676
|
.status {
|
|
637
677
|
display: flex;
|
|
638
678
|
align-items: flex-end;
|
|
@@ -651,4 +691,4 @@ export default defineComponent({
|
|
|
651
691
|
margin-left: 20px;
|
|
652
692
|
flex: 1 1 1px;
|
|
653
693
|
}
|
|
654
|
-
</style>
|
|
694
|
+
</style>
|