@tager/admin-banners 0.3.3 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  import { TFunction } from 'i18next';
2
2
  import { ColumnDefinition } from '@tager/admin-ui';
3
3
  import { Banner, Status } from '../../../typings/banners';
4
+ import { Zone } from '../../../typings/zones';
4
5
  export declare function getStatus(type: Status, t: TFunction): string;
5
- export declare function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[];
6
+ export declare function getColumnDefs(zoneList: Zone[], t: TFunction): ColumnDefinition<Banner>[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tager/admin-banners",
3
- "version": "0.3.3",
3
+ "version": "0.3.7",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.esm.js",
@@ -27,9 +27,9 @@
27
27
  "@rollup/plugin-commonjs": "^15.0.0",
28
28
  "@rollup/plugin-node-resolve": "^9.0.0",
29
29
  "@tager/admin-dynamic-field": "^0.1.18",
30
- "@tager/admin-layout": "^0.5.3",
30
+ "@tager/admin-layout": "^0.5.4",
31
31
  "@tager/admin-services": "^0.2.26",
32
- "@tager/admin-ui": "^0.8.85",
32
+ "@tager/admin-ui": "^0.8.96",
33
33
  "@types/lodash.isequal": "^4.5.5",
34
34
  "@types/lodash.pick": "^4.4.6",
35
35
  "@types/node": "12.x",
@@ -0,0 +1,48 @@
1
+ import {
2
+ computed,
3
+ onMounted,
4
+ Ref,
5
+ SetupContext,
6
+ watch,
7
+ } from '@vue/composition-api';
8
+
9
+ import { Nullable, ResourceRef, useResource } from '@tager/admin-services';
10
+
11
+ import { getZoneFields } from '../services/requests';
12
+ import { ZoneFields } from '../typings/zones';
13
+ import { BannerFormValues } from '../typings/banners';
14
+
15
+ export function useFetchZoneFields({
16
+ context,
17
+ values,
18
+ }: {
19
+ context: SetupContext;
20
+ values: Ref<BannerFormValues>;
21
+ }): ResourceRef<Nullable<ZoneFields>> {
22
+ const zoneId = computed(() => values.value.bannerZone?.value ?? '');
23
+
24
+ const [fetchZoneFields, resource] = useResource<Nullable<ZoneFields>>({
25
+ fetchResource: () => getZoneFields(zoneId.value),
26
+ initialValue: null,
27
+ context,
28
+ resourceName: 'Zone Fields',
29
+ });
30
+
31
+ onMounted(() => {
32
+ if (!zoneId.value) {
33
+ return;
34
+ }
35
+
36
+ fetchZoneFields();
37
+ });
38
+
39
+ watch(zoneId, () => {
40
+ if (!zoneId.value) {
41
+ return;
42
+ }
43
+
44
+ fetchZoneFields();
45
+ });
46
+
47
+ return resource;
48
+ }
package/src/locales/en.ts CHANGED
@@ -23,6 +23,8 @@ const EN = {
23
23
  remove: 'Remove',
24
24
  actions: 'actions',
25
25
  date: 'Date',
26
+ name: 'Name',
27
+ priority: 'Priority',
26
28
 
27
29
  success: 'Success',
28
30
  error: 'Error',
package/src/locales/ru.ts CHANGED
@@ -25,6 +25,8 @@ const RU: typeof EN = {
25
25
  remove: 'Удалить',
26
26
  actions: 'Действия',
27
27
  date: 'Дата',
28
+ name: 'Название',
29
+ priority: 'Приоритет',
28
30
 
29
31
  success: 'Успех',
30
32
  error: 'Ошибка',
@@ -1,6 +1,6 @@
1
1
  import { request, ResponseBody } from '@tager/admin-services';
2
2
 
3
- import { Zone } from '../typings/zones';
3
+ import { Zone, ZoneFields } from '../typings/zones';
4
4
  import { Banner, BannerPayload } from '../typings/banners';
5
5
 
6
6
  /** Zones **/
@@ -13,6 +13,12 @@ export function getZones(params?: {
13
13
  return request.get({ path: '/admin/adv/zones', params });
14
14
  }
15
15
 
16
+ export function getZoneFields(
17
+ zoneId: string
18
+ ): Promise<ResponseBody<ZoneFields>> {
19
+ return request.get({ path: `/admin/adv/zones/${zoneId}` });
20
+ }
21
+
16
22
  /** Banners **/
17
23
 
18
24
  export function getBanners(params?: {
@@ -1,5 +1,11 @@
1
1
  import { FileType, Nullable } from '@tager/admin-services';
2
2
  import { OptionType, SingleFileInputValueType } from '@tager/admin-ui';
3
+ import {
4
+ FieldShortType,
5
+ FieldUnion,
6
+ IncomingValueUnion,
7
+ OutgoingValueUnion,
8
+ } from '@tager/admin-dynamic-field';
3
9
 
4
10
  export enum Status {
5
11
  Waiting = 'WAITING',
@@ -11,6 +17,7 @@ export enum Status {
11
17
  export interface Banner {
12
18
  id: number;
13
19
  status: Status;
20
+ priority: number;
14
21
  link: Nullable<string>;
15
22
  image: Nullable<FileType>;
16
23
  bannerZone: Nullable<string>;
@@ -19,26 +26,31 @@ export interface Banner {
19
26
  dateEnd: Nullable<string>;
20
27
  disabled: boolean;
21
28
  comment: Nullable<string>;
29
+ fields: FieldShortType<IncomingValueUnion>[];
22
30
  }
23
31
 
24
32
  export interface BannerFormValues {
25
33
  link: Nullable<string>;
26
34
  image: Nullable<SingleFileInputValueType>;
27
35
  bannerZone: Nullable<OptionType>;
36
+ priority: string;
28
37
  openNewTab: boolean;
29
38
  dateStart: string;
30
39
  dateEnd: string;
31
40
  disabled: boolean;
32
41
  comment: string;
42
+ fields: FieldUnion[];
33
43
  }
34
44
 
35
45
  export interface BannerPayload {
36
46
  link: Nullable<string>;
37
47
  image: Nullable<string>;
48
+ priority: number;
38
49
  bannerZone: string;
39
50
  openNewTab: boolean;
40
- dateStart: string;
41
- dateEnd: string;
51
+ dateStart: Nullable<string>;
52
+ dateEnd: Nullable<string>;
42
53
  disabled: boolean;
43
54
  comment: string;
55
+ fields: FieldShortType<OutgoingValueUnion>[];
44
56
  }
@@ -1,5 +1,11 @@
1
+ import { FieldConfigUnion } from '@tager/admin-dynamic-field';
2
+
1
3
  export interface Zone {
2
4
  id: string;
3
5
  name: string;
4
6
  bannersCount: number;
5
7
  }
8
+
9
+ export interface ZoneFields extends Zone {
10
+ fields: FieldConfigUnion[];
11
+ }
@@ -1,5 +1,6 @@
1
1
  import { OptionType } from '@tager/admin-ui';
2
2
  import { createId, Nullable } from '@tager/admin-services';
3
+ import { universalFieldUtils } from '@tager/admin-dynamic-field';
3
4
 
4
5
  import {
5
6
  Banner,
@@ -16,6 +17,7 @@ export function convertBannerToFormValues(
16
17
  );
17
18
 
18
19
  return {
20
+ priority: String(banner?.priority ?? 1),
19
21
  link: banner?.link ?? '',
20
22
  image: banner?.image ? { id: createId(), file: banner.image } : null,
21
23
  bannerZone: foundZone ?? null,
@@ -24,6 +26,7 @@ export function convertBannerToFormValues(
24
26
  dateEnd: banner?.dateEnd ?? '',
25
27
  disabled: banner?.disabled ?? false,
26
28
  comment: banner?.comment ?? '',
29
+ fields: [],
27
30
  };
28
31
  }
29
32
 
@@ -32,7 +35,14 @@ export function convertBannerFormValuesToPayload(
32
35
  ): BannerPayload {
33
36
  return {
34
37
  ...values,
38
+ priority: values.priority ? Number(values.priority) : 1,
39
+ dateStart: values.dateStart ? values.dateStart : null,
40
+ dateEnd: values.dateEnd ? values.dateEnd : null,
35
41
  image: values.image?.file.id ?? null,
36
42
  bannerZone: values.bannerZone?.value ?? '',
43
+ fields: values.fields.map((field) => ({
44
+ name: field.config.name,
45
+ value: universalFieldUtils.getOutgoingValue(field),
46
+ })),
37
47
  };
38
48
  }
@@ -7,35 +7,22 @@
7
7
  >
8
8
  <template v-slot:content>
9
9
  <form novalidate @submit.prevent="submitForm">
10
- <form-field-select
11
- v-model="values.bannerZone"
12
- name="bannerZone"
13
- :label="$t('banners:zone')"
14
- :options="zonesOptionList"
15
- :error="errors.bannerZone"
16
- />
17
-
18
- <form-field-file-input
19
- v-model="values.image"
20
- name="image"
21
- file-type="image"
22
- :label="$t('banners:image')"
23
- :error="errors.file"
24
- />
25
-
26
- <form-field
27
- v-model="values.link"
28
- name="link"
29
- :label="$t('banners:link')"
30
- :error="errors.name"
31
- />
10
+ <div class="zone">
11
+ <form-field-select
12
+ v-model="values.bannerZone"
13
+ name="bannerZone"
14
+ :label="$t('banners:zone')"
15
+ :options="zonesOptionList"
16
+ :error="errors.bannerZone"
17
+ />
32
18
 
33
- <form-field-checkbox
34
- v-model="values.openNewTab"
35
- name="openNewTab"
36
- :label="$t('banners:openNewTab')"
37
- :error="errors.openNewTab"
38
- />
19
+ <form-field
20
+ v-model="values.priority"
21
+ name="priority"
22
+ :label="$t('banners:priority')"
23
+ :error="errors.priority"
24
+ />
25
+ </div>
39
26
 
40
27
  <input-label>{{ $t('banners:period') }}</input-label>
41
28
 
@@ -64,6 +51,36 @@
64
51
  :error="errors.disabled"
65
52
  />
66
53
 
54
+ <div class="link">
55
+ <form-field
56
+ v-model="values.link"
57
+ name="link"
58
+ :label="$t('banners:link')"
59
+ :error="errors.name"
60
+ />
61
+
62
+ <form-field-checkbox
63
+ v-model="values.openNewTab"
64
+ name="openNewTab"
65
+ :label="$t('banners:openNewTab')"
66
+ :error="errors.openNewTab"
67
+ />
68
+ </div>
69
+
70
+ <form-field-file-input
71
+ v-model="values.image"
72
+ name="image"
73
+ file-type="image"
74
+ :label="$t('banners:image')"
75
+ :error="errors.file"
76
+ />
77
+
78
+ <DynamicField
79
+ v-for="field of values.fields"
80
+ :key="field.name"
81
+ :field="field"
82
+ />
83
+
67
84
  <form-field
68
85
  v-model="values.comment"
69
86
  name="comment"
@@ -96,6 +113,7 @@ import {
96
113
  } from '@vue/composition-api';
97
114
 
98
115
  import { FormFooter, OptionType, TagerFormSubmitEvent } from '@tager/admin-ui';
116
+ import { DynamicField, universalFieldUtils } from '@tager/admin-dynamic-field';
99
117
  import { convertRequestErrorToMap } from '@tager/admin-services';
100
118
 
101
119
  import { useFetchZones } from '../../../hooks';
@@ -106,6 +124,7 @@ import {
106
124
  getBannersBannerListUrl,
107
125
  } from '../../../constants/paths';
108
126
  import { createBanner, updateBanner } from '../../../services/requests';
127
+ import { useFetchZoneFields } from '../../../hooks/useFetchZoneFields';
109
128
 
110
129
  import {
111
130
  convertBannerFormValuesToPayload,
@@ -114,7 +133,7 @@ import {
114
133
 
115
134
  export default defineComponent({
116
135
  name: 'BannerForm',
117
- components: { FormFooter },
136
+ components: { FormFooter, DynamicField },
118
137
  setup(props, context: SetupContext) {
119
138
  const bannerId = computed<string>(
120
139
  () => context.root.$route.params.bannerId
@@ -155,6 +174,24 @@ export default defineComponent({
155
174
  );
156
175
  });
157
176
 
177
+ /** Zone Fields **/
178
+
179
+ const {
180
+ loading: isZoneFieldsLoading,
181
+ data: zoneFields,
182
+ } = useFetchZoneFields({ context, values });
183
+
184
+ watch(zoneFields, () => {
185
+ values.value.fields = (
186
+ zoneFields.value?.fields ?? []
187
+ ).map((fieldConfig, index) =>
188
+ universalFieldUtils.createFormField(
189
+ fieldConfig,
190
+ banner.value ? banner.value.fields[index].value ?? null : null
191
+ )
192
+ );
193
+ });
194
+
158
195
  const submitForm = (event: TagerFormSubmitEvent) => {
159
196
  isSubmitting.value = true;
160
197
 
@@ -210,7 +247,10 @@ export default defineComponent({
210
247
  };
211
248
 
212
249
  const isContentLoading = computed<boolean>(
213
- () => isBannerLoading.value || isZonesLoading.value
250
+ () =>
251
+ isBannerLoading.value ||
252
+ isZonesLoading.value ||
253
+ isZoneFieldsLoading.value
214
254
  );
215
255
 
216
256
  return {
@@ -233,4 +273,32 @@ export default defineComponent({
233
273
  grid-template-columns: repeat(2, 1fr);
234
274
  column-gap: 10px;
235
275
  }
276
+
277
+ .zone {
278
+ display: flex;
279
+
280
+ > *:first-child {
281
+ flex: 1 1 1px;
282
+ }
283
+
284
+ > *:last-child {
285
+ flex-basis: 30%;
286
+ margin-left: 20px;
287
+ }
288
+ }
289
+
290
+ .link {
291
+ display: flex;
292
+ align-items: flex-end;
293
+
294
+ > *:first-child {
295
+ flex: 1 1 1px;
296
+ }
297
+
298
+ > *:last-child {
299
+ flex-basis: 30%;
300
+ margin-left: 20px;
301
+ padding-bottom: 8px;
302
+ }
303
+ }
236
304
  </style>
@@ -3,6 +3,7 @@ import { TFunction } from 'i18next';
3
3
  import { ColumnDefinition } from '@tager/admin-ui';
4
4
 
5
5
  import { Banner, Status } from '../../../typings/banners';
6
+ import { Zone } from '../../../typings/zones';
6
7
 
7
8
  export function getStatus(type: Status, t: TFunction) {
8
9
  switch (type) {
@@ -20,12 +21,16 @@ export function getStatus(type: Status, t: TFunction) {
20
21
  }
21
22
  }
22
23
 
23
- export function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[] {
24
+ export function getColumnDefs(
25
+ zoneList: Zone[],
26
+ t: TFunction
27
+ ): ColumnDefinition<Banner>[] {
24
28
  return [
25
29
  {
26
30
  id: 0,
27
31
  name: '#',
28
32
  field: 'id',
33
+ format: ({ rowIndex }) => String(rowIndex + 1),
29
34
  style: { width: '50px', textAlign: 'center' },
30
35
  headStyle: { width: '50px', textAlign: 'center' },
31
36
  },
@@ -33,8 +38,14 @@ export function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[] {
33
38
  id: 1,
34
39
  name: t('banners:zone'),
35
40
  field: 'bannerZone',
36
- format: ({ row }) =>
37
- row.bannerZone ? row.bannerZone : t('banners:bannerZoneIsDeleted'),
41
+ format: ({ row }) => {
42
+ const foundBannerZone = zoneList.find(
43
+ (zone) => zone.id === row.bannerZone
44
+ );
45
+ return foundBannerZone
46
+ ? foundBannerZone.name
47
+ : t('banners:bannerZoneIsDeleted');
48
+ },
38
49
  },
39
50
  {
40
51
  id: 2,
@@ -46,6 +57,13 @@ export function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[] {
46
57
  },
47
58
  {
48
59
  id: 3,
60
+ name: t('banners:priority'),
61
+ field: 'priority',
62
+ style: { width: '100px', textAlign: 'center' },
63
+ headStyle: { width: '100px', textAlign: 'center' },
64
+ },
65
+ {
66
+ id: 4,
49
67
  name: t('banners:period'),
50
68
  field: 'dateStart',
51
69
  format: ({ row }) =>
@@ -54,13 +72,13 @@ export function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[] {
54
72
  }`,
55
73
  },
56
74
  {
57
- id: 4,
75
+ id: 5,
58
76
  name: t('banners:image'),
59
77
  field: 'image',
60
78
  type: 'image',
61
79
  },
62
80
  {
63
- id: 5,
81
+ id: 6,
64
82
  name: t('banners:link'),
65
83
  field: 'link',
66
84
  type: 'name',
@@ -76,14 +94,17 @@ export function getColumnDefs(t: TFunction): ColumnDefinition<Banner>[] {
76
94
  },
77
95
  ],
78
96
  }),
97
+ options: {
98
+ shouldOpenNewTab: true,
99
+ },
79
100
  },
80
101
  {
81
- id: 6,
102
+ id: 7,
82
103
  name: t('banners:comment'),
83
104
  field: 'comment',
84
105
  },
85
106
  {
86
- id: 7,
107
+ id: 8,
87
108
  name: t('banners:actions'),
88
109
  field: 'actions',
89
110
  style: { whiteSpace: 'nowrap', width: '100px' },
@@ -181,7 +181,7 @@ export default defineComponent({
181
181
  };
182
182
 
183
183
  const columnDefs = computed<ColumnDefinition<Banner>[]>(() =>
184
- getColumnDefs(context.root.$t)
184
+ getColumnDefs(zoneList.value, context.root.$t)
185
185
  );
186
186
 
187
187
  const isRowDataLoading = computed<boolean>(
@@ -112,7 +112,7 @@ export function useAdvancedSearch({ context, t, zoneList }: Params): State {
112
112
  const filterParams = computed(() =>
113
113
  getFilterParams({
114
114
  [FilterTypes.Zone]: zoneFilter.value.map(({ value }) => value),
115
- [FilterTypes.Date]: dateFilter.value,
115
+ [FilterTypes.Date]: dateFilter.value || [],
116
116
  [FilterTypes.Status]: statusFilter.value.map(({ value }) => value),
117
117
  })
118
118
  );