@tager/admin-blog 0.3.21 → 0.3.25

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.
Files changed (86) hide show
  1. package/dist/index.esm.js +3452 -612
  2. package/dist/index.umd.js +3454 -619
  3. package/package.json +13 -7
  4. package/src/constants/menu.ts +0 -2
  5. package/src/constants/paths.ts +0 -5
  6. package/src/constants/routes.ts +5 -18
  7. package/src/constants/scopes.ts +11 -0
  8. package/src/dev.ts +11 -44
  9. package/src/hooks/index.ts +6 -0
  10. package/src/hooks/useBlogCategoryList.ts +3 -5
  11. package/src/hooks/useBlogPostList.ts +2 -4
  12. package/src/hooks/useModuleConfig.ts +4 -8
  13. package/src/hooks/useStore.ts +8 -0
  14. package/src/hooks/useUserPermission.ts +16 -0
  15. package/src/hooks/useUserProfile.ts +13 -0
  16. package/src/locales/en.ts +17 -5
  17. package/src/locales/ru.ts +17 -4
  18. package/src/router/index.ts +39 -0
  19. package/src/services/requests.ts +33 -43
  20. package/src/store/index.ts +21 -0
  21. package/src/store/user.ts +109 -0
  22. package/src/typings/common.ts +1 -0
  23. package/src/typings/model.ts +62 -38
  24. package/src/utils/common.ts +23 -0
  25. package/src/views/App.vue +10 -4
  26. package/src/views/{BlogCategoryForm/BlogCategoryForm.helpers.ts → Categories/CategoryForm/CategoryForm.helpers.ts} +22 -7
  27. package/src/views/{BlogCategoryForm/BlogCategoryForm.vue → Categories/CategoryForm/CategoryForm.vue} +140 -63
  28. package/src/views/Categories/CategoryForm/index.ts +1 -0
  29. package/src/views/Categories/CategoryList/CategoryList.helpers.ts +91 -0
  30. package/src/views/Categories/CategoryList/CategoryList.vue +269 -0
  31. package/src/views/Categories/CategoryList/hooks/index.ts +1 -0
  32. package/src/views/Categories/CategoryList/hooks/useAdvancedSearch.ts +95 -0
  33. package/src/views/Categories/CategoryList/index.ts +1 -0
  34. package/src/views/Home.vue +2 -9
  35. package/src/views/Posts/PostForm/PostForm.helpers.ts +150 -0
  36. package/src/views/Posts/PostForm/PostForm.vue +550 -0
  37. package/src/views/{BlogPostForm → Posts/PostForm}/components/TabList/TabList.types.ts +0 -0
  38. package/src/views/{BlogPostForm → Posts/PostForm}/components/TabList/TabList.vue +1 -1
  39. package/src/views/{BlogPostForm → Posts/PostForm}/components/TabList/index.ts +0 -0
  40. package/src/views/Posts/PostForm/index.ts +1 -0
  41. package/src/views/{BlogPostList/BlogPostList.helpers.ts → Posts/PostList/PostList.helpers.ts} +10 -18
  42. package/src/views/Posts/PostList/PostList.vue +361 -0
  43. package/src/views/Posts/PostList/hooks/index.ts +1 -0
  44. package/src/views/Posts/PostList/hooks/useAdvancedSearch.ts +250 -0
  45. package/src/views/Posts/PostList/index.ts +1 -0
  46. package/dist/constants/menu.d.ts +0 -5
  47. package/dist/constants/paths.d.ts +0 -16
  48. package/dist/constants/routes.d.ts +0 -6
  49. package/dist/dev.d.ts +0 -3
  50. package/dist/hooks/useBlogCategoryList.d.ts +0 -7
  51. package/dist/hooks/useBlogPostList.d.ts +0 -7
  52. package/dist/hooks/useModuleConfig.d.ts +0 -7
  53. package/dist/locales/en.d.ts +0 -63
  54. package/dist/locales/ru.d.ts +0 -3
  55. package/dist/main.d.ts +0 -4
  56. package/dist/services/requests.d.ts +0 -68
  57. package/dist/typings/model.d.ts +0 -74
  58. package/dist/views/BlogCategoryForm/BlogCategoryForm.helpers.d.ts +0 -16
  59. package/dist/views/BlogCategoryForm/BlogCategoryForm.vue.d.ts +0 -86
  60. package/dist/views/BlogCategoryForm/index.d.ts +0 -1
  61. package/dist/views/BlogCategoryList/BlogCategoryList.helpers.d.ts +0 -6
  62. package/dist/views/BlogCategoryList/BlogCategoryList.vue.d.ts +0 -3
  63. package/dist/views/BlogCategoryList/index.d.ts +0 -1
  64. package/dist/views/BlogPostForm/BlogPostForm.helpers.d.ts +0 -27
  65. package/dist/views/BlogPostForm/BlogPostForm.vue.d.ts +0 -9320
  66. package/dist/views/BlogPostForm/components/TabList/TabList.types.d.ts +0 -5
  67. package/dist/views/BlogPostForm/components/TabList/index.d.ts +0 -2
  68. package/dist/views/BlogPostForm/index.d.ts +0 -1
  69. package/dist/views/BlogPostList/BlogPostList.helpers.d.ts +0 -6
  70. package/dist/views/BlogPostList/BlogPostList.vue.d.ts +0 -45
  71. package/dist/views/BlogPostList/index.d.ts +0 -1
  72. package/dist/views/BlogSettings/BlogSettings.helpers.d.ts +0 -6
  73. package/dist/views/BlogSettings/BlogSettings.vue.d.ts +0 -9132
  74. package/dist/views/BlogSettings/index.d.ts +0 -1
  75. package/src/views/BlogCategoryForm/index.ts +0 -1
  76. package/src/views/BlogCategoryList/BlogCategoryList.helpers.ts +0 -82
  77. package/src/views/BlogCategoryList/BlogCategoryList.vue +0 -196
  78. package/src/views/BlogCategoryList/index.ts +0 -1
  79. package/src/views/BlogPostForm/BlogPostForm.helpers.ts +0 -152
  80. package/src/views/BlogPostForm/BlogPostForm.vue +0 -534
  81. package/src/views/BlogPostForm/index.ts +0 -1
  82. package/src/views/BlogPostList/BlogPostList.vue +0 -174
  83. package/src/views/BlogPostList/index.ts +0 -1
  84. package/src/views/BlogSettings/BlogSettings.helpers.ts +0 -25
  85. package/src/views/BlogSettings/BlogSettings.vue +0 -110
  86. package/src/views/BlogSettings/index.ts +0 -1
@@ -1,534 +0,0 @@
1
- <template>
2
- <page
3
- :title="isCreation ? $t('blog:createPost') : $t('blog:updatePost')"
4
- :is-content-loading="isContentLoading"
5
- :header-buttons="headerButtonList"
6
- :footer="{
7
- backHref: postListUrl,
8
- onSubmit: submitForm,
9
- isSubmitting: isSubmitting,
10
- }"
11
- >
12
- <template v-slot:content>
13
- <form novalidate @submit.prevent="submitForm">
14
- <tab-list
15
- :tab-list="tabList"
16
- :selected-tab-id="selectedTabId"
17
- @tab:update="selectedTabId = $event.tabId"
18
- />
19
-
20
- <template v-if="selectedTabId === 'common'">
21
- <form-field-select
22
- v-if="isCreation && isLangSpecific"
23
- v-model="values.language"
24
- name="language"
25
- :label="$t('blog:language')"
26
- :options="languageOptionList"
27
- :error="errors.language"
28
- />
29
-
30
- <form-field
31
- v-model="values.title"
32
- name="title"
33
- :label="$t('blog:title')"
34
- :error="errors.title"
35
- @input="handleTitleChange"
36
- />
37
-
38
- <form-field-url-alias-input
39
- id="urlAlias"
40
- v-model="values.urlAlias"
41
- name="urlAlias"
42
- :label="$t('blog:URLAlias')"
43
- :url-template="urlAliasTemplate"
44
- :error="errors.urlAlias"
45
- @change="handleAliasChange"
46
- />
47
-
48
- <form-field
49
- v-model="values.excerpt"
50
- name="excerpt"
51
- :label="$t('blog:excerpt')"
52
- type="textarea"
53
- :error="errors.excerpt"
54
- />
55
- <form-field-rich-text-input
56
- v-model="values.body"
57
- name="body"
58
- :label="$t('blog:body')"
59
- :error="errors.body"
60
- :get-upload-adapter-options="getUploadAdapterOptions"
61
- />
62
- <ShortCodeConstructor
63
- :short-code-config-list="
64
- moduleConfig ? moduleConfig.shortcodes : []
65
- "
66
- />
67
-
68
- <form-field
69
- v-model="values.date"
70
- name="date"
71
- :label="$t('blog:date')"
72
- type="date"
73
- :error="errors.date"
74
- />
75
- </template>
76
-
77
- <template v-if="selectedTabId === 'images'">
78
- <form-field-file-input
79
- v-model="values.coverImage"
80
- :label="$t('blog:coverImage')"
81
- name="coverImage"
82
- file-type="image"
83
- :scenario="moduleConfig ? moduleConfig.fileScenarios.cover : null"
84
- />
85
-
86
- <form-field-file-input
87
- v-model="values.image"
88
- name="image"
89
- :label="$t('blog:innerImage')"
90
- file-type="image"
91
- :scenario="moduleConfig ? moduleConfig.fileScenarios.image : null"
92
- />
93
-
94
- <form-field-file-input
95
- v-model="values.imageMobile"
96
- name="imageMobile"
97
- :label="$t('blog:innerImageMobile')"
98
- file-type="image"
99
- :scenario="moduleConfig ? moduleConfig.fileScenarios.imageMobile : null"
100
- />
101
- </template>
102
-
103
- <template v-if="selectedTabId === 'relations'">
104
- <form-field
105
- v-model="values.tags"
106
- name="tags"
107
- :label="$t('blog:tags')"
108
- :error="errors.tags"
109
- />
110
-
111
- <form-field-multi-select
112
- v-model="values.categories"
113
- name="categories"
114
- :label="$t('blog:categories')"
115
- :options="categoryOptionList"
116
- :error="errors.categories"
117
- />
118
-
119
- <form-field-multi-select
120
- v-model="values.relatedPosts"
121
- name="relatedPosts"
122
- :label="$t('blog:relatedPosts')"
123
- :options="postOptionList"
124
- :error="errors.relatedPosts"
125
- :searchable="true"
126
- />
127
- </template>
128
-
129
- <template v-if="selectedTabId === 'additional'">
130
- <DynamicField
131
- v-for="field of values.additionalFields"
132
- :key="field.name"
133
- :field="field"
134
- />
135
- </template>
136
-
137
- <template v-if="selectedTabId === 'seo'">
138
- <seo-field-group
139
- :title="values.pageTitle"
140
- :title-error-message="errors.pageTitle"
141
- :title-label="$t('blog:pageTitle')"
142
- :description="values.pageDescription"
143
- :description-error-message="errors.pageDescription"
144
- :description-label="$t('blog:pageDescription')"
145
- :image="values.openGraphImage"
146
- :image-error-message="errors.openGraphImage"
147
- :image-label="$t('blog:openGraphImage')"
148
- :image-scenario="moduleConfig ? moduleConfig.fileScenarios.openGraph : null"
149
- @change="handleSeoFieldGroupChange"
150
- />
151
- </template>
152
- </form>
153
- </template>
154
-
155
- <template v-slot:footer>
156
- <FormFooter
157
- :back-href="postListUrl"
158
- :on-submit="submitForm"
159
- :is-submitting="isSubmitting"
160
- :is-creation="isCreation"
161
- :can-create-another="isCreation"
162
- />
163
- </template>
164
- </page>
165
- </template>
166
-
167
- <script lang="ts">
168
- import {
169
- computed,
170
- defineComponent,
171
- onMounted,
172
- ref,
173
- watch,
174
- } from '@vue/composition-api';
175
-
176
- import {
177
- convertRequestErrorToMap,
178
- isNotNullish,
179
- Nullable,
180
- useResource,
181
- urlTranslit,
182
- } from '@tager/admin-services';
183
- import {
184
- createTabErrorFinder,
185
- OptionType,
186
- TabType,
187
- ShortCodeConstructor,
188
- SeoChangeEvent,
189
- FormFooter,
190
- TagerFormSubmitEvent,
191
- } from '@tager/admin-ui';
192
- import {DynamicField} from '@tager/admin-dynamic-field';
193
-
194
- import {
195
- createBlogPost,
196
- getBlogPost,
197
- updateBlogPost,
198
- } from '../../services/requests';
199
- import {PostFull} from '../../typings/model';
200
- import {getBlogPostFormUrl, getBlogPostListUrl} from '../../constants/paths';
201
- import useModuleConfig from '../../hooks/useModuleConfig';
202
- import useBlogCategoryList from '../../hooks/useBlogCategoryList';
203
- import useBlogPostList from '../../hooks/useBlogPostList';
204
-
205
- import {
206
- convertCategoryListToOptions,
207
- convertFormValuesToCreationPayload,
208
- convertFormValuesToUpdatePayload,
209
- convertPostToFormValues,
210
- FormValues,
211
- } from './BlogPostForm.helpers';
212
-
213
- export default defineComponent({
214
- name: 'BlogPostForm',
215
- components: {DynamicField, ShortCodeConstructor, FormFooter},
216
- setup(props, context) {
217
- const postId = computed<string>(() => context.root.$route.params.postId);
218
- const isCreation = computed<boolean>(() => postId.value === 'create');
219
-
220
- const urlAliasChanged = ref<boolean>(false);
221
-
222
- /** Fetch module config */
223
- const {
224
- data: moduleConfig,
225
- loading: isModuleConfigLoading,
226
- } = useModuleConfig({context});
227
-
228
- const languageOptionList = computed<Array<OptionType>>(
229
- () =>
230
- moduleConfig.value?.languages.map((lang) => ({
231
- value: lang.id,
232
- label: lang.name,
233
- })) ?? []
234
- );
235
-
236
- const isLangSpecific = computed(() => languageOptionList.value.length > 0);
237
-
238
- /** Fetch category list */
239
- const {
240
- data: categoryList,
241
- loading: isCategoryListLoading,
242
- } = useBlogCategoryList({context});
243
-
244
- /** Fetch Post */
245
-
246
- const [fetchPost, {data: post, loading: isPostLoading}] = useResource<Nullable<PostFull>>({
247
- fetchResource: () => getBlogPost(postId.value),
248
- initialValue: null,
249
- context,
250
- resourceName: 'Post',
251
- });
252
-
253
- onMounted(() => {
254
- if (isCreation.value) return;
255
-
256
- fetchPost();
257
- });
258
-
259
- watch(postId, () => {
260
- if (isCreation.value) return;
261
-
262
- fetchPost();
263
- });
264
-
265
- /** Fetch post list */
266
- const {data: postList, loading: isPostListLoading} = useBlogPostList({
267
- context,
268
- });
269
-
270
- const postOptionList = computed<Array<OptionType<number>>>(() =>
271
- postList.value
272
- .filter((relatedPost) => relatedPost.id !== post.value?.id)
273
- .map((post) => ({
274
- value: post.id,
275
- label: post.title,
276
- }))
277
- );
278
-
279
- /** Form State */
280
- const values = ref<FormValues>(
281
- convertPostToFormValues(
282
- post.value,
283
- languageOptionList.value,
284
- postOptionList.value,
285
- moduleConfig.value?.fields ?? []
286
- )
287
- );
288
- const errors = ref<Record<string, string>>({});
289
- const isSubmitting = ref<boolean>(false);
290
-
291
- watch([post, languageOptionList, postOptionList, moduleConfig], () => {
292
- values.value = convertPostToFormValues(
293
- post.value,
294
- languageOptionList.value,
295
- postOptionList.value,
296
- moduleConfig.value?.fields ?? []
297
- );
298
- });
299
-
300
- function submitForm(event: TagerFormSubmitEvent) {
301
- isSubmitting.value = true;
302
-
303
- const creationBody = convertFormValuesToCreationPayload(values.value);
304
- const updateBody = convertFormValuesToUpdatePayload(values.value);
305
-
306
- const requestPromise = isCreation.value
307
- ? createBlogPost(creationBody)
308
- : updateBlogPost(postId.value, updateBody);
309
-
310
- requestPromise
311
- .then(({data}) => {
312
- errors.value = {};
313
-
314
- if (event.type === 'create') {
315
- context.root.$router.push(
316
- getBlogPostFormUrl({postId: String(data.id)})
317
- );
318
- }
319
-
320
- if (event.type === 'create_exit' || event.type === 'save_exit') {
321
- if (context.root.$previousRoute) {
322
- context.root.$router.back();
323
- } else {
324
- context.root.$router.push(getBlogPostListUrl());
325
- }
326
- }
327
-
328
- if (event.type === 'create_create-another') {
329
- values.value = convertPostToFormValues(
330
- null,
331
- languageOptionList.value,
332
- postOptionList.value,
333
- moduleConfig.value?.fields ?? []
334
- );
335
- }
336
-
337
- context.root.$toast({
338
- variant: 'success',
339
- title: context.root.$t('blog:success'),
340
- body: isCreation.value
341
- ? context.root.$t('blog:blogPostWasSuccessfullyCreated')
342
- : context.root.$t('blog:blogPostWasSuccessfullyUpdated'),
343
- });
344
- })
345
- .catch((error) => {
346
- console.error(error);
347
- errors.value = convertRequestErrorToMap(error);
348
- context.root.$toast({
349
- variant: 'danger',
350
- title: context.root.$t('blog:error'),
351
- body: isCreation.value
352
- ? context.root.$t('blog:blogPostCreationWasFailed')
353
- : context.root.$t('blog:blogPostUpdateWasFailed'),
354
- });
355
- })
356
- .finally(() => {
357
- isSubmitting.value = false;
358
- });
359
- }
360
-
361
- /** Category Options */
362
-
363
- const categoryOptionList = computed<Array<OptionType<number>>>(() =>
364
- convertCategoryListToOptions(
365
- categoryList.value,
366
- values.value.language?.value ?? null
367
- )
368
- );
369
-
370
- watch([categoryOptionList, moduleConfig], () => {
371
- function isOptionExist(
372
- selectedCategoryOption: OptionType<number>
373
- ): boolean {
374
- return categoryOptionList.value.some(
375
- (option) => option.value === selectedCategoryOption.value
376
- );
377
- }
378
-
379
- if (isCreation.value) {
380
- if (moduleConfig?.value?.defaultCategories) {
381
- const defaultIds = moduleConfig.value.defaultCategories.map((item: { id: number }) => item.id);
382
- values.value.categories = categoryOptionList.value.filter((item: OptionType<number>) => {
383
- return defaultIds.indexOf(item.value) !== -1;
384
- });
385
- }
386
- }
387
-
388
- values.value.categories = values.value.categories.filter(isOptionExist);
389
- });
390
-
391
- /** Misc */
392
-
393
- const isContentLoading = computed<boolean>(
394
- () =>
395
- isPostLoading.value ||
396
- isCategoryListLoading.value ||
397
- isPostListLoading.value ||
398
- isModuleConfigLoading.value
399
- );
400
-
401
- function getUploadAdapterOptions() {
402
- return {uploadScenario: moduleConfig.value?.fileScenarios.content};
403
- }
404
-
405
- const blogPagePath = computed<string>(() => {
406
- const origin = process.env.VUE_APP_WEBSITE_URL || window.location.origin;
407
- return origin + (post.value?.urlTemplate ?? '');
408
- });
409
-
410
- const tabList = computed<Array<TabType>>(() => {
411
- const hasErrors = createTabErrorFinder(errors.value);
412
- return [
413
- {
414
- id: 'common',
415
- label: context.root.$t('blog:common'),
416
- hasErrors: hasErrors([
417
- 'title',
418
- 'language',
419
- 'urlAlias',
420
- 'excerpt',
421
- 'body',
422
- 'date',
423
- ]),
424
- },
425
- {
426
- id: 'images',
427
- label: context.root.$t('blog:images'),
428
- hasErrors: hasErrors(['coverImage', 'image']),
429
- },
430
- {
431
- id: 'relations',
432
- label: context.root.$t('blog:relations'),
433
- hasErrors: hasErrors(['categories', 'relatedPosts', 'tags']),
434
- },
435
- values.value.additionalFields.length > 0
436
- ? {
437
- id: 'additional',
438
- label: context.root.$t('blog:additionalFields'),
439
- hasErrors: hasErrors([]),
440
- }
441
- : null,
442
- {
443
- id: 'seo',
444
- label: 'SEO',
445
- hasErrors: hasErrors([
446
- 'pageTitle',
447
- 'pageDescription',
448
- 'openGraphImage',
449
- ]),
450
- },
451
- ].filter(isNotNullish);
452
- });
453
-
454
- const selectedTabId = ref<string>(tabList.value[0].id);
455
-
456
- const headerButtonList = computed<Array<{ text: string; href: string; target?: string }>>(() =>
457
- [
458
- post.value
459
- ? {
460
- text: context.root.$t('blog:viewPost'),
461
- href: process.env.VUE_APP_WEBSITE_URL + post.value.url,
462
- target: '_blank',
463
- }
464
- : null,
465
- ].filter(isNotNullish)
466
- );
467
-
468
- function handleSeoFieldGroupChange({
469
- title,
470
- description,
471
- image,
472
- }: SeoChangeEvent) {
473
- values.value.pageTitle = title;
474
- values.value.pageDescription = description;
475
- values.value.openGraphImage = image;
476
- }
477
-
478
- function handleTitleChange(value: string) {
479
- if (urlAliasChanged.value === false) {
480
- values.value.urlAlias = urlTranslit(value);
481
- }
482
- }
483
-
484
- function handleAliasChange() {
485
- urlAliasChanged.value = true;
486
- }
487
-
488
- const urlAliasTemplate = computed<string>(() => {
489
- if (!moduleConfig.value || !moduleConfig.value.urlPostTemplate) {
490
- return '';
491
- }
492
-
493
- let result = moduleConfig.value.urlPostTemplate;
494
-
495
- if (values.value.language) {
496
- result = result.replace('{language}', values.value.language.value);
497
- }
498
-
499
- if (postId.value !== 'create') {
500
- result = result.replace('{id}', postId.value);
501
- }
502
-
503
- return result;
504
- });
505
-
506
- return {
507
- isCreation,
508
- postId,
509
- pagePath: blogPagePath,
510
- categoryOptionList,
511
- values,
512
- errors,
513
- isContentLoading,
514
- postListUrl: getBlogPostListUrl(),
515
- submitForm,
516
- isLangSpecific,
517
- languageOptionList,
518
- isSubmitting,
519
- moduleConfig,
520
- postOptionList,
521
- getUploadAdapterOptions,
522
- tabList,
523
- selectedTabId,
524
- headerButtonList,
525
- handleSeoFieldGroupChange,
526
- handleTitleChange,
527
- handleAliasChange,
528
- urlAliasTemplate
529
- };
530
- },
531
- });
532
- </script>
533
-
534
- <style scoped lang="scss"></style>
@@ -1 +0,0 @@
1
- export { default } from './BlogPostForm.vue';
@@ -1,174 +0,0 @@
1
- <template>
2
- <page
3
- :title="pageTitle"
4
- :header-buttons="[
5
- {
6
- text: $t('blog:newPost'),
7
- href: getBlogPostFormUrl({ postId: 'create' }),
8
- },
9
- ]"
10
- >
11
- <template v-slot:content>
12
- <data-table
13
- :column-defs="columnDefs"
14
- :row-data="rowData"
15
- :loading="isRowDataLoading"
16
- :error-message="errorMessage"
17
- :search-query="searchQuery"
18
- :pagination="{
19
- pageNumber,
20
- pageCount,
21
- pageSize,
22
- disabled: isRowDataLoading,
23
- }"
24
- data-table="blog-post"
25
- @change="handleChange"
26
- >
27
- <template v-slot:cell(actions)="{ row }">
28
- <base-button
29
- variant="icon"
30
- :title="$t('blog:edit')"
31
- :disabled="isDeleting(row.id)"
32
- :href="getBlogPostFormUrl({ postId: row.id })"
33
- >
34
- <svg-icon name="edit"></svg-icon>
35
- </base-button>
36
- <base-button
37
- variant="icon"
38
- :title="$t('blog:remove')"
39
- :disabled="isDeleting(row.id)"
40
- @click="handleResourceDelete(row.id)"
41
- >
42
- <svg-icon name="delete"></svg-icon>
43
- </base-button>
44
- </template>
45
- </data-table>
46
- </template>
47
- </page>
48
- </template>
49
-
50
- <script lang="ts">
51
- import { computed, defineComponent } from '@vue/composition-api';
52
-
53
- import { ColumnDefinition, useDataTable } from '@tager/admin-ui';
54
- import { Nullable, useResourceDelete } from '@tager/admin-services';
55
-
56
- import { BlogCategory, PostShort } from '../../typings/model';
57
- import { deleteBlogPost, getBlogPostList } from '../../services/requests';
58
- import { getBlogPostFormUrl } from '../../constants/paths';
59
- import useModuleConfig from '../../hooks/useModuleConfig';
60
- import useBlogCategoryList from '../../hooks/useBlogCategoryList';
61
-
62
- import {
63
- convertPostList,
64
- getPostTableColumnDefs,
65
- } from './BlogPostList.helpers';
66
-
67
- export default defineComponent({
68
- name: 'BlogPostList',
69
- setup(props, context) {
70
- const categoryId = computed<string>(() => {
71
- return Array.isArray(context.root.$route.query.category)
72
- ? context.root.$route.query.category[0] ?? ''
73
- : context.root.$route.query.category;
74
- });
75
-
76
- /** Fetch module config */
77
- const {
78
- data: moduleConfig,
79
- loading: isModuleConfigLoading,
80
- } = useModuleConfig({ context });
81
-
82
- /** Fetch category list */
83
- const {
84
- data: categoryList,
85
- loading: isCategoryListLoading,
86
- } = useBlogCategoryList({ context });
87
-
88
- const selectedCategory = computed<Nullable<BlogCategory>>(() =>
89
- categoryId.value
90
- ? categoryList.value.find(
91
- (category) => String(category.id) === String(categoryId.value)
92
- ) ?? null
93
- : null
94
- );
95
-
96
- const pageTitle = computed<string>(() => {
97
- return selectedCategory.value
98
- ? `${context.root.$t('blog:postsByCategory')} "${
99
- selectedCategory.value.name
100
- }"`
101
- : context.root.$t('blog:posts');
102
- });
103
-
104
- /** Fetch Post list */
105
- const {
106
- fetchEntityList: fetchPostList,
107
- isLoading: isPostLoading,
108
- rowData: postList,
109
- errorMessage,
110
- searchQuery,
111
- handleChange,
112
- pageNumber,
113
- pageCount,
114
- pageSize,
115
- } = useDataTable<PostShort>({
116
- fetchEntityList: (params) =>
117
- getBlogPostList({
118
- query: params.searchQuery,
119
- pageNumber: params.pageNumber,
120
- pageSize: params.pageSize,
121
- }),
122
- initialValue: [],
123
- context,
124
- resourceName: 'Blog post list',
125
- pageSize: 100,
126
- });
127
-
128
- const displayedPostList = computed<Array<PostShort>>(() =>
129
- convertPostList(
130
- postList.value,
131
- selectedCategory.value,
132
- moduleConfig.value?.languages ?? []
133
- )
134
- );
135
-
136
- const { handleResourceDelete, isDeleting } = useResourceDelete({
137
- deleteResource: deleteBlogPost,
138
- resourceName: 'Post',
139
- onSuccess: fetchPostList,
140
- context,
141
- });
142
-
143
- const isRowDataLoading = computed<boolean>(
144
- () =>
145
- isCategoryListLoading.value ||
146
- isPostLoading.value ||
147
- isModuleConfigLoading.value
148
- );
149
-
150
- const columnDefs = computed<Array<ColumnDefinition<PostShort>>>(() =>
151
- getPostTableColumnDefs(moduleConfig.value, context.root.$t)
152
- );
153
-
154
- return {
155
- columnDefs,
156
- rowData: displayedPostList,
157
- handleResourceDelete,
158
- isDeleting,
159
- categoryList,
160
- isRowDataLoading,
161
- errorMessage,
162
- getBlogPostFormUrl,
163
- pageTitle,
164
- searchQuery,
165
- handleChange,
166
- pageNumber,
167
- pageCount,
168
- pageSize,
169
- };
170
- },
171
- });
172
- </script>
173
-
174
- <style scoped lang="scss"></style>
@@ -1 +0,0 @@
1
- export { default } from './BlogPostList.vue';