@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.
Files changed (83) hide show
  1. package/dist/constants/paths.d.ts +6 -14
  2. package/dist/constants/routes.d.ts +5 -5
  3. package/dist/dev/App.vue.d.ts +5 -0
  4. package/dist/dev/config.d.ts +2 -0
  5. package/dist/dev/env.d.ts +1 -0
  6. package/dist/dev/main.d.ts +3 -0
  7. package/dist/hooks/index.d.ts +4 -4
  8. package/dist/hooks/useFetchCategories.d.ts +3 -6
  9. package/dist/hooks/useFetchCategory.d.ts +7 -8
  10. package/dist/hooks/useFetchModuleConfig.d.ts +3 -6
  11. package/dist/hooks/useFetchPosts.d.ts +3 -6
  12. package/dist/index.mjs +2355 -0
  13. package/dist/locales/apply.d.ts +1 -0
  14. package/dist/locales/en.d.ts +92 -86
  15. package/dist/locales/ru.d.ts +3 -3
  16. package/dist/main.d.ts +3 -4
  17. package/dist/services/requests.d.ts +60 -59
  18. package/dist/style.css +1 -0
  19. package/dist/typings/common.d.ts +1 -1
  20. package/dist/typings/model.d.ts +106 -106
  21. package/dist/utils/common.d.ts +2 -2
  22. package/dist/utils/paths.d.ts +8 -0
  23. package/dist/views/Categories/CategoryForm/CategoryForm.helpers.d.ts +7 -7
  24. package/dist/views/Categories/CategoryForm/CategoryForm.vue.d.ts +53 -116
  25. package/dist/views/Categories/CategoryForm/index.d.ts +1 -1
  26. package/dist/views/Categories/CategoryList/CategoryList.helpers.d.ts +7 -7
  27. package/dist/views/Categories/CategoryList/CategoryList.vue.d.ts +26 -57
  28. package/dist/views/Categories/CategoryList/hooks/index.d.ts +1 -1
  29. package/dist/views/Categories/CategoryList/hooks/useAdvancedSearch.d.ts +19 -16
  30. package/dist/views/Categories/CategoryList/index.d.ts +1 -1
  31. package/dist/views/Posts/PostForm/PostForm.helpers.d.ts +32 -32
  32. package/dist/views/Posts/PostForm/PostForm.vue.d.ts +2768 -9398
  33. package/dist/views/Posts/PostForm/index.d.ts +1 -1
  34. package/dist/views/Posts/PostList/PostList.helpers.d.ts +8 -7
  35. package/dist/views/Posts/PostList/PostList.vue.d.ts +40 -78
  36. package/dist/views/Posts/PostList/hooks/index.d.ts +1 -1
  37. package/dist/views/Posts/PostList/hooks/useAdvancedSearch.d.ts +27 -24
  38. package/dist/views/Posts/PostList/index.d.ts +1 -1
  39. package/package.json +51 -49
  40. package/src/constants/paths.ts +0 -22
  41. package/src/constants/routes.ts +9 -9
  42. package/src/dev/App.vue +56 -0
  43. package/src/dev/config.ts +23 -0
  44. package/src/dev/env.ts +17 -0
  45. package/src/dev/main.ts +49 -0
  46. package/src/hooks/useFetchCategories.ts +2 -7
  47. package/src/hooks/useFetchCategory.ts +3 -6
  48. package/src/hooks/useFetchModuleConfig.ts +2 -7
  49. package/src/hooks/useFetchPosts.ts +4 -6
  50. package/src/locales/apply.ts +9 -0
  51. package/src/locales/en.ts +10 -4
  52. package/src/locales/ru.ts +11 -3
  53. package/src/main.ts +3 -8
  54. package/src/services/requests.ts +1 -0
  55. package/src/utils/paths.ts +23 -0
  56. package/src/views/Categories/CategoryForm/CategoryForm.vue +81 -65
  57. package/src/views/Categories/CategoryList/CategoryList.helpers.ts +1 -1
  58. package/src/views/Categories/CategoryList/CategoryList.vue +86 -58
  59. package/src/views/Categories/CategoryList/hooks/useAdvancedSearch.ts +9 -12
  60. package/src/views/Posts/PostForm/PostForm.vue +265 -225
  61. package/src/views/Posts/PostList/PostList.helpers.ts +27 -2
  62. package/src/views/Posts/PostList/PostList.vue +203 -192
  63. package/src/views/Posts/PostList/hooks/useAdvancedSearch.ts +22 -30
  64. package/CHANGELOG.md +0 -13
  65. package/dist/constants/menu.d.ts +0 -5
  66. package/dist/dev.d.ts +0 -1
  67. package/dist/index.esm.js +0 -5294
  68. package/dist/index.umd.js +0 -5321
  69. package/dist/router/index.d.ts +0 -4
  70. package/dist/views/Posts/PostForm/components/TabList/TabList.types.d.ts +0 -5
  71. package/dist/views/Posts/PostForm/components/TabList/index.d.ts +0 -2
  72. package/src/constants/menu.ts +0 -31
  73. package/src/dev.ts +0 -34
  74. package/src/router/index.ts +0 -40
  75. package/src/typings/sfc.d.ts +0 -12
  76. package/src/typings/shims-tsx.d.ts +0 -13
  77. package/src/typings/shims-vue.d.ts +0 -11
  78. package/src/typings/translate.d.ts +0 -10
  79. package/src/views/App.vue +0 -22
  80. package/src/views/Home.vue +0 -31
  81. package/src/views/Posts/PostForm/components/TabList/TabList.types.ts +0 -5
  82. package/src/views/Posts/PostForm/components/TabList/TabList.vue +0 -92
  83. package/src/views/Posts/PostForm/components/TabList/index.ts +0 -2
@@ -1,7 +1,7 @@
1
1
  import { TFunction } from 'i18next';
2
2
 
3
3
  import { notEmpty, Nullable } from '@tager/admin-services';
4
- import { ColumnDefinition } from '@tager/admin-ui';
4
+ import { ColumnDefinition, OptionType } from '@tager/admin-ui';
5
5
 
6
6
  import {
7
7
  Category,
@@ -9,7 +9,7 @@ import {
9
9
  Language,
10
10
  PostShort,
11
11
  } from '../../../typings/model';
12
- import { getBlogPostFormUrl } from '../../../constants/paths';
12
+ import { getBlogPostFormUrl } from '../../../utils/paths';
13
13
 
14
14
  export function convertPostList(
15
15
  postList: PostShort[],
@@ -122,3 +122,28 @@ export function getPostTableColumnDefs(
122
122
 
123
123
  return COLUMN_DEFS.filter(notEmpty);
124
124
  }
125
+
126
+ export function getPostTableSortOptions(t: TFunction): Array<OptionType> {
127
+ return [
128
+ {
129
+ value: 'datetime_desc',
130
+ label: t('blog:sortDateTimeDesc'),
131
+ },
132
+ {
133
+ value: 'datetime_asc',
134
+ label: t('blog:sortDateTimeAsc'),
135
+ },
136
+ {
137
+ value: 'title_asc',
138
+ label: t('blog:sortTitleAsc'),
139
+ },
140
+ {
141
+ value: 'title_desc',
142
+ label: t('blog:sortTitleDesc'),
143
+ },
144
+ {
145
+ value: 'status',
146
+ label: t('blog:sortStatus'),
147
+ },
148
+ ];
149
+ }
@@ -1,215 +1,239 @@
1
1
  <template>
2
- <page
3
- :title='pageTitle'
4
- :header-buttons="[
2
+ <Page
3
+ :title="pageTitle"
4
+ :header-buttons="[
5
5
  {
6
- text: $t('blog:newPost'),
6
+ text: $i18n.t('blog:newPost'),
7
7
  href: getBlogPostFormUrl({ postId: 'create' }),
8
8
  },
9
9
  ]"
10
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='{
11
+ <template #content>
12
+ <DataTable
13
+ :column-defs="columnDefs"
14
+ :row-data="rowData"
15
+ :loading="isRowDataLoading"
16
+ :error-message="errorMessage"
17
+ :search-query="searchQuery"
18
+ :pagination="{
19
19
  pageNumber,
20
20
  pageCount,
21
21
  pageSize,
22
22
  disabled: isRowDataLoading,
23
- }'
24
- data-table='blog-post'
25
- @change='handleChange'
23
+ }"
24
+ :sort="{ options: sortOptions, value: sortValue }"
25
+ data-table="blog-post"
26
+ @change="handleChange"
26
27
  >
27
- <template v-slot:filters>
28
- <advanced-search :tags='tags' @click:tag='tagRemovalHandler'>
29
- <div class='filters'>
30
- <form-field-multi-select
31
- v-model='categoryFilter'
32
- :options='categoryOptionList'
33
- name='categoryFilter'
34
- :searchable='true'
35
- :label="$t('blog:category')"
36
- class='filter'
28
+ <template #filters>
29
+ <AdvancedSearch :tags="tags" @click:tag="tagRemovalHandler">
30
+ <div class="filters">
31
+ <FormFieldMultiSelect
32
+ v-model:selected-options="categoryFilter"
33
+ :options="categoryOptionList"
34
+ name="categoryFilter"
35
+ :searchable="true"
36
+ :label="$i18n.t('blog:category')"
37
+ class="filter"
37
38
  />
38
39
 
39
- <form-field-multi-select
40
- v-if='isLangSpecific'
41
- v-model='languageFilter'
42
- :options='languageOptionList'
43
- name='languageFilter'
44
- :searchable='true'
45
- :label="$t('blog:language')"
46
- class='filter'
40
+ <FormFieldMultiSelect
41
+ v-if="isLangSpecific"
42
+ v-model:selected-options="languageFilter"
43
+ :options="languageOptionList"
44
+ name="languageFilter"
45
+ :searchable="true"
46
+ :label="$i18n.t('blog:language')"
47
+ class="filter"
48
+ />
49
+ <FormFieldMultiSelect
50
+ v-model:selected-options="statusFilter"
51
+ :options="statusOptionList"
52
+ name="statusFilter"
53
+ :searchable="true"
54
+ :label="$i18n.t('blog:status')"
55
+ class="filter"
56
+ />
57
+ </div>
58
+
59
+ <div class="filters">
60
+ <FormField
61
+ v-model:value="fromDateFilter"
62
+ :label="$i18n.t('blog:dateOfPublicationFrom')"
63
+ name="fromDateFilter"
64
+ type="date"
65
+ :max="toDateFilter"
47
66
  />
48
67
 
49
- <div class='filter'>
50
- <div class='date-label'>
51
- {{ $t('blog:dateOfPublication') }}
52
- </div>
53
-
54
- <div class='date-content'>
55
- <form-field
56
- v-model='fromDateFilter'
57
- :label="$t('blog:From')"
58
- name='fromDateFilter'
59
- type='date'
60
- :max='toDateFilter'
61
- />
62
-
63
- <form-field
64
- v-model='toDateFilter'
65
- :label="$t('blog:To')"
66
- name='toDateFilter'
67
- type='date'
68
- :min='fromDateFilter'
69
- />
70
- </div>
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'
68
+ <FormField
69
+ v-model:value="toDateFilter"
70
+ :label="$i18n.t('blog:dateOfPublicationTo')"
71
+ name="toDateFilter"
72
+ type="date"
73
+ :min="fromDateFilter"
80
74
  />
81
75
  </div>
82
- </advanced-search>
76
+ </AdvancedSearch>
83
77
  </template>
84
78
 
85
- <template v-slot:cell(status)='{ row }'>
86
- <div class='status'>
87
- <span>{{ getStatuses(t)[row.status] }}</span>
88
- <span v-if='row.status === "PUBLISHED" && row.archiveAt'>
89
- {{ t('blog:archiveAtLabel') }}: <i>{{ formatDateTime(new Date(row.archiveAt), true) }}</i>
90
- </span>
91
- <span v-if='row.status === "DRAFT" && row.publishAt'>
92
- {{ t('blog:publishAtLabel') }}: <i>{{ formatDateTime(new Date(row.publishAt), true) }}</i>
79
+ <template #cell(status)="{ row }">
80
+ <div class="status">
81
+ <span>{{ getStatuses($i18n.t)[row.status] }}</span>
82
+
83
+ <span v-if="row.status === 'PUBLISHED' && row.archiveAt">
84
+ {{ $i18n.t('blog:archiveAtLabel') }}:
85
+ <i>{{ formatDateTime(new Date(row.archiveAt), true) }}</i>
86
+ </span>
87
+
88
+ <span v-if="row.status === 'DRAFT' && row.publishAt">
89
+ {{ $i18n.t('blog:publishAtLabel') }}:
90
+ <i>{{ formatDateTime(new Date(row.publishAt), true) }}</i>
93
91
  </span>
94
92
  </div>
95
93
  </template>
96
94
 
97
- <template v-slot:cell(actions)='{ row }'>
98
- <base-button
99
- variant='icon'
100
- :title="$t('blog:edit')"
101
- :disabled='isBusy(row.id)'
102
- :href='getBlogPostFormUrl({ postId: row.id })'
95
+ <template #cell(actions)="{ row }">
96
+ <BaseButton
97
+ variant="icon"
98
+ :title="$i18n.t('blog:edit')"
99
+ :disabled="isBusy(row.id)"
100
+ :href="getBlogPostFormUrl({ postId: row.id })"
103
101
  >
104
- <svg-icon name='edit' />
105
- </base-button>
106
-
107
- <base-button
108
- variant='icon'
109
- :title="$t('blog:clone')"
110
- :disabled='isBusy(row.id)'
111
- @click='handleResourceClone(row.id)'
102
+ <EditIcon/>
103
+ </BaseButton>
104
+
105
+ <BaseButton
106
+ variant="icon"
107
+ :title="$i18n.t('blog:clone')"
108
+ :disabled="isBusy(row.id)"
109
+ @click="handleResourceClone(row.id)"
112
110
  >
113
- <svg-icon name='contentCopy' />
114
- </base-button>
115
-
116
- <base-button
117
- variant='icon'
118
- :title="$t('blog:remove')"
119
- :disabled='isBusy(row.id)'
120
- @click='handleResourceDelete(row.id)'
111
+ <ContentCopyIcon/>
112
+ </BaseButton>
113
+
114
+ <BaseButton
115
+ variant="icon"
116
+ :title="$i18n.t('blog:remove')"
117
+ :disabled="isBusy(row.id)"
118
+ @click="handleResourceDelete(row.id)"
121
119
  >
122
- <svg-icon name='delete' />
123
- </base-button>
120
+ <DeleteIcon/>
121
+ </BaseButton>
124
122
  </template>
125
- </data-table>
123
+ </DataTable>
126
124
  </template>
127
- </page>
125
+ </Page>
128
126
  </template>
129
127
 
130
- <script lang='ts'>
131
- import { computed, defineComponent, watch } from '@vue/composition-api';
128
+ <script lang="ts">
129
+ import {computed, defineComponent, watch} from 'vue';
132
130
  import isEqual from 'lodash.isequal';
133
131
  import pick from 'lodash.pick';
132
+ import {useRoute, useRouter} from 'vue-router';
134
133
 
135
134
  import {
136
135
  ColumnDefinition,
137
136
  OptionType,
138
137
  useDataTable,
139
- useTranslation,
140
- formatDateTime
138
+ formatDateTime,
139
+ AdvancedSearch,
140
+ FormFieldMultiSelect,
141
+ FormField,
142
+ BaseButton,
143
+ EditIcon,
144
+ ContentCopyIcon,
145
+ DeleteIcon,
146
+ DataTable,
141
147
  } from '@tager/admin-ui';
142
148
  import {
143
149
  Nullable,
150
+ useI18n,
144
151
  useResourceClone,
145
- useResourceDelete
152
+ useResourceDelete,
146
153
  } from '@tager/admin-services';
154
+ import {Page} from '@tager/admin-layout';
147
155
 
148
- import { useFetchModuleConfig, useFetchCategories } from '../../../hooks';
156
+ import {useFetchModuleConfig, useFetchCategories} from '../../../hooks';
149
157
  import {
150
158
  clonePost,
151
159
  deleteBlogPost,
152
- getPosts
160
+ getPosts,
153
161
  } from '../../../services/requests';
154
- import { getBlogPostFormUrl } from '../../../constants/paths';
162
+ import {getBlogPostFormUrl} from '../../../utils/paths';
155
163
  import {
156
164
  Category,
157
165
  Language,
158
166
  PostFull,
159
- PostShort
167
+ PostShort,
160
168
  } from '../../../typings/model';
161
- import { getStatusOptions } from '../PostForm/PostForm.helpers';
169
+ import {getStatusOptions} from '../PostForm/PostForm.helpers';
162
170
 
163
- import { convertPostList, getPostTableColumnDefs, getStatuses } from './PostList.helpers';
164
- import { useAdvancedSearch } from './hooks';
171
+ import {
172
+ convertPostList,
173
+ getPostTableColumnDefs,
174
+ getPostTableSortOptions,
175
+ getStatuses,
176
+ } from './PostList.helpers';
177
+ import {useAdvancedSearch} from './hooks';
165
178
 
166
179
  export default defineComponent({
167
- name: 'Posts',
168
- setup(props, context) {
169
- const { t } = useTranslation(context);
180
+ name: 'PostList',
181
+ components: {
182
+ DeleteIcon,
183
+ ContentCopyIcon,
184
+ EditIcon,
185
+ BaseButton,
186
+ FormField,
187
+ FormFieldMultiSelect,
188
+ AdvancedSearch,
189
+ Page,
190
+ DataTable,
191
+ },
192
+ setup() {
193
+ const {t} = useI18n();
194
+ const route = useRoute();
195
+ const router = useRouter();
170
196
 
171
197
  const categoryId = computed<string>(() => {
172
- return Array.isArray(context.root.$route.query.category)
173
- ? context.root.$route.query.category[0] ?? ''
174
- : context.root.$route.query.category;
198
+ return Array.isArray(route.query.category)
199
+ ? (route.query.category[0] as string) ?? ''
200
+ : (route.query.category as string);
175
201
  });
176
202
 
177
203
  const statusOptionList = computed<OptionType[]>(() => getStatusOptions(t));
178
204
 
179
205
  /** Fetch module config **/
180
206
 
181
- const {
182
- data: moduleConfig,
183
- loading: isModuleConfigLoading
184
- } = useFetchModuleConfig({ context });
207
+ const {data: moduleConfig, loading: isModuleConfigLoading} =
208
+ useFetchModuleConfig();
185
209
 
186
210
  const languageList = computed<Language[]>(
187
- () => moduleConfig.value?.languages ?? []
211
+ () => moduleConfig.value?.languages ?? []
188
212
  );
189
213
 
190
214
  /** Fetch category list **/
191
215
 
192
- const {
193
- data: categoryList,
194
- loading: isCategoryListLoading
195
- } = useFetchCategories({ context });
216
+ const {data: categoryList, loading: isCategoryListLoading} =
217
+ useFetchCategories();
196
218
 
197
219
  const selectedCategory = computed<Nullable<Category>>(() =>
198
- categoryId.value
199
- ? categoryList.value.find(
200
- ({ id }) => String(id) === String(categoryId.value)
201
- ) ?? null
202
- : null
220
+ categoryId.value
221
+ ? categoryList.value.find(
222
+ ({id}) => String(id) === String(categoryId.value)
223
+ ) ?? null
224
+ : null
203
225
  );
204
226
 
205
227
  const pageTitle = computed<string>(() => {
206
228
  return selectedCategory.value
207
- ? `${context.root.$t('blog:postsByCategory')} "${
208
- selectedCategory.value.name
209
- }"`
210
- : context.root.$t('blog:posts');
229
+ ? `${t('blog:postsByCategory')} "${selectedCategory.value.name}"`
230
+ : t('blog:posts');
211
231
  });
212
232
 
233
+ const isLangSpecific = computed<boolean>(
234
+ () => languageOptionList.value.length > 1
235
+ );
236
+
213
237
  /** Advanced search **/
214
238
 
215
239
  const {
@@ -222,17 +246,16 @@ export default defineComponent({
222
246
  filterParams,
223
247
  tags,
224
248
  tagRemovalHandler,
225
- statusFilter
249
+ statusFilter,
226
250
  } = useAdvancedSearch({
227
- context,
251
+ t,
252
+ route,
228
253
  categoryList,
229
254
  languageList,
230
- statusOptionList
255
+ statusOptionList,
231
256
  });
232
257
 
233
- const isLangSpecific = computed<boolean>(
234
- () => languageOptionList.value.length > 1
235
- );
258
+ const sortOptions = getPostTableSortOptions(t);
236
259
 
237
260
  /** Fetch Post list **/
238
261
 
@@ -245,19 +268,21 @@ export default defineComponent({
245
268
  handleChange,
246
269
  pageNumber,
247
270
  pageCount,
248
- pageSize
271
+ pageSize,
272
+ sort,
249
273
  } = useDataTable<PostShort>({
250
274
  fetchEntityList: (params) =>
251
- getPosts({
252
- query: params.searchQuery,
253
- pageNumber: params.pageNumber,
254
- pageSize: params.pageSize,
255
- ...filterParams.value
256
- }),
275
+ getPosts({
276
+ query: params.searchQuery,
277
+ pageNumber: params.pageNumber,
278
+ pageSize: params.pageSize,
279
+ sort: params.sort || undefined,
280
+ ...filterParams.value,
281
+ }),
257
282
  initialValue: [],
258
- context,
259
283
  resourceName: 'Blog post list',
260
- pageSize: 100
284
+ pageSize: 100,
285
+ defaultSort: sortOptions[0].value,
261
286
  });
262
287
 
263
288
  watch(filterParams, () => {
@@ -266,45 +291,43 @@ export default defineComponent({
266
291
  }
267
292
 
268
293
  const newQuery = {
269
- ...pick(context.root.$route.query, ['query', 'pageNumber']),
270
- ...filterParams.value
294
+ ...pick(route.query, ['query', 'pageNumber', 'sort']),
295
+ ...filterParams.value,
271
296
  };
272
297
 
273
- if (!isEqual(context.root.$route.query, newQuery)) {
274
- context.root.$router.replace({ query: newQuery });
298
+ if (!isEqual(route.query, newQuery)) {
299
+ router.replace({query: newQuery});
275
300
  fetchPostList();
276
301
  }
277
302
  });
278
303
 
279
304
  const displayedPostList = computed<PostShort[]>(() =>
280
- convertPostList(
281
- postList.value,
282
- selectedCategory.value,
283
- moduleConfig.value?.languages ?? []
284
- )
305
+ convertPostList(
306
+ postList.value,
307
+ selectedCategory.value,
308
+ moduleConfig.value?.languages ?? []
309
+ )
285
310
  );
286
311
 
287
312
  const isRowDataLoading = computed<boolean>(
288
- () =>
289
- isCategoryListLoading.value ||
290
- isPostLoading.value ||
291
- isModuleConfigLoading.value
313
+ () =>
314
+ isCategoryListLoading.value ||
315
+ isPostLoading.value ||
316
+ isModuleConfigLoading.value
292
317
  );
293
318
 
294
- const { isDeleting, handleResourceDelete } = useResourceDelete({
319
+ const {isDeleting, handleResourceDelete} = useResourceDelete({
295
320
  deleteResource: deleteBlogPost,
296
321
  resourceName: 'Post',
297
322
  onSuccess: fetchPostList,
298
- context
299
323
  });
300
324
 
301
- const { isCloning, handleResourceClone } = useResourceClone({
325
+ const {isCloning, handleResourceClone} = useResourceClone({
302
326
  cloneResource: clonePost,
303
327
  confirmMessage: t('blog:cloneConfirm'),
304
328
  successMessage: t('blog:cloneSuccess'),
305
329
  failureMessage: t('blog:cloneFailure'),
306
330
  onSuccessRedirectTo: (data: PostFull) => `/blog/posts/${data.id}`,
307
- context
308
331
  });
309
332
 
310
333
  function isBusy(postId: number): boolean {
@@ -312,13 +335,15 @@ export default defineComponent({
312
335
  }
313
336
 
314
337
  const columnDefs = computed<ColumnDefinition<PostShort>[]>(() =>
315
- getPostTableColumnDefs(moduleConfig.value, context.root.$t)
338
+ getPostTableColumnDefs(moduleConfig.value, t)
316
339
  );
317
340
 
318
341
  return {
319
342
  t,
320
343
  formatDateTime,
321
344
  columnDefs,
345
+ sortOptions,
346
+ sortValue: sort,
322
347
  rowData: displayedPostList,
323
348
  handleResourceDelete,
324
349
  isDeleting,
@@ -349,40 +374,27 @@ export default defineComponent({
349
374
 
350
375
  // Clone
351
376
  handleResourceClone,
352
- isBusy
377
+ isBusy,
353
378
  };
354
- }
379
+ },
355
380
  });
356
381
  </script>
357
382
 
358
- <style scoped lang='scss'>
383
+ <style scoped lang="scss">
359
384
  .filters {
360
- display: flex;
361
- margin: 0 -10px;
385
+ margin-bottom: 1rem;
386
+ width: 100%;
387
+ display: grid;
388
+ gap: 1rem;
389
+ grid-template-columns: 1fr 1fr;
362
390
 
363
391
  &:not(:first-child) {
364
- margin-top: 10px;
392
+ margin-top: 1rem;
365
393
  }
366
-
367
- .filter {
368
- padding: 10px 10px 0;
369
- width: 50%;
370
- margin: 0;
371
- }
372
- }
373
-
374
- .date-label {
375
- margin-bottom: 0.5rem;
376
- }
377
-
378
- .date-content {
379
- display: grid;
380
- grid-template-columns: repeat(2, 1fr);
381
- column-gap: 10px;
382
394
  }
383
395
 
384
396
  .status {
385
- span:first-child {
397
+ span {
386
398
  display: block;
387
399
  }
388
400
 
@@ -395,6 +407,5 @@ export default defineComponent({
395
407
  display: block;
396
408
  }
397
409
  }
398
- ;
399
410
  }
400
411
  </style>