@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
@@ -0,0 +1,361 @@
1
+ <template>
2
+ <page
3
+ :title="pageTitle"
4
+ :header-buttons="
5
+ [
6
+ canViewAdministrators
7
+ ? {
8
+ text: $t('blog:newPost'),
9
+ href: getBlogPostFormUrl({ postId: 'create' }),
10
+ }
11
+ : null,
12
+ ].filter(Boolean)
13
+ "
14
+ >
15
+ <template v-slot:content>
16
+ <data-table
17
+ :column-defs="columnDefs"
18
+ :row-data="rowData"
19
+ :loading="isRowDataLoading"
20
+ :error-message="errorMessage"
21
+ :search-query="searchQuery"
22
+ :pagination="{
23
+ pageNumber,
24
+ pageCount,
25
+ pageSize,
26
+ disabled: isRowDataLoading,
27
+ }"
28
+ data-table="blog-post"
29
+ @change="handleChange"
30
+ >
31
+ <template v-slot:filters>
32
+ <advanced-search :tags="tags" @click:tag="tagRemovalHandler">
33
+ <div class="filters">
34
+ <form-field-multi-select
35
+ v-model="categoryFilter"
36
+ :options="categoryOptionList"
37
+ name="categoryFilter"
38
+ :searchable="true"
39
+ :label="$t('blog:category')"
40
+ class="filter"
41
+ />
42
+
43
+ <form-field-multi-select
44
+ v-if="isLangSpecific"
45
+ v-model="languageFilter"
46
+ :options="languageOptionList"
47
+ name="languageFilter"
48
+ :searchable="true"
49
+ :label="$t('blog:language')"
50
+ class="filter"
51
+ />
52
+
53
+ <div class="filter">
54
+ <div class="date-label">
55
+ {{ $t('blog:dateOfPublication') }}
56
+ </div>
57
+
58
+ <div class="date-content">
59
+ <form-field
60
+ v-model="fromDateFilter"
61
+ :label="$t('blog:From')"
62
+ name="fromDateFilter"
63
+ type="date"
64
+ :max="toDateFilter"
65
+ />
66
+
67
+ <form-field
68
+ v-model="toDateFilter"
69
+ :label="$t('blog:To')"
70
+ name="toDateFilter"
71
+ type="date"
72
+ :min="fromDateFilter"
73
+ />
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </advanced-search>
78
+ </template>
79
+
80
+ <template v-slot:cell(actions)="{ row }">
81
+ <base-button
82
+ v-if="canViewAdministrators"
83
+ variant="icon"
84
+ :title="$t('blog:edit')"
85
+ :disabled="isBusy(row.id)"
86
+ :href="getBlogPostFormUrl({ postId: row.id })"
87
+ >
88
+ <svg-icon name="edit" />
89
+ </base-button>
90
+
91
+ <base-button
92
+ variant="icon"
93
+ :title="$t('blog:clone')"
94
+ :disabled="isBusy(row.id)"
95
+ @click="handleResourceClone(row.id)"
96
+ >
97
+ <svg-icon name="contentCopy" />
98
+ </base-button>
99
+
100
+ <base-button
101
+ v-if="canViewAdministrators"
102
+ variant="icon"
103
+ :title="$t('blog:remove')"
104
+ :disabled="isBusy(row.id)"
105
+ @click="handleResourceDelete(row.id)"
106
+ >
107
+ <svg-icon name="delete" />
108
+ </base-button>
109
+ </template>
110
+ </data-table>
111
+ </template>
112
+ </page>
113
+ </template>
114
+
115
+ <script lang="ts">
116
+ import { computed, defineComponent, watch } from '@vue/composition-api';
117
+ import isEqual from 'lodash.isequal';
118
+ import pick from 'lodash.pick';
119
+
120
+ import {
121
+ ColumnDefinition,
122
+ useDataTable,
123
+ useTranslation,
124
+ } from '@tager/admin-ui';
125
+ import {
126
+ Nullable,
127
+ useResourceClone,
128
+ useResourceDelete,
129
+ } from '@tager/admin-services';
130
+
131
+ import { Category, Language, PostFull, PostShort } from '@/typings/model';
132
+ import {
133
+ clonePost,
134
+ deleteBlogPost,
135
+ getBlogPostList,
136
+ } from '@/services/requests';
137
+ import { getBlogPostFormUrl } from '@/constants/paths';
138
+ import {
139
+ useModuleConfig,
140
+ useBlogCategoryList,
141
+ useUserPermission,
142
+ } from '@/hooks';
143
+ import { Scope } from '@/constants/scopes';
144
+
145
+ import { convertPostList, getPostTableColumnDefs } from './PostList.helpers';
146
+ import { useAdvancedSearch } from './hooks';
147
+
148
+ export default defineComponent({
149
+ name: 'BlogPostList',
150
+ setup(props, context) {
151
+ const { t } = useTranslation(context);
152
+
153
+ const canViewAdministrators = useUserPermission(
154
+ context,
155
+ Scope.AdministratorsView
156
+ );
157
+
158
+ const categoryId = computed<string>(() => {
159
+ return Array.isArray(context.root.$route.query.category)
160
+ ? context.root.$route.query.category[0] ?? ''
161
+ : context.root.$route.query.category;
162
+ });
163
+
164
+ /** Fetch module config */
165
+ const {
166
+ data: moduleConfig,
167
+ loading: isModuleConfigLoading,
168
+ } = useModuleConfig({ context });
169
+
170
+ const languageList = computed<Language[]>(
171
+ () => moduleConfig.value?.languages ?? []
172
+ );
173
+
174
+ /** Fetch category list */
175
+ const {
176
+ data: categoryList,
177
+ loading: isCategoryListLoading,
178
+ } = useBlogCategoryList({ context });
179
+
180
+ const selectedCategory = computed<Nullable<Category>>(() =>
181
+ categoryId.value
182
+ ? categoryList.value.find(
183
+ ({ id }) => String(id) === String(categoryId.value)
184
+ ) ?? null
185
+ : null
186
+ );
187
+
188
+ const pageTitle = computed<string>(() => {
189
+ return selectedCategory.value
190
+ ? `${context.root.$t('blog:postsByCategory')} "${
191
+ selectedCategory.value.name
192
+ }"`
193
+ : context.root.$t('blog:posts');
194
+ });
195
+
196
+ /** Advanced search **/
197
+
198
+ const {
199
+ categoryFilter,
200
+ categoryOptionList,
201
+ languageFilter,
202
+ languageOptionList,
203
+ fromDateFilter,
204
+ toDateFilter,
205
+ filterParams,
206
+ tags,
207
+ tagRemovalHandler,
208
+ } = useAdvancedSearch({
209
+ context,
210
+ categoryList,
211
+ languageList,
212
+ });
213
+
214
+ const isLangSpecific = computed<boolean>(
215
+ () => languageOptionList.value.length > 1
216
+ );
217
+
218
+ /** Fetch Post list */
219
+ const {
220
+ fetchEntityList: fetchPostList,
221
+ isLoading: isPostLoading,
222
+ rowData: postList,
223
+ errorMessage,
224
+ searchQuery,
225
+ handleChange,
226
+ pageNumber,
227
+ pageCount,
228
+ pageSize,
229
+ } = useDataTable<PostShort>({
230
+ fetchEntityList: (params) =>
231
+ getBlogPostList({
232
+ query: params.searchQuery,
233
+ pageNumber: params.pageNumber,
234
+ pageSize: params.pageSize,
235
+ ...filterParams.value,
236
+ }),
237
+ initialValue: [],
238
+ context,
239
+ resourceName: 'Blog post list',
240
+ pageSize: 100,
241
+ });
242
+
243
+ watch(filterParams, () => {
244
+ if (isModuleConfigLoading.value || isCategoryListLoading.value) {
245
+ return;
246
+ }
247
+
248
+ const newQuery = {
249
+ ...pick(context.root.$route.query, ['query', 'pageNumber']),
250
+ ...filterParams.value,
251
+ };
252
+
253
+ if (!isEqual(context.root.$route.query, newQuery)) {
254
+ context.root.$router.replace({ query: newQuery });
255
+ fetchPostList();
256
+ }
257
+ });
258
+
259
+ const displayedPostList = computed<PostShort[]>(() =>
260
+ convertPostList(
261
+ postList.value,
262
+ selectedCategory.value,
263
+ moduleConfig.value?.languages ?? []
264
+ )
265
+ );
266
+
267
+ const isRowDataLoading = computed<boolean>(
268
+ () =>
269
+ isCategoryListLoading.value ||
270
+ isPostLoading.value ||
271
+ isModuleConfigLoading.value
272
+ );
273
+
274
+ const { isDeleting, handleResourceDelete } = useResourceDelete({
275
+ deleteResource: deleteBlogPost,
276
+ resourceName: 'Post',
277
+ onSuccess: fetchPostList,
278
+ context,
279
+ });
280
+
281
+ const { isCloning, handleResourceClone } = useResourceClone({
282
+ cloneResource: clonePost,
283
+ confirmMessage: t('blog:cloneConfirm'),
284
+ successMessage: t('blog:cloneSuccess'),
285
+ failureMessage: t('blog:cloneFailure'),
286
+ onSuccessRedirectTo: (data: PostFull) => `/posts/${data.id}`,
287
+ context,
288
+ });
289
+
290
+ function isBusy(postId: number): boolean {
291
+ return isDeleting(postId) || isCloning(postId) || isRowDataLoading.value;
292
+ }
293
+
294
+ const columnDefs = computed<ColumnDefinition<PostShort>[]>(() =>
295
+ getPostTableColumnDefs(moduleConfig.value, context.root.$t)
296
+ );
297
+
298
+ return {
299
+ columnDefs,
300
+ rowData: displayedPostList,
301
+ handleResourceDelete,
302
+ isDeleting,
303
+ categoryList,
304
+ isRowDataLoading,
305
+ errorMessage,
306
+ getBlogPostFormUrl,
307
+ pageTitle,
308
+ searchQuery,
309
+ handleChange,
310
+ pageNumber,
311
+ pageCount,
312
+ pageSize,
313
+
314
+ // Advanced search
315
+ categoryFilter,
316
+ categoryOptionList,
317
+ isLangSpecific,
318
+ languageFilter,
319
+ languageOptionList,
320
+ fromDateFilter,
321
+ toDateFilter,
322
+ tags,
323
+ tagRemovalHandler,
324
+
325
+ // Permissions
326
+ canViewAdministrators,
327
+
328
+ // Clone
329
+ handleResourceClone,
330
+ isBusy,
331
+ };
332
+ },
333
+ });
334
+ </script>
335
+
336
+ <style scoped lang="scss">
337
+ .filters {
338
+ display: flex;
339
+ margin: 0 -10px;
340
+
341
+ &:not(:first-child) {
342
+ margin-top: 10px;
343
+ }
344
+
345
+ .filter {
346
+ padding: 10px 10px 0;
347
+ width: 50%;
348
+ margin: 0;
349
+ }
350
+ }
351
+
352
+ .date-label {
353
+ margin-bottom: 0.5rem;
354
+ }
355
+
356
+ .date-content {
357
+ display: grid;
358
+ grid-template-columns: repeat(2, 1fr);
359
+ column-gap: 10px;
360
+ }
361
+ </style>
@@ -0,0 +1 @@
1
+ export { useAdvancedSearch } from './useAdvancedSearch';
@@ -0,0 +1,250 @@
1
+ import {
2
+ computed,
3
+ ComputedRef,
4
+ Ref,
5
+ ref,
6
+ SetupContext,
7
+ watch,
8
+ } from '@vue/composition-api';
9
+
10
+ import {
11
+ FilterTagType,
12
+ getFilterParamAsString,
13
+ getFilterParamAsStringArray,
14
+ getFilterParams,
15
+ OptionType,
16
+ } from '@tager/admin-ui';
17
+ import { isNotNullish } from '@tager/admin-services';
18
+
19
+ import { Category, Language } from '@/typings/model';
20
+ import { getNameWithDepth } from '@/utils/common';
21
+
22
+ interface Params {
23
+ context: SetupContext;
24
+ categoryList: ComputedRef<Category[]>;
25
+ languageList: ComputedRef<Language[]>;
26
+ }
27
+
28
+ interface State {
29
+ categoryFilter: Ref<OptionType[]>;
30
+ categoryOptionList: ComputedRef<OptionType[]>;
31
+ languageFilter: Ref<OptionType[]>;
32
+ languageOptionList: ComputedRef<OptionType[]>;
33
+ fromDateFilter: Ref<string>;
34
+ toDateFilter: Ref<string>;
35
+ filterParams: ComputedRef<Record<string, string | string[]>>;
36
+ tags: ComputedRef<FilterTagType[]>;
37
+ tagRemovalHandler(event: FilterTagType): void;
38
+ }
39
+
40
+ enum FilterTypes {
41
+ CATEGORY = 'category',
42
+ LANGUAGE = 'language',
43
+ FROM_DATE = 'from-date',
44
+ TO_DATE = 'to-date',
45
+ }
46
+
47
+ export const dateFormat = (date: string) => date.split('-').reverse().join('.');
48
+
49
+ export function useAdvancedSearch({
50
+ context,
51
+ categoryList,
52
+ languageList,
53
+ }: Params): State {
54
+ /** Category **/
55
+
56
+ const categoryOptionList = computed<OptionType[]>(() =>
57
+ categoryList.value.map(({ id, name, depth }) => ({
58
+ value: String(id),
59
+ label: getNameWithDepth(name, depth),
60
+ }))
61
+ );
62
+
63
+ const initialCategoryFilter = computed<OptionType[]>(() => {
64
+ const queryValue = getFilterParamAsStringArray(
65
+ context.root.$route.query,
66
+ FilterTypes.CATEGORY
67
+ );
68
+ return categoryOptionList.value.filter(({ value }) =>
69
+ queryValue.some((selected) => selected === value)
70
+ );
71
+ });
72
+
73
+ const categoryFilter = ref<OptionType[]>(initialCategoryFilter.value);
74
+
75
+ watch(initialCategoryFilter, () => {
76
+ categoryFilter.value = initialCategoryFilter.value;
77
+ });
78
+
79
+ /** Language **/
80
+
81
+ const languageOptionList = computed<OptionType[]>(() =>
82
+ languageList.value.map(({ id, name }) => ({ value: id, label: name }))
83
+ );
84
+
85
+ const initialLanguageFilter = computed<OptionType[]>(() => {
86
+ const queryValue = getFilterParamAsStringArray(
87
+ context.root.$route.query,
88
+ FilterTypes.LANGUAGE
89
+ );
90
+ return languageOptionList.value.filter(({ value }) =>
91
+ queryValue.some((selected) => selected === value)
92
+ );
93
+ });
94
+
95
+ const languageFilter = ref<OptionType[]>(initialLanguageFilter.value);
96
+
97
+ watch(initialLanguageFilter, () => {
98
+ languageFilter.value = initialLanguageFilter.value;
99
+ });
100
+
101
+ /** From date **/
102
+
103
+ const initialFromDateFilter = computed<string>(
104
+ () =>
105
+ getFilterParamAsString(
106
+ context.root.$route.query,
107
+ FilterTypes.FROM_DATE
108
+ ) ?? ''
109
+ );
110
+
111
+ const fromDateFilter = ref<string>(initialFromDateFilter.value);
112
+
113
+ watch(initialFromDateFilter, () => {
114
+ fromDateFilter.value = initialFromDateFilter.value;
115
+ });
116
+
117
+ /** To date **/
118
+
119
+ const initialToDateFilter = computed<string>(
120
+ () =>
121
+ getFilterParamAsString(context.root.$route.query, FilterTypes.TO_DATE) ??
122
+ ''
123
+ );
124
+
125
+ const toDateFilter = ref<string>(initialToDateFilter.value);
126
+
127
+ watch(initialToDateFilter, () => {
128
+ toDateFilter.value = initialToDateFilter.value;
129
+ });
130
+
131
+ /** Date **/
132
+
133
+ const date = computed<FilterTagType | null>(() => {
134
+ if (!fromDateFilter.value && !toDateFilter.value) {
135
+ return null;
136
+ }
137
+
138
+ let label = '';
139
+
140
+ if (fromDateFilter.value && toDateFilter.value) {
141
+ label = `${dateFormat(fromDateFilter.value)} - ${dateFormat(
142
+ toDateFilter.value
143
+ )}`;
144
+ }
145
+
146
+ if (fromDateFilter.value && !toDateFilter.value) {
147
+ label = `${context.root.$t('blog:from')} ${dateFormat(
148
+ fromDateFilter.value
149
+ )}`;
150
+ }
151
+
152
+ if (!fromDateFilter.value && toDateFilter.value) {
153
+ label = `${context.root.$t('blog:to')} ${dateFormat(toDateFilter.value)}`;
154
+ }
155
+
156
+ return {
157
+ value: '',
158
+ label,
159
+ name: FilterTypes.FROM_DATE,
160
+ title: context.root.$t('blog:dateOfPublication'),
161
+ };
162
+ });
163
+
164
+ /** Params **/
165
+
166
+ const filterParams = computed(() => {
167
+ const filters: Record<string, string | string[]> = {
168
+ [FilterTypes.CATEGORY]: categoryFilter.value.map(({ value }) => value),
169
+ [FilterTypes.LANGUAGE]: languageFilter.value.map(({ value }) => value),
170
+ };
171
+
172
+ if (fromDateFilter.value) {
173
+ filters[FilterTypes.FROM_DATE] = fromDateFilter.value;
174
+ }
175
+
176
+ if (toDateFilter.value) {
177
+ filters[FilterTypes.TO_DATE] = toDateFilter.value;
178
+ }
179
+
180
+ return getFilterParams(filters);
181
+ });
182
+
183
+ /** Tag removal handler **/
184
+
185
+ function tagRemovalHandler(event: FilterTagType) {
186
+ if (event.name === FilterTypes.CATEGORY) {
187
+ categoryFilter.value = categoryFilter.value.filter(
188
+ ({ value }) => value !== event.value
189
+ );
190
+ }
191
+ if (event.name === FilterTypes.LANGUAGE) {
192
+ languageFilter.value = languageFilter.value.filter(
193
+ ({ value }) => value !== event.value
194
+ );
195
+ }
196
+ if (event.name === FilterTypes.FROM_DATE) {
197
+ fromDateFilter.value = '';
198
+ toDateFilter.value = '';
199
+ }
200
+ }
201
+
202
+ /** Tags **/
203
+
204
+ const tags = computed<FilterTagType[]>(() =>
205
+ [
206
+ ...categoryFilter.value.map(({ value, label }) => ({
207
+ value,
208
+ label,
209
+ name: FilterTypes.CATEGORY,
210
+ title: context.root.$t('blog:category'),
211
+ })),
212
+ ...languageFilter.value.map(({ value, label }) => ({
213
+ value,
214
+ label,
215
+ name: FilterTypes.LANGUAGE,
216
+ title: context.root.$t('blog:language'),
217
+ })),
218
+ date.value,
219
+ ].filter(isNotNullish)
220
+ );
221
+
222
+ /** Helpers **/
223
+
224
+ const selectedCategoryOptionList = computed<OptionType[]>(() => {
225
+ if (languageFilter.value.length === 0) {
226
+ return categoryOptionList.value;
227
+ }
228
+
229
+ const selectedList = categoryList.value.filter(({ language }) =>
230
+ languageFilter.value.some(({ value }) => value === language)
231
+ );
232
+
233
+ return selectedList.map(({ id, name, depth }) => ({
234
+ value: String(id),
235
+ label: getNameWithDepth(name, depth),
236
+ }));
237
+ });
238
+
239
+ return {
240
+ categoryFilter,
241
+ categoryOptionList: selectedCategoryOptionList,
242
+ languageFilter,
243
+ languageOptionList,
244
+ fromDateFilter,
245
+ toDateFilter,
246
+ tagRemovalHandler,
247
+ tags: tags,
248
+ filterParams,
249
+ };
250
+ }
@@ -0,0 +1 @@
1
+ export { default } from './PostList.vue';
@@ -1,5 +0,0 @@
1
- import { MenuItemType } from '@tager/admin-layout';
2
- import { TranslateFunction } from '@tager/admin-services';
3
- export declare function getBlogMenuItem(params: {
4
- t: TranslateFunction;
5
- }): MenuItemType;
@@ -1,16 +0,0 @@
1
- export declare const BLOG_ROUTE_PATHS: {
2
- readonly POST_LIST: "/blog/posts";
3
- readonly POST_FORM: "/blog/posts/:postId";
4
- readonly CATEGORY_LIST: "/blog/categories";
5
- readonly CATEGORY_FORM: "/blog/categories/:categoryId";
6
- readonly SETTINGS: "/blog/settings";
7
- };
8
- export declare function getBlogPostListUrl(): "/blog/posts";
9
- export declare function getBlogPostFormUrl(params: {
10
- postId: number | string;
11
- }): string;
12
- export declare function getBlogCategoryListUrl(): "/blog/categories";
13
- export declare function getBlogCategoryFormUrl(params: {
14
- categoryId: number | string;
15
- }): string;
16
- export declare function getBlogSettingsUrl(): "/blog/settings";
@@ -1,6 +0,0 @@
1
- import { CustomRouteConfig } from '@tager/admin-layout';
2
- export declare const BLOG_POST_LIST_ROUTE: CustomRouteConfig;
3
- export declare const BLOG_POST_FORM_ROUTE: CustomRouteConfig;
4
- export declare const BLOG_CATEGORY_LIST_ROUTE: CustomRouteConfig;
5
- export declare const BLOG_CATEGORY_FORM_ROUTE: CustomRouteConfig;
6
- export declare const BLOG_SETTINGS_ROUTE: CustomRouteConfig;
package/dist/dev.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import { CustomRouteConfig } from '@tager/admin-layout';
2
- import '@tager/admin-ui/dist/admin-ui.css';
3
- export declare const HOME_ROUTE: CustomRouteConfig;
@@ -1,7 +0,0 @@
1
- import { SetupContext } from '@vue/composition-api';
2
- import { ResourceRef } from '@tager/admin-services';
3
- import { BlogCategory } from '../typings/model';
4
- export declare function useBlogCategoryList(params: {
5
- context: SetupContext;
6
- }): ResourceRef<Array<BlogCategory>>;
7
- export default useBlogCategoryList;
@@ -1,7 +0,0 @@
1
- import { SetupContext } from '@vue/composition-api';
2
- import { ResourceRef } from '@tager/admin-services';
3
- import { PostShort } from '../typings/model';
4
- export declare function useBlogPostList(params: {
5
- context: SetupContext;
6
- }): ResourceRef<Array<PostShort>>;
7
- export default useBlogPostList;
@@ -1,7 +0,0 @@
1
- import { SetupContext } from '@vue/composition-api';
2
- import { Nullable, ResourceRef } from '@tager/admin-services';
3
- import { BlogModuleConfigType } from '../typings/model';
4
- export declare function useModuleConfig(params: {
5
- context: SetupContext;
6
- }): ResourceRef<Nullable<BlogModuleConfigType>>;
7
- export default useModuleConfig;