@tager/admin-blog 0.3.37 → 0.3.41

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.
@@ -42,7 +42,7 @@ export interface PostFull extends SeoInfo {
42
42
  readonly url: string;
43
43
  readonly urlTemplate: string;
44
44
  readonly urlAlias: string;
45
- readonly datetime: string;
45
+ readonly datetime: string | null;
46
46
  readonly status: string;
47
47
  readonly excerpt: string;
48
48
  readonly image: Nullable<FileType>;
@@ -84,6 +84,7 @@ export interface CategoryFormValues {
84
84
  name: string;
85
85
  parent: OptionType<Nullable<number>>;
86
86
  urlAlias: string;
87
+ isDefault: boolean;
87
88
  pageTitle: Nullable<string>;
88
89
  pageDescription: Nullable<string>;
89
90
  pageKeywords: Nullable<string>;
@@ -16,6 +16,7 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
16
16
  disabled?: boolean | undefined;
17
17
  };
18
18
  urlAlias: string;
19
+ isDefault: boolean;
19
20
  pageTitle: Nullable<string>;
20
21
  pageDescription: Nullable<string>;
21
22
  pageKeywords: Nullable<string>;
@@ -72,6 +73,7 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
72
73
  disabled?: boolean | undefined;
73
74
  };
74
75
  urlAlias: string;
76
+ isDefault: boolean;
75
77
  pageTitle: Nullable<string>;
76
78
  pageDescription: Nullable<string>;
77
79
  pageKeywords: Nullable<string>;
@@ -1,8 +1,10 @@
1
+ import { TFunction } from 'i18next';
1
2
  import { Nullable } from '@tager/admin-services';
2
3
  import { OptionType, SingleFileInputValueType } from '@tager/admin-ui';
3
4
  import { FieldConfigUnion, FieldUnion } from '@tager/admin-dynamic-field';
4
5
  import { PostCreationPayload, PostUpdatePayload } from '../../../services/requests';
5
6
  import { Category, PostFull } from '../../../typings/model';
7
+ export declare const getStatusOptions: (t: TFunction) => OptionType[];
6
8
  export interface FormValues {
7
9
  title: string;
8
10
  excerpt: string;
@@ -20,8 +22,9 @@ export interface FormValues {
20
22
  relatedPosts: OptionType<number>[];
21
23
  tags: string;
22
24
  additionalFields: FieldUnion[];
25
+ status: OptionType;
23
26
  }
24
- export declare function convertPostToFormValues(post: Nullable<PostFull>, languageOptionList: OptionType[], postOptionList: OptionType<number>[], additionalFieldList: FieldConfigUnion[]): FormValues;
27
+ export declare function convertPostToFormValues(post: Nullable<PostFull>, languageOptionList: OptionType[], postOptionList: OptionType<number>[], additionalFieldList: FieldConfigUnion[], statusOptions: OptionType[]): FormValues;
25
28
  export declare function convertFormValuesToCreationPayload(values: FormValues): PostCreationPayload;
26
29
  export declare function convertFormValuesToUpdatePayload(values: FormValues): PostUpdatePayload;
27
30
  export declare function convertCategoryListToOptions(categoryList: Category[], languageId: Nullable<string>): OptionType<number>[];
@@ -4657,6 +4657,11 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
4657
4657
  };
4658
4658
  value: null;
4659
4659
  })[];
4660
+ status: {
4661
+ value: string;
4662
+ label: string;
4663
+ disabled?: boolean | undefined;
4664
+ };
4660
4665
  }>;
4661
4666
  errors: import("@vue/composition-api").Ref<{
4662
4667
  [x: string]: string;
@@ -4684,6 +4689,7 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
4684
4689
  handleAliasChange: () => void;
4685
4690
  urlAliasTemplate: import("@vue/composition-api").ComputedRef<string>;
4686
4691
  handleCategoriesChange: (selectedOptions: OptionType<number>[]) => void;
4692
+ statusOptions: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
4687
4693
  }> & {
4688
4694
  [key: string]: unknown;
4689
4695
  }, {}, {}, unknown, {
@@ -9347,6 +9353,11 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
9347
9353
  };
9348
9354
  value: null;
9349
9355
  })[];
9356
+ status: {
9357
+ value: string;
9358
+ label: string;
9359
+ disabled?: boolean | undefined;
9360
+ };
9350
9361
  }>;
9351
9362
  errors: import("@vue/composition-api").Ref<{
9352
9363
  [x: string]: string;
@@ -9374,6 +9385,7 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
9374
9385
  handleAliasChange: () => void;
9375
9386
  urlAliasTemplate: import("@vue/composition-api").ComputedRef<string>;
9376
9387
  handleCategoriesChange: (selectedOptions: OptionType<number>[]) => void;
9388
+ statusOptions: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
9377
9389
  }>, {
9378
9390
  [x: string]: any;
9379
9391
  }, {}, {}, {
@@ -1,4 +1,4 @@
1
- import { ColumnDefinition } from '@tager/admin-ui';
1
+ import { ColumnDefinition, OptionType } from '@tager/admin-ui';
2
2
  import { getBlogPostFormUrl } from '../../../constants/paths';
3
3
  import { Category, PostShort } from '../../../typings/model';
4
4
  declare const _default: import("vue").ComponentOptions<import("vue").default, import("@vue/composition-api").ShallowUnwrapRef<{
@@ -16,13 +16,15 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
16
16
  pageNumber: import("@vue/composition-api").Ref<number>;
17
17
  pageCount: import("@vue/composition-api").ComputedRef<number>;
18
18
  pageSize: import("@vue/composition-api").Ref<number>;
19
- categoryFilter: import("@vue/composition-api").Ref<import("@tager/admin-ui").OptionType<string>[]>;
20
- categoryOptionList: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").OptionType<string>[]>;
19
+ categoryFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
20
+ categoryOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
21
21
  isLangSpecific: import("@vue/composition-api").ComputedRef<boolean>;
22
- languageFilter: import("@vue/composition-api").Ref<import("@tager/admin-ui").OptionType<string>[]>;
23
- languageOptionList: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").OptionType<string>[]>;
22
+ languageFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
23
+ languageOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
24
24
  fromDateFilter: import("@vue/composition-api").Ref<string>;
25
25
  toDateFilter: import("@vue/composition-api").Ref<string>;
26
+ statusFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
27
+ statusOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
26
28
  tags: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").FilterTagType[]>;
27
29
  tagRemovalHandler: (event: import("@tager/admin-ui").FilterTagType) => void;
28
30
  handleResourceClone: (entityId: string | number) => void;
@@ -48,13 +50,15 @@ declare const _default: import("vue").ComponentOptions<import("vue").default, im
48
50
  pageNumber: import("@vue/composition-api").Ref<number>;
49
51
  pageCount: import("@vue/composition-api").ComputedRef<number>;
50
52
  pageSize: import("@vue/composition-api").Ref<number>;
51
- categoryFilter: import("@vue/composition-api").Ref<import("@tager/admin-ui").OptionType<string>[]>;
52
- categoryOptionList: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").OptionType<string>[]>;
53
+ categoryFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
54
+ categoryOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
53
55
  isLangSpecific: import("@vue/composition-api").ComputedRef<boolean>;
54
- languageFilter: import("@vue/composition-api").Ref<import("@tager/admin-ui").OptionType<string>[]>;
55
- languageOptionList: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").OptionType<string>[]>;
56
+ languageFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
57
+ languageOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
56
58
  fromDateFilter: import("@vue/composition-api").Ref<string>;
57
59
  toDateFilter: import("@vue/composition-api").Ref<string>;
60
+ statusFilter: import("@vue/composition-api").Ref<OptionType<string>[]>;
61
+ statusOptionList: import("@vue/composition-api").ComputedRef<OptionType<string>[]>;
58
62
  tags: import("@vue/composition-api").ComputedRef<import("@tager/admin-ui").FilterTagType[]>;
59
63
  tagRemovalHandler: (event: import("@tager/admin-ui").FilterTagType) => void;
60
64
  handleResourceClone: (entityId: string | number) => void;
@@ -5,6 +5,7 @@ interface Params {
5
5
  context: SetupContext;
6
6
  categoryList: ComputedRef<Category[]>;
7
7
  languageList: ComputedRef<Language[]>;
8
+ statusOptionList: ComputedRef<OptionType[]>;
8
9
  }
9
10
  interface State {
10
11
  categoryFilter: Ref<OptionType[]>;
@@ -13,10 +14,11 @@ interface State {
13
14
  languageOptionList: ComputedRef<OptionType[]>;
14
15
  fromDateFilter: Ref<string>;
15
16
  toDateFilter: Ref<string>;
17
+ statusFilter: Ref<OptionType[]>;
16
18
  filterParams: ComputedRef<Record<string, string | string[]>>;
17
19
  tags: ComputedRef<FilterTagType[]>;
18
20
  tagRemovalHandler(event: FilterTagType): void;
19
21
  }
20
22
  export declare const dateFormat: (date: string) => string;
21
- export declare function useAdvancedSearch({ context, categoryList, languageList, }: Params): State;
23
+ export declare function useAdvancedSearch({ context, categoryList, languageList, statusOptionList, }: Params): State;
22
24
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tager/admin-blog",
3
- "version": "0.3.37",
3
+ "version": "0.3.41",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.esm.js",
package/src/locales/en.ts CHANGED
@@ -31,7 +31,6 @@ const EN = {
31
31
  actions: 'Actions',
32
32
  updatePost: 'Update post',
33
33
  title: 'Title',
34
- status: 'Status',
35
34
  link: 'Link',
36
35
  excerpt: 'Excerpt',
37
36
  body: 'Body',
@@ -77,9 +76,10 @@ const EN = {
77
76
  parentCategory: 'Parent category',
78
77
  noParent: 'No parent',
79
78
 
79
+ status: 'Status',
80
80
  statusPublished: 'Published',
81
81
  statusDraft: 'Draft',
82
- statusArchived: 'Archived'
82
+ statusArchived: 'Archived',
83
83
  };
84
84
 
85
85
  export default EN;
package/src/locales/ru.ts CHANGED
@@ -34,7 +34,6 @@ const RU: typeof EN = {
34
34
  updatePost: 'Обновить пост',
35
35
  title: 'Заголовок',
36
36
  link: 'Ссылка',
37
- status: 'Статус',
38
37
  excerpt: 'Краткое описание',
39
38
  defaultCategory: 'Категория по-умолчанию',
40
39
  body: 'Содержание',
@@ -79,9 +78,10 @@ const RU: typeof EN = {
79
78
  parentCategory: 'Родительская категория',
80
79
  noParent: 'Нет родительской',
81
80
 
81
+ status: 'Статус',
82
82
  statusPublished: 'Опубликован',
83
83
  statusDraft: 'Черновик',
84
- statusArchived: 'Снят с публикации'
84
+ statusArchived: 'В архиве',
85
85
  };
86
86
 
87
87
  export default RU;
@@ -51,7 +51,7 @@ export interface PostFull extends SeoInfo {
51
51
  readonly url: string;
52
52
  readonly urlTemplate: string;
53
53
  readonly urlAlias: string;
54
- readonly datetime: string;
54
+ readonly datetime: string|null;
55
55
  readonly status: string;
56
56
  readonly excerpt: string;
57
57
  readonly image: Nullable<FileType>;
@@ -98,6 +98,7 @@ export interface CategoryFormValues {
98
98
  name: string;
99
99
  parent: OptionType<Nullable<number>>;
100
100
  urlAlias: string;
101
+ isDefault: boolean;
101
102
 
102
103
  pageTitle: Nullable<string>;
103
104
  pageDescription: Nullable<string>;
@@ -25,6 +25,7 @@ export function convertCategoryToFormValues(
25
25
  name: '',
26
26
  parent: { value: null, label: t('blog:noParent') },
27
27
  urlAlias: '',
28
+ isDefault: false,
28
29
 
29
30
  pageTitle: '',
30
31
  pageDescription: '',
@@ -37,6 +38,7 @@ export function convertCategoryToFormValues(
37
38
 
38
39
  return {
39
40
  language: currentLangOption ?? null,
41
+ isDefault: category.isDefault,
40
42
  name: category.name,
41
43
  parent: category.parent
42
44
  ? { value: category.parent.id, label: category.parent.name }
@@ -62,7 +64,7 @@ export function convertCategoryFormValuesToPayload(
62
64
  name: values.name,
63
65
  parent: values.parent.value,
64
66
  urlAlias: values.urlAlias,
65
- isDefault: false,
67
+ isDefault: values.isDefault,
66
68
 
67
69
  pageTitle: values.pageTitle,
68
70
  pageDescription: values.pageDescription,
@@ -62,6 +62,13 @@
62
62
  :error="errors.language"
63
63
  />
64
64
 
65
+ <form-field-checkbox
66
+ v-model="values.isDefault"
67
+ name="isDefault"
68
+ :label="$t('blog:defaultCategory')"
69
+ :error="errors.isDefault"
70
+ />
71
+
65
72
  <form-field
66
73
  v-model="values.name"
67
74
  name="name"
@@ -1,3 +1,5 @@
1
+ import { TFunction } from 'i18next';
2
+
1
3
  import { createId, Nullable } from '@tager/admin-services';
2
4
  import { OptionType, SingleFileInputValueType } from '@tager/admin-ui';
3
5
  import {
@@ -13,6 +15,12 @@ import {
13
15
  import { getNameWithDepth } from '../../../utils/common';
14
16
  import { Category, PostFull } from '../../../typings/model';
15
17
 
18
+ export const getStatusOptions = (t: TFunction): OptionType[] => [
19
+ { label: t('blog:statusPublished'), value: 'PUBLISHED' },
20
+ { label: t('blog:statusDraft'), value: 'DRAFT' },
21
+ { label: t('blog:statusArchived'), value: 'ARCHIVED' },
22
+ ];
23
+
16
24
  export interface FormValues {
17
25
  title: string;
18
26
  excerpt: string;
@@ -30,13 +38,15 @@ export interface FormValues {
30
38
  relatedPosts: OptionType<number>[];
31
39
  tags: string;
32
40
  additionalFields: FieldUnion[];
41
+ status: OptionType;
33
42
  }
34
43
 
35
44
  export function convertPostToFormValues(
36
45
  post: Nullable<PostFull>,
37
46
  languageOptionList: OptionType[],
38
47
  postOptionList: OptionType<number>[],
39
- additionalFieldList: FieldConfigUnion[]
48
+ additionalFieldList: FieldConfigUnion[],
49
+ statusOptions: OptionType[]
40
50
  ): FormValues {
41
51
  if (!post) {
42
52
  return {
@@ -58,6 +68,7 @@ export function convertPostToFormValues(
58
68
  additionalFields: additionalFieldList.map((fieldConfig) =>
59
69
  universalFieldUtils.createFormField(fieldConfig, null)
60
70
  ),
71
+ status: statusOptions[0],
61
72
  };
62
73
  }
63
74
 
@@ -69,11 +80,15 @@ export function convertPostToFormValues(
69
80
  post.relatedPosts.some((relatedPost) => relatedPost.id === option.value)
70
81
  );
71
82
 
83
+ const foundStatus =
84
+ statusOptions.find(({ value }) => value === post.status) ??
85
+ statusOptions[0];
86
+
72
87
  return {
73
88
  title: post.title,
74
89
  excerpt: post.excerpt,
75
90
  body: post.body,
76
- datetime: post.datetime.substr(0, 10),
91
+ datetime: post.datetime ? post.datetime.substr(0, 10) : '',
77
92
  coverImage: post.coverImage
78
93
  ? { id: createId(), file: post.coverImage }
79
94
  : null,
@@ -94,15 +109,16 @@ export function convertPostToFormValues(
94
109
  language: currentLangOption ?? null,
95
110
  relatedPosts: selectedPostOptionList,
96
111
  tags: post.tags.join(','),
97
- additionalFields: additionalFieldList.map((fieldConfig, index) => {
112
+ additionalFields: additionalFieldList.map((fieldConfig) => {
98
113
  const postAdditionalField = post.additionalFields.find(
99
- (item) => item.name === fieldConfig.name
114
+ ({ name }) => name === fieldConfig.name
100
115
  );
101
116
  return universalFieldUtils.createFormField(
102
117
  fieldConfig,
103
118
  postAdditionalField?.value
104
119
  );
105
120
  }),
121
+ status: foundStatus,
106
122
  };
107
123
  }
108
124
 
@@ -121,7 +137,6 @@ export function convertFormValuesToCreationPayload(
121
137
  pageTitle: values.pageTitle,
122
138
  pageDescription: values.pageDescription,
123
139
  openGraphImage: values.openGraphImage?.file.id ?? null,
124
- status: 'PUBLISHED',
125
140
  categories: values.categories.map((option) => option.value),
126
141
  language: values.language?.value ?? null,
127
142
  relatedPosts: values.relatedPosts.map(
@@ -132,6 +147,7 @@ export function convertFormValuesToCreationPayload(
132
147
  name: field.config.name,
133
148
  value: universalFieldUtils.getOutgoingValue(field),
134
149
  })),
150
+ status: values.status.value,
135
151
  };
136
152
  }
137
153
 
@@ -18,6 +18,15 @@
18
18
  />
19
19
 
20
20
  <template v-if="selectedTabId === 'common'">
21
+ <form-field-select
22
+ v-model="values.status"
23
+ name="status"
24
+ :error="errors.status"
25
+ :label="$t('blog:status')"
26
+ :no-options-message="$t('blog:noTemplates')"
27
+ :options="statusOptions"
28
+ />
29
+
21
30
  <form-field-select
22
31
  v-if="isCreation && isLangSpecific"
23
32
  v-model="values.language"
@@ -52,6 +61,7 @@
52
61
  type="textarea"
53
62
  :error="errors.excerpt"
54
63
  />
64
+
55
65
  <form-field-rich-text-input
56
66
  v-model="values.body"
57
67
  name="body"
@@ -59,6 +69,7 @@
59
69
  :error="errors.body"
60
70
  :get-upload-adapter-options="getUploadAdapterOptions"
61
71
  />
72
+
62
73
  <ShortCodeConstructor
63
74
  :short-code-config-list="
64
75
  moduleConfig ? moduleConfig.shortcodes : []
@@ -218,6 +229,7 @@ import {
218
229
  convertFormValuesToUpdatePayload,
219
230
  convertPostToFormValues,
220
231
  FormValues,
232
+ getStatusOptions,
221
233
  } from './PostForm.helpers';
222
234
 
223
235
  export default defineComponent({
@@ -229,6 +241,10 @@ export default defineComponent({
229
241
 
230
242
  const urlAliasChanged = ref<boolean>(false);
231
243
 
244
+ const statusOptions = computed<OptionType[]>(() =>
245
+ getStatusOptions(context.root.$t)
246
+ );
247
+
232
248
  /** Fetch module config **/
233
249
 
234
250
  const {
@@ -300,7 +316,8 @@ export default defineComponent({
300
316
  post.value,
301
317
  languageOptionList.value,
302
318
  postOptionList.value,
303
- moduleConfig.value?.fields ?? []
319
+ moduleConfig.value?.fields ?? [],
320
+ statusOptions.value
304
321
  )
305
322
  );
306
323
  const errors = ref<Record<string, string>>({});
@@ -310,7 +327,8 @@ export default defineComponent({
310
327
  post.value,
311
328
  languageOptionList.value,
312
329
  postOptionList.value,
313
- moduleConfig.value?.fields ?? []
330
+ moduleConfig.value?.fields ?? [],
331
+ statusOptions.value
314
332
  );
315
333
  });
316
334
 
@@ -347,7 +365,8 @@ export default defineComponent({
347
365
  null,
348
366
  languageOptionList.value,
349
367
  postOptionList.value,
350
- moduleConfig.value?.fields ?? []
368
+ moduleConfig.value?.fields ?? [],
369
+ statusOptions.value
351
370
  );
352
371
  }
353
372
 
@@ -499,7 +518,7 @@ export default defineComponent({
499
518
  }
500
519
 
501
520
  function handleTitleChange(value: string) {
502
- if (urlAliasChanged.value === false) {
521
+ if (isCreation.value && urlAliasChanged.value === false) {
503
522
  values.value.urlAlias = urlTranslit(value);
504
523
  }
505
524
  }
@@ -587,6 +606,8 @@ export default defineComponent({
587
606
  handleAliasChange,
588
607
  urlAliasTemplate,
589
608
  handleCategoriesChange,
609
+
610
+ statusOptions,
590
611
  };
591
612
  },
592
613
  });
@@ -7,7 +7,7 @@ import {
7
7
  Category,
8
8
  ModuleConfig,
9
9
  Language,
10
- PostShort
10
+ PostShort,
11
11
  } from '../../../typings/model';
12
12
  import { getBlogPostFormUrl } from '../../../constants/paths';
13
13
 
@@ -28,7 +28,7 @@ export function convertPostList(
28
28
 
29
29
  return {
30
30
  ...post,
31
- language: foundLanguage ? foundLanguage.name : post.language
31
+ language: foundLanguage ? foundLanguage.name : post.language,
32
32
  };
33
33
  }
34
34
 
@@ -41,7 +41,7 @@ export function getStatuses(t: TFunction): Record<string, string> {
41
41
  PUBLISHED: t('blog:statusPublished'),
42
42
  DRAFT: t('blog:statusDraft'),
43
43
  ARCHIVED: t('blog:statusArchived'),
44
- }
44
+ };
45
45
  }
46
46
 
47
47
  export function getPostTableColumnDefs(
@@ -58,7 +58,7 @@ export function getPostTableColumnDefs(
58
58
  name: 'ID',
59
59
  field: 'id',
60
60
  style: { width: '50px', textAlign: 'center' },
61
- headStyle: { width: '50px', textAlign: 'center' }
61
+ headStyle: { width: '50px', textAlign: 'center' },
62
62
  },
63
63
  {
64
64
  id: 2,
@@ -66,9 +66,7 @@ export function getPostTableColumnDefs(
66
66
  field: 'status',
67
67
  style: { width: '120px' },
68
68
  headStyle: { width: '120px' },
69
- format: ({ row }) => {
70
- return getStatuses(t)[row.status];
71
- }
69
+ format: ({ row }) => getStatuses(t)[row.status],
72
70
  },
73
71
  {
74
72
  id: 2,
@@ -78,16 +76,16 @@ export function getPostTableColumnDefs(
78
76
  format: ({ row }) => ({
79
77
  adminLink: {
80
78
  text: row.title,
81
- url: getBlogPostFormUrl({ postId: row.id })
79
+ url: getBlogPostFormUrl({ postId: row.id }),
82
80
  },
83
81
  websiteLink: {
84
82
  text: row.url,
85
83
  url: [
86
84
  process.env.VUE_APP_WEBSITE_URL || window.location.origin,
87
- row.url
88
- ].join('')
89
- }
90
- })
85
+ row.url,
86
+ ].join(''),
87
+ },
88
+ }),
91
89
  },
92
90
  {
93
91
  id: 3,
@@ -95,26 +93,32 @@ export function getPostTableColumnDefs(
95
93
  field: 'image',
96
94
  type: 'image',
97
95
  style: { width: '250px' },
98
- headStyle: { width: '250px' }
96
+ headStyle: { width: '250px' },
99
97
  },
100
98
  isLangSpecific
101
99
  ? { id: 4, name: t('blog:language'), field: 'language' }
102
100
  : null,
103
- { id: 5, name: t('blog:date'), field: 'datetime', type: 'datetime', options: { ignoreStartOfDayTime: true } },
101
+ {
102
+ id: 5,
103
+ name: t('blog:date'),
104
+ field: 'datetime',
105
+ type: 'datetime',
106
+ options: { ignoreStartOfDayTime: true },
107
+ },
104
108
  {
105
109
  id: 6,
106
110
  name: t('blog:categories'),
107
111
  field: 'categories',
108
112
  format: ({ row }) =>
109
- row.categories.map((category) => category.name).join(', ')
113
+ row.categories.map((category) => category.name).join(', '),
110
114
  },
111
115
  {
112
116
  id: 7,
113
117
  name: t('blog:actions'),
114
118
  field: 'actions',
115
119
  style: { whiteSpace: 'nowrap', width: '120px' },
116
- headStyle: { whiteSpace: 'nowrap', width: '120px' }
117
- }
120
+ headStyle: { whiteSpace: 'nowrap', width: '120px' },
121
+ },
118
122
  ];
119
123
 
120
124
  return COLUMN_DEFS.filter(notEmpty);
@@ -69,6 +69,15 @@
69
69
  />
70
70
  </div>
71
71
  </div>
72
+
73
+ <form-field-multi-select
74
+ v-model="statusFilter"
75
+ :options="statusOptionList"
76
+ name="statusFilter"
77
+ :searchable="true"
78
+ :label="$t('blog:status')"
79
+ class="filter"
80
+ />
72
81
  </div>
73
82
  </advanced-search>
74
83
  </template>
@@ -113,6 +122,7 @@ import pick from 'lodash.pick';
113
122
 
114
123
  import {
115
124
  ColumnDefinition,
125
+ OptionType,
116
126
  useDataTable,
117
127
  useTranslation,
118
128
  } from '@tager/admin-ui';
@@ -135,6 +145,7 @@ import {
135
145
  PostFull,
136
146
  PostShort,
137
147
  } from '../../../typings/model';
148
+ import { getStatusOptions } from '../PostForm/PostForm.helpers';
138
149
 
139
150
  import { convertPostList, getPostTableColumnDefs } from './PostList.helpers';
140
151
  import { useAdvancedSearch } from './hooks';
@@ -150,6 +161,8 @@ export default defineComponent({
150
161
  : context.root.$route.query.category;
151
162
  });
152
163
 
164
+ const statusOptionList = computed<OptionType[]>(() => getStatusOptions(t));
165
+
153
166
  /** Fetch module config **/
154
167
 
155
168
  const {
@@ -196,10 +209,12 @@ export default defineComponent({
196
209
  filterParams,
197
210
  tags,
198
211
  tagRemovalHandler,
212
+ statusFilter,
199
213
  } = useAdvancedSearch({
200
214
  context,
201
215
  categoryList,
202
216
  languageList,
217
+ statusOptionList,
203
218
  });
204
219
 
205
220
  const isLangSpecific = computed<boolean>(
@@ -311,6 +326,8 @@ export default defineComponent({
311
326
  languageOptionList,
312
327
  fromDateFilter,
313
328
  toDateFilter,
329
+ statusFilter,
330
+ statusOptionList,
314
331
  tags,
315
332
  tagRemovalHandler,
316
333