@tager/admin-blog 0.3.38 → 0.3.42

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.
@@ -1,157 +1,191 @@
1
1
  <template>
2
2
  <page
3
3
  :title="isCreation ? $t('blog:createPost') : $t('blog:updatePost')"
4
- :is-content-loading="isContentLoading"
5
- :header-buttons="headerButtonList"
6
- :footer="{
4
+ :is-content-loading='isContentLoading'
5
+ :header-buttons='headerButtonList'
6
+ :footer='{
7
7
  backHref: postListUrl,
8
8
  onSubmit: submitForm,
9
9
  isSubmitting: isSubmitting,
10
- }"
10
+ }'
11
11
  >
12
12
  <template v-slot:content>
13
- <form novalidate @submit.prevent="submitForm">
13
+ <form novalidate @submit.prevent='submitForm'>
14
14
  <tab-list
15
- :tab-list="tabList"
16
- :selected-tab-id="selectedTabId"
17
- @tab:update="selectedTabId = $event.tabId"
15
+ :tab-list='tabList'
16
+ :selected-tab-id='selectedTabId'
17
+ @tab:update='selectedTabId = $event.tabId'
18
18
  />
19
19
 
20
20
  <template v-if="selectedTabId === 'common'">
21
+
21
22
  <form-field-select
22
- v-if="isCreation && isLangSpecific"
23
- v-model="values.language"
24
- name="language"
23
+ v-if='isCreation && isLangSpecific'
24
+ v-model='values.language'
25
+ name='language'
25
26
  :label="$t('blog:language')"
26
- :options="languageOptionList"
27
- :error="errors.language"
27
+ :options='languageOptionList'
28
+ :error='errors.language'
28
29
  />
29
30
 
30
31
  <form-field
31
- v-model="values.title"
32
- name="title"
32
+ v-model='values.title'
33
+ name='title'
33
34
  :label="$t('blog:title')"
34
- :error="errors.title"
35
- @input="handleTitleChange"
35
+ :error='errors.title'
36
+ @input='handleTitleChange'
36
37
  />
37
38
 
38
39
  <form-field-url-alias-input
39
- id="urlAlias"
40
- v-model="values.urlAlias"
41
- name="urlAlias"
40
+ id='urlAlias'
41
+ v-model='values.urlAlias'
42
+ name='urlAlias'
42
43
  :label="$t('blog:link')"
43
- :url-template="urlAliasTemplate"
44
- :error="errors.urlAlias"
45
- @change="handleAliasChange"
44
+ :url-template='urlAliasTemplate'
45
+ :error='errors.urlAlias'
46
+ @change='handleAliasChange'
47
+ />
48
+
49
+ <div class='status'>
50
+ <div class='status-value'>
51
+ <form-field-select
52
+ v-model='values.status'
53
+ name='status'
54
+ :error='errors.status'
55
+ :label="$t('blog:status')"
56
+ :no-options-message="$t('blog:noTemplates')"
57
+ :options='statusOptions'
58
+ />
59
+ </div>
60
+ <div class='status-checkbox' v-if='values.status.value === "PUBLISHED" || values.status.value === "DRAFT"'>
61
+ <form-field-checkbox
62
+ v-model='values.statusDateEnabled'
63
+ name='statusDateEnabled'
64
+ :label="$t(values.status.value === 'PUBLISHED' ? 'blog:scheduleArchive' : 'blog:schedulePublish')"
65
+ :error='errors.status'
66
+ />
67
+ </div>
68
+ <div class='status-date'
69
+ v-if='values.statusDateEnabled && (values.status.value === "PUBLISHED" || values.status.value === "DRAFT")'>
70
+ <form-field
71
+ v-model='values.statusDate'
72
+ name='statusDate'
73
+ type='date'
74
+ :label="$t(values.status.value === 'PUBLISHED' ? 'blog:archiveAt' : 'blog:publishAt')"
75
+ :error='errors.statusDate'
76
+ />
77
+ </div>
78
+ </div>
79
+
80
+ <form-field
81
+ v-model='values.datetime'
82
+ name='datetime'
83
+ :label="$t('blog:date')"
84
+ type='date'
85
+ :error='errors.datetime'
46
86
  />
47
87
 
48
88
  <form-field
49
- v-model="values.excerpt"
50
- name="excerpt"
89
+ v-model='values.excerpt'
90
+ name='excerpt'
51
91
  :label="$t('blog:excerpt')"
52
- type="textarea"
53
- :error="errors.excerpt"
92
+ type='textarea'
93
+ :error='errors.excerpt'
54
94
  />
95
+
55
96
  <form-field-rich-text-input
56
- v-model="values.body"
57
- name="body"
97
+ v-model='values.body'
98
+ name='body'
58
99
  :label="$t('blog:body')"
59
- :error="errors.body"
60
- :get-upload-adapter-options="getUploadAdapterOptions"
100
+ :error='errors.body'
101
+ :get-upload-adapter-options='getUploadAdapterOptions'
61
102
  />
103
+
62
104
  <ShortCodeConstructor
63
- :short-code-config-list="
105
+ :short-code-config-list='
64
106
  moduleConfig ? moduleConfig.shortcodes : []
65
- "
66
- />
67
-
68
- <form-field
69
- v-model="values.datetime"
70
- name="datetime"
71
- :label="$t('blog:date')"
72
- type="date"
73
- :error="errors.datetime"
107
+ '
74
108
  />
75
109
  </template>
76
110
 
77
111
  <template v-if="selectedTabId === 'images'">
78
112
  <form-field-file-input
79
- v-model="values.coverImage"
113
+ v-model='values.coverImage'
80
114
  :label="$t('blog:coverImage')"
81
- name="coverImage"
82
- file-type="image"
83
- :scenario="moduleConfig ? moduleConfig.fileScenarios.cover : null"
115
+ name='coverImage'
116
+ file-type='image'
117
+ :scenario='moduleConfig ? moduleConfig.fileScenarios.cover : null'
84
118
  />
85
119
 
86
120
  <form-field-file-input
87
- v-model="values.image"
88
- name="image"
121
+ v-model='values.image'
122
+ name='image'
89
123
  :label="$t('blog:innerImage')"
90
- file-type="image"
91
- :scenario="moduleConfig ? moduleConfig.fileScenarios.image : null"
124
+ file-type='image'
125
+ :scenario='moduleConfig ? moduleConfig.fileScenarios.image : null'
92
126
  />
93
127
 
94
128
  <form-field-file-input
95
- v-model="values.imageMobile"
96
- name="imageMobile"
129
+ v-model='values.imageMobile'
130
+ name='imageMobile'
97
131
  :label="$t('blog:innerImageMobile')"
98
- file-type="image"
99
- :scenario="
132
+ file-type='image'
133
+ :scenario='
100
134
  moduleConfig ? moduleConfig.fileScenarios.imageMobile : null
101
- "
135
+ '
102
136
  />
103
137
  </template>
104
138
 
105
139
  <template v-if="selectedTabId === 'relations'">
106
140
  <form-field
107
- v-model="values.tags"
108
- name="tags"
141
+ v-model='values.tags'
142
+ name='tags'
109
143
  :label="$t('blog:tags')"
110
- :error="errors.tags"
144
+ :error='errors.tags'
111
145
  />
112
146
 
113
147
  <form-field-multi-select
114
- :selected-options="values.categories"
115
- name="categories"
148
+ :selected-options='values.categories'
149
+ name='categories'
116
150
  :label="$t('blog:categories')"
117
- :options="categoryOptionList"
118
- :error="errors.categories"
119
- @change="handleCategoriesChange"
151
+ :options='categoryOptionList'
152
+ :error='errors.categories'
153
+ @change='handleCategoriesChange'
120
154
  />
121
155
 
122
156
  <form-field-multi-select
123
- v-model="values.relatedPosts"
124
- name="relatedPosts"
157
+ v-model='values.relatedPosts'
158
+ name='relatedPosts'
125
159
  :label="$t('blog:relatedPosts')"
126
- :options="postOptionList"
127
- :error="errors.relatedPosts"
128
- :searchable="true"
160
+ :options='postOptionList'
161
+ :error='errors.relatedPosts'
162
+ :searchable='true'
129
163
  />
130
164
  </template>
131
165
 
132
166
  <template v-if="selectedTabId === 'additional'">
133
167
  <DynamicField
134
- v-for="field of values.additionalFields"
135
- :key="field.name"
136
- :field="field"
168
+ v-for='field of values.additionalFields'
169
+ :key='field.name'
170
+ :field='field'
137
171
  />
138
172
  </template>
139
173
 
140
174
  <template v-if="selectedTabId === 'seo'">
141
175
  <seo-field-group
142
- :title="values.pageTitle"
143
- :title-error-message="errors.pageTitle"
176
+ :title='values.pageTitle'
177
+ :title-error-message='errors.pageTitle'
144
178
  :title-label="$t('blog:pageTitle')"
145
- :description="values.pageDescription"
146
- :description-error-message="errors.pageDescription"
179
+ :description='values.pageDescription'
180
+ :description-error-message='errors.pageDescription'
147
181
  :description-label="$t('blog:pageDescription')"
148
- :image="values.openGraphImage"
149
- :image-error-message="errors.openGraphImage"
182
+ :image='values.openGraphImage'
183
+ :image-error-message='errors.openGraphImage'
150
184
  :image-label="$t('blog:openGraphImage')"
151
- :image-scenario="
185
+ :image-scenario='
152
186
  moduleConfig ? moduleConfig.fileScenarios.openGraph : null
153
- "
154
- @change="handleSeoFieldGroupChange"
187
+ '
188
+ @change='handleSeoFieldGroupChange'
155
189
  />
156
190
  </template>
157
191
  </form>
@@ -159,23 +193,23 @@
159
193
 
160
194
  <template v-slot:footer>
161
195
  <FormFooter
162
- :back-href="postListUrl"
163
- :on-submit="submitForm"
164
- :is-submitting="isSubmitting"
165
- :is-creation="isCreation"
166
- :can-create-another="isCreation"
196
+ :back-href='postListUrl'
197
+ :on-submit='submitForm'
198
+ :is-submitting='isSubmitting'
199
+ :is-creation='isCreation'
200
+ :can-create-another='isCreation'
167
201
  />
168
202
  </template>
169
203
  </page>
170
204
  </template>
171
205
 
172
- <script lang="ts">
206
+ <script lang='ts'>
173
207
  import {
174
208
  computed,
175
209
  defineComponent,
176
210
  onMounted,
177
211
  ref,
178
- watch,
212
+ watch
179
213
  } from '@vue/composition-api';
180
214
 
181
215
  import {
@@ -183,7 +217,7 @@ import {
183
217
  isNotNullish,
184
218
  Nullable,
185
219
  useResource,
186
- urlTranslit,
220
+ urlTranslit
187
221
  } from '@tager/admin-services';
188
222
  import {
189
223
  createTabErrorFinder,
@@ -192,24 +226,24 @@ import {
192
226
  ShortCodeConstructor,
193
227
  SeoChangeEvent,
194
228
  FormFooter,
195
- TagerFormSubmitEvent,
229
+ TagerFormSubmitEvent
196
230
  } from '@tager/admin-ui';
197
231
  import { DynamicField } from '@tager/admin-dynamic-field';
198
232
 
199
233
  import {
200
234
  getBlogPostFormUrl,
201
- getBlogPostListUrl,
235
+ getBlogPostListUrl
202
236
  } from '../../../constants/paths';
203
237
  import {
204
238
  createBlogPost,
205
239
  getPost,
206
- updateBlogPost,
240
+ updateBlogPost
207
241
  } from '../../../services/requests';
208
242
  import { Language, PostFull } from '../../../typings/model';
209
243
  import {
210
244
  useFetchModuleConfig,
211
245
  useFetchCategories,
212
- useFetchPosts,
246
+ useFetchPosts
213
247
  } from '../../../hooks';
214
248
 
215
249
  import {
@@ -218,6 +252,7 @@ import {
218
252
  convertFormValuesToUpdatePayload,
219
253
  convertPostToFormValues,
220
254
  FormValues,
255
+ getStatusOptions
221
256
  } from './PostForm.helpers';
222
257
 
223
258
  export default defineComponent({
@@ -229,11 +264,15 @@ export default defineComponent({
229
264
 
230
265
  const urlAliasChanged = ref<boolean>(false);
231
266
 
267
+ const statusOptions = computed<OptionType[]>(() =>
268
+ getStatusOptions(context.root.$t)
269
+ );
270
+
232
271
  /** Fetch module config **/
233
272
 
234
273
  const {
235
274
  data: moduleConfig,
236
- loading: isModuleConfigLoading,
275
+ loading: isModuleConfigLoading
237
276
  } = useFetchModuleConfig({ context });
238
277
 
239
278
  const languageList = computed<Language[]>(
@@ -243,7 +282,7 @@ export default defineComponent({
243
282
  const languageOptionList = computed<OptionType[]>(() =>
244
283
  languageList.value.map(({ id, name }) => ({
245
284
  value: id,
246
- label: name,
285
+ label: name
247
286
  }))
248
287
  );
249
288
 
@@ -253,18 +292,16 @@ export default defineComponent({
253
292
 
254
293
  const {
255
294
  data: categoryList,
256
- loading: isCategoryListLoading,
295
+ loading: isCategoryListLoading
257
296
  } = useFetchCategories({ context });
258
297
 
259
298
  /** Fetch Post */
260
299
 
261
- const [fetchPost, { data: post, loading: isPostLoading }] = useResource<
262
- Nullable<PostFull>
263
- >({
300
+ const [fetchPost, { data: post, loading: isPostLoading }] = useResource<Nullable<PostFull>>({
264
301
  fetchResource: () => getPost(postId.value),
265
302
  initialValue: null,
266
303
  context,
267
- resourceName: 'Post',
304
+ resourceName: 'Post'
268
305
  });
269
306
 
270
307
  onMounted(() => {
@@ -281,7 +318,7 @@ export default defineComponent({
281
318
 
282
319
  /** Fetch post list */
283
320
  const { data: postList, loading: isPostListLoading } = useFetchPosts({
284
- context,
321
+ context
285
322
  });
286
323
 
287
324
  const postOptionList = computed<OptionType<number>[]>(() =>
@@ -289,7 +326,7 @@ export default defineComponent({
289
326
  .filter((relatedPost) => relatedPost.id !== post.value?.id)
290
327
  .map((post) => ({
291
328
  value: post.id,
292
- label: post.title,
329
+ label: post.title
293
330
  }))
294
331
  );
295
332
 
@@ -300,7 +337,8 @@ export default defineComponent({
300
337
  post.value,
301
338
  languageOptionList.value,
302
339
  postOptionList.value,
303
- moduleConfig.value?.fields ?? []
340
+ moduleConfig.value?.fields ?? [],
341
+ statusOptions.value
304
342
  )
305
343
  );
306
344
  const errors = ref<Record<string, string>>({});
@@ -310,7 +348,8 @@ export default defineComponent({
310
348
  post.value,
311
349
  languageOptionList.value,
312
350
  postOptionList.value,
313
- moduleConfig.value?.fields ?? []
351
+ moduleConfig.value?.fields ?? [],
352
+ statusOptions.value
314
353
  );
315
354
  });
316
355
 
@@ -347,7 +386,8 @@ export default defineComponent({
347
386
  null,
348
387
  languageOptionList.value,
349
388
  postOptionList.value,
350
- moduleConfig.value?.fields ?? []
389
+ moduleConfig.value?.fields ?? [],
390
+ statusOptions.value
351
391
  );
352
392
  }
353
393
 
@@ -356,7 +396,7 @@ export default defineComponent({
356
396
  title: context.root.$t('blog:success'),
357
397
  body: isCreation.value
358
398
  ? context.root.$t('blog:blogPostWasSuccessfullyCreated')
359
- : context.root.$t('blog:blogPostWasSuccessfullyUpdated'),
399
+ : context.root.$t('blog:blogPostWasSuccessfullyUpdated')
360
400
  });
361
401
  })
362
402
  .catch((error) => {
@@ -367,7 +407,7 @@ export default defineComponent({
367
407
  title: context.root.$t('blog:error'),
368
408
  body: isCreation.value
369
409
  ? context.root.$t('blog:blogPostCreationWasFailed')
370
- : context.root.$t('blog:blogPostUpdateWasFailed'),
410
+ : context.root.$t('blog:blogPostUpdateWasFailed')
371
411
  });
372
412
  })
373
413
  .finally(() => {
@@ -440,25 +480,25 @@ export default defineComponent({
440
480
  'urlAlias',
441
481
  'excerpt',
442
482
  'body',
443
- 'date',
444
- ]),
483
+ 'date'
484
+ ])
445
485
  },
446
486
  {
447
487
  id: 'images',
448
488
  label: context.root.$t('blog:images'),
449
- hasErrors: hasErrors(['coverImage', 'image']),
489
+ hasErrors: hasErrors(['coverImage', 'image'])
450
490
  },
451
491
  {
452
492
  id: 'relations',
453
493
  label: context.root.$t('blog:relations'),
454
- hasErrors: hasErrors(['categories', 'relatedPosts', 'tags']),
494
+ hasErrors: hasErrors(['categories', 'relatedPosts', 'tags'])
455
495
  },
456
496
  values.value.additionalFields.length > 0
457
497
  ? {
458
- id: 'additional',
459
- label: context.root.$t('blog:additionalFields'),
460
- hasErrors: hasErrors([]),
461
- }
498
+ id: 'additional',
499
+ label: context.root.$t('blog:additionalFields'),
500
+ hasErrors: hasErrors([])
501
+ }
462
502
  : null,
463
503
  {
464
504
  id: 'seo',
@@ -466,40 +506,38 @@ export default defineComponent({
466
506
  hasErrors: hasErrors([
467
507
  'pageTitle',
468
508
  'pageDescription',
469
- 'openGraphImage',
470
- ]),
471
- },
509
+ 'openGraphImage'
510
+ ])
511
+ }
472
512
  ].filter(isNotNullish);
473
513
  });
474
514
 
475
515
  const selectedTabId = ref<string>(tabList.value[0].id);
476
516
 
477
- const headerButtonList = computed<
478
- { text: string; href: string; target?: string }[]
479
- >(() =>
517
+ const headerButtonList = computed<{ text: string; href: string; target?: string }[]>(() =>
480
518
  [
481
519
  post.value
482
520
  ? {
483
- text: context.root.$t('blog:viewPost'),
484
- href: process.env.VUE_APP_WEBSITE_URL + post.value.url,
485
- target: '_blank',
486
- }
487
- : null,
521
+ text: context.root.$t('blog:viewPost'),
522
+ href: process.env.VUE_APP_WEBSITE_URL + post.value.url,
523
+ target: '_blank'
524
+ }
525
+ : null
488
526
  ].filter(isNotNullish)
489
527
  );
490
528
 
491
529
  function handleSeoFieldGroupChange({
492
- title,
493
- description,
494
- image,
495
- }: SeoChangeEvent) {
530
+ title,
531
+ description,
532
+ image
533
+ }: SeoChangeEvent) {
496
534
  values.value.pageTitle = title;
497
535
  values.value.pageDescription = description;
498
536
  values.value.openGraphImage = image;
499
537
  }
500
538
 
501
539
  function handleTitleChange(value: string) {
502
- if (urlAliasChanged.value === false) {
540
+ if (isCreation.value && urlAliasChanged.value === false) {
503
541
  values.value.urlAlias = urlTranslit(value);
504
542
  }
505
543
  }
@@ -541,7 +579,7 @@ export default defineComponent({
541
579
 
542
580
  const newSelectedOption: OptionType<number> = {
543
581
  value: foundSelectedCategory.id,
544
- label: foundSelectedCategory.name,
582
+ label: foundSelectedCategory.name
545
583
  };
546
584
 
547
585
  if (
@@ -587,7 +625,30 @@ export default defineComponent({
587
625
  handleAliasChange,
588
626
  urlAliasTemplate,
589
627
  handleCategoriesChange,
628
+
629
+ statusOptions
590
630
  };
591
- },
631
+ }
592
632
  });
593
633
  </script>
634
+
635
+ <style scoped lang='scss'>
636
+ .status {
637
+ display: flex;
638
+ align-items: flex-end;
639
+ }
640
+
641
+ .status-value {
642
+ flex-basis: 50%;
643
+ }
644
+
645
+ .status-checkbox {
646
+ margin-left: 20px;
647
+ padding-bottom: 8px;
648
+ }
649
+
650
+ .status-date {
651
+ margin-left: 20px;
652
+ flex: 1 1 1px;
653
+ }
654
+ </style>