@tager/admin-banners 0.1.5 → 0.3.0

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 (80) hide show
  1. package/CHANGELOG.md +13 -13
  2. package/dist/constants/menu.d.ts +4 -1
  3. package/dist/constants/paths.d.ts +8 -15
  4. package/dist/constants/routes.d.ts +3 -4
  5. package/dist/hooks/index.d.ts +2 -0
  6. package/dist/hooks/useFetchBanner.d.ts +8 -0
  7. package/dist/hooks/useFetchBanners.d.ts +6 -0
  8. package/dist/hooks/useFetchZones.d.ts +6 -0
  9. package/dist/index.esm.js +3200 -875
  10. package/dist/index.umd.js +3213 -886
  11. package/dist/locales/en.d.ts +39 -0
  12. package/dist/locales/ru.d.ts +3 -0
  13. package/dist/{index.d.ts → main.d.ts} +1 -0
  14. package/dist/router/index.d.ts +4 -0
  15. package/dist/services/requests.d.ts +19 -35
  16. package/dist/typings/banners.d.ts +40 -0
  17. package/dist/typings/common.d.ts +1 -0
  18. package/dist/typings/model.d.ts +103 -15
  19. package/dist/typings/zones.d.ts +5 -0
  20. package/dist/utils/common.d.ts +2 -0
  21. package/dist/views/Banners/BannerForm/BannerForm.helpers.d.ts +5 -0
  22. package/dist/views/Banners/BannerForm/BannerForm.vue.d.ts +81 -0
  23. package/dist/views/Banners/BannerForm/index.d.ts +1 -0
  24. package/dist/views/Banners/BannerList/BannerList.helpers.d.ts +5 -0
  25. package/dist/views/Banners/BannerList/BannerList.vue.d.ts +55 -0
  26. package/dist/views/Banners/BannerList/hooks/index.d.ts +1 -0
  27. package/dist/views/Banners/BannerList/hooks/useAdvancedSearch.d.ts +21 -0
  28. package/dist/views/Banners/BannerList/index.d.ts +1 -0
  29. package/dist/views/Zones/ZoneList/ZoneList.helpers.d.ts +5 -0
  30. package/dist/views/Zones/ZoneList/ZoneList.vue.d.ts +28 -0
  31. package/dist/views/Zones/ZoneList/index.d.ts +1 -0
  32. package/package.json +76 -67
  33. package/src/config/config.json +19 -19
  34. package/src/constants/menu.ts +26 -12
  35. package/src/constants/paths.ts +19 -36
  36. package/src/constants/routes.ts +44 -66
  37. package/src/dev.ts +22 -34
  38. package/src/hooks/index.ts +2 -0
  39. package/src/hooks/useFetchBanner.ts +41 -0
  40. package/src/hooks/useFetchBanners.ts +23 -0
  41. package/src/hooks/useFetchZones.ts +23 -0
  42. package/src/locales/en.ts +43 -0
  43. package/src/locales/ru.ts +45 -0
  44. package/src/main.ts +12 -0
  45. package/src/router/index.ts +38 -0
  46. package/src/services/requests.ts +52 -107
  47. package/src/typings/banners.ts +44 -0
  48. package/src/typings/common.ts +1 -0
  49. package/src/typings/model.ts +121 -18
  50. package/src/typings/sfc.d.ts +12 -12
  51. package/src/typings/shims-tsx.d.ts +13 -13
  52. package/src/typings/shims-vue.d.ts +11 -10
  53. package/src/typings/translate.d.ts +10 -0
  54. package/src/typings/zones.ts +5 -0
  55. package/src/utils/common.ts +13 -0
  56. package/src/views/App.vue +22 -22
  57. package/src/views/Banners/BannerForm/BannerForm.helpers.ts +38 -0
  58. package/src/views/Banners/BannerForm/BannerForm.vue +236 -0
  59. package/src/views/Banners/BannerForm/index.ts +1 -0
  60. package/src/views/Banners/BannerList/BannerList.helpers.ts +93 -0
  61. package/src/views/Banners/BannerList/BannerList.vue +233 -0
  62. package/src/views/Banners/BannerList/hooks/index.ts +1 -0
  63. package/src/views/Banners/BannerList/hooks/useAdvancedSearch.ts +152 -0
  64. package/src/views/Banners/BannerList/index.ts +1 -0
  65. package/src/views/Home.vue +37 -0
  66. package/src/views/Zones/ZoneList/ZoneList.helpers.ts +34 -0
  67. package/src/views/Zones/ZoneList/ZoneList.vue +75 -0
  68. package/src/views/Zones/ZoneList/index.ts +1 -0
  69. package/dist/views/BannerAreaForm.vue.d.ts +0 -22
  70. package/dist/views/BannerAreaList.vue.d.ts +0 -17
  71. package/dist/views/BannerItemForm.vue.d.ts +0 -27
  72. package/dist/views/BannerItemList.vue.d.ts +0 -22
  73. package/src/index.ts +0 -3
  74. package/src/locales/en.js +0 -3
  75. package/src/locales/ru.js +0 -3
  76. package/src/views/BannerAreaForm.vue +0 -173
  77. package/src/views/BannerAreaList.vue +0 -176
  78. package/src/views/BannerItemForm.vue +0 -230
  79. package/src/views/BannerItemList.vue +0 -221
  80. package/typings/index.d.ts +0 -15
@@ -0,0 +1,152 @@
1
+ import {
2
+ computed,
3
+ ComputedRef,
4
+ ref,
5
+ Ref,
6
+ SetupContext,
7
+ watch,
8
+ } from '@vue/composition-api';
9
+ import { TFunction } from 'i18next';
10
+
11
+ import {
12
+ FilterTagType,
13
+ getFilterParamAsString,
14
+ getFilterParamAsStringArray,
15
+ getFilterParams,
16
+ OptionType,
17
+ } from '@tager/admin-ui';
18
+
19
+ import { Zone } from '../../../../typings/zones';
20
+ import { Status } from '../../../../typings/banners';
21
+ import { getStatus } from '../BannerList.helpers';
22
+
23
+ interface Params {
24
+ context: SetupContext;
25
+ t: TFunction;
26
+ zoneList: ComputedRef<Zone[]>;
27
+ }
28
+
29
+ interface State {
30
+ zoneFilter: Ref<OptionType[]>;
31
+ zonesOptionList: ComputedRef<OptionType[]>;
32
+ dateFilter: Ref<string>;
33
+ statusFilter: Ref<OptionType[]>;
34
+ statusesOptionList: ComputedRef<OptionType[]>;
35
+ filterParams: ComputedRef<Record<string, string | string[]>>;
36
+ tags: ComputedRef<FilterTagType[]>;
37
+ tagRemovalHandler(event: FilterTagType): void;
38
+ }
39
+
40
+ enum FilterTypes {
41
+ Zone = 'zone',
42
+ Date = 'date',
43
+ Status = 'status',
44
+ }
45
+
46
+ export function useAdvancedSearch({ context, t, zoneList }: Params): State {
47
+ /** Zone **/
48
+
49
+ const zonesOptionList = computed<OptionType[]>(() =>
50
+ zoneList.value.map(({ id, name }) => ({
51
+ value: id,
52
+ label: name,
53
+ }))
54
+ );
55
+
56
+ const initialZoneFilter = computed<OptionType[]>(() => {
57
+ const queryValue = getFilterParamAsStringArray(
58
+ context.root.$route.query,
59
+ FilterTypes.Zone
60
+ );
61
+ return zonesOptionList.value.filter(({ value }) =>
62
+ queryValue.some((selected) => selected === value)
63
+ );
64
+ });
65
+
66
+ const zoneFilter = ref<OptionType[]>(initialZoneFilter.value);
67
+
68
+ watch(initialZoneFilter, () => {
69
+ zoneFilter.value = initialZoneFilter.value;
70
+ });
71
+
72
+ /** Date **/
73
+
74
+ const initialDateFilter = computed<string>(
75
+ () =>
76
+ getFilterParamAsString(context.root.$route.query, FilterTypes.Date) ?? ''
77
+ );
78
+
79
+ const dateFilter = ref<string>(initialDateFilter.value);
80
+
81
+ watch(initialDateFilter, () => {
82
+ dateFilter.value = initialDateFilter.value;
83
+ });
84
+
85
+ /** Status **/
86
+
87
+ const statusesOptionList = computed<OptionType[]>(() =>
88
+ Object.entries(Status).map(([_, value]) => ({
89
+ value: value,
90
+ label: getStatus(value, t),
91
+ }))
92
+ );
93
+
94
+ const initialStatusFilter = computed<OptionType[]>(() => {
95
+ const queryValue = getFilterParamAsStringArray(
96
+ context.root.$route.query,
97
+ FilterTypes.Status
98
+ );
99
+ return statusesOptionList.value.filter(({ value }) =>
100
+ queryValue.some((selected) => selected === value)
101
+ );
102
+ });
103
+
104
+ const statusFilter = ref<OptionType[]>(initialStatusFilter.value);
105
+
106
+ watch(initialStatusFilter, () => {
107
+ statusFilter.value = initialStatusFilter.value;
108
+ });
109
+
110
+ /** Params **/
111
+
112
+ const filterParams = computed(() =>
113
+ getFilterParams({
114
+ [FilterTypes.Zone]: zoneFilter.value.map(({ value }) => value),
115
+ [FilterTypes.Date]: dateFilter.value,
116
+ [FilterTypes.Status]: statusFilter.value.map(({ value }) => value),
117
+ })
118
+ );
119
+
120
+ /** Tag removal handler **/
121
+
122
+ const tagRemovalHandler = (event: FilterTagType): void => {
123
+ if (event.name === FilterTypes.Zone) {
124
+ zoneFilter.value = zoneFilter.value.filter(
125
+ ({ value }) => value !== event.value
126
+ );
127
+ }
128
+ if (event.name === FilterTypes.Date) {
129
+ dateFilter.value = '';
130
+ }
131
+ if (event.name === FilterTypes.Status) {
132
+ statusFilter.value = statusFilter.value.filter(
133
+ ({ value }) => value !== event.value
134
+ );
135
+ }
136
+ };
137
+
138
+ /** Tags **/
139
+
140
+ const tags = computed<FilterTagType[]>(() => []);
141
+
142
+ return {
143
+ zoneFilter,
144
+ zonesOptionList,
145
+ dateFilter,
146
+ statusFilter,
147
+ statusesOptionList,
148
+ filterParams,
149
+ tags,
150
+ tagRemovalHandler,
151
+ };
152
+ }
@@ -0,0 +1 @@
1
+ export { default } from './BannerList.vue';
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <navigation-grid :nav-items="navItemList" />
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { defineComponent, ref } from '@vue/composition-api';
7
+
8
+ import { NavigationGridItem } from '@tager/admin-ui';
9
+
10
+ import {
11
+ getBannersZoneListUrl,
12
+ getBannersBannerListUrl,
13
+ } from '../constants/paths';
14
+
15
+ export default defineComponent({
16
+ name: 'Home',
17
+ setup(props, context) {
18
+ const navItemList = ref<NavigationGridItem[]>([
19
+ {
20
+ name: context.root.$t('banners:banners'),
21
+ linkList: [
22
+ {
23
+ url: getBannersZoneListUrl(),
24
+ text: context.root.$t('banners:zones'),
25
+ },
26
+ {
27
+ url: getBannersBannerListUrl(),
28
+ text: context.root.$t('banners:banners'),
29
+ },
30
+ ],
31
+ },
32
+ ]);
33
+
34
+ return { navItemList };
35
+ },
36
+ });
37
+ </script>
@@ -0,0 +1,34 @@
1
+ import { TFunction } from 'i18next';
2
+
3
+ import { ColumnDefinition } from '@tager/admin-ui';
4
+
5
+ import { Zone } from '../../../typings/zones';
6
+ import { getBannersBannerListUrl } from '../../../constants/paths';
7
+
8
+ export function getColumnDefs(t: TFunction): ColumnDefinition<Zone>[] {
9
+ return [
10
+ {
11
+ id: 0,
12
+ name: 'ID',
13
+ field: 'id',
14
+ style: { width: '50px', textAlign: 'center' },
15
+ headStyle: { width: '50px', textAlign: 'center' },
16
+ },
17
+ {
18
+ id: 1,
19
+ name: t('banners:name'),
20
+ field: 'name',
21
+ type: 'name',
22
+ },
23
+ {
24
+ id: 2,
25
+ name: t('banners:banners'),
26
+ field: 'bannersCount',
27
+ style: { whiteSpace: 'nowrap', width: '130px' },
28
+ },
29
+ ];
30
+ }
31
+
32
+ export function getLinkToBannersByZone(zoneId: number): string {
33
+ return `${getBannersBannerListUrl()}?filter[zone]=${zoneId}`;
34
+ }
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <page :title="$t('banners:zones')">
3
+ <template v-slot:content>
4
+ <data-table
5
+ :column-defs="columnDefs"
6
+ :row-data="rowData"
7
+ :loading="isRowDataLoading"
8
+ :error-message="errorMessage"
9
+ data-table="banners-zones"
10
+ :use-search="false"
11
+ :use-pagination="false"
12
+ @change="handleChange"
13
+ >
14
+ <template v-slot:cell(banners-count)="{ row }">
15
+ <count-button
16
+ :href="getLinkToBannersByZone(row.id)"
17
+ variant="outline-secondary"
18
+ :count="row.bannersCount"
19
+ >
20
+ {{ $t('banners:banners') }}
21
+ </count-button>
22
+ </template>
23
+ </data-table>
24
+ </template>
25
+ </page>
26
+ </template>
27
+
28
+ <script lang="ts">
29
+ import {
30
+ computed,
31
+ defineComponent,
32
+ onMounted,
33
+ SetupContext,
34
+ } from '@vue/composition-api';
35
+
36
+ import { useDataTable } from '@tager/admin-ui';
37
+
38
+ import { Zone } from '../../../typings/zones';
39
+ import { getZones } from '../../../services/requests';
40
+
41
+ import { getColumnDefs, getLinkToBannersByZone } from './ZoneList.helpers';
42
+
43
+ export default defineComponent({
44
+ name: 'ZoneList',
45
+ setup(props, context: SetupContext) {
46
+ const {
47
+ fetchEntityList: fetchZones,
48
+ isLoading: isZonesLoading,
49
+ rowData,
50
+ errorMessage,
51
+ handleChange,
52
+ } = useDataTable<Zone>({
53
+ fetchEntityList: getZones,
54
+ initialValue: [],
55
+ context,
56
+ resourceName: 'Banner Zones',
57
+ });
58
+
59
+ onMounted(() => {
60
+ fetchZones();
61
+ });
62
+
63
+ const columnDefs = computed(() => getColumnDefs(context.root.$t));
64
+
65
+ return {
66
+ columnDefs,
67
+ isRowDataLoading: isZonesLoading,
68
+ rowData,
69
+ errorMessage,
70
+ handleChange,
71
+ getLinkToBannersByZone,
72
+ };
73
+ },
74
+ });
75
+ </script>
@@ -0,0 +1 @@
1
+ export { default } from './ZoneList.vue';
@@ -1,22 +0,0 @@
1
- import Vue from 'vue';
2
- import { BannerArea } from '../typings/model';
3
- import { getBannerAreaListUrl } from '../constants/paths';
4
- declare type FormValues = {
5
- alias: string;
6
- label: string;
7
- scenario: string;
8
- };
9
- declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
10
- values: FormValues;
11
- errors: Record<string, string>;
12
- isContentLoading: boolean;
13
- }, {
14
- convertReviewToInitialValues(bannerArea: BannerArea): FormValues;
15
- updateValues(): void;
16
- submitForm(): void;
17
- getAreaListUrl: typeof getBannerAreaListUrl;
18
- }, {
19
- areaId: string;
20
- isCreation: boolean;
21
- }, Record<never, any>>;
22
- export default _default;
@@ -1,17 +0,0 @@
1
- import Vue from 'vue';
2
- import { ColumnDefinition } from '@tager/admin-ui';
3
- import { Nullable } from '@tager/admin-services';
4
- import { BannerArea } from '../typings/model';
5
- declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
6
- columnDefs: Array<ColumnDefinition<BannerArea>>;
7
- rowData: Array<BannerArea>;
8
- deletingBannerAreaIdList: Array<number>;
9
- isRowDataLoading: boolean;
10
- errorMessage: Nullable<string>;
11
- }, {
12
- getBannerAreaUrl(areaId: number | string): string;
13
- refreshBannerAreaList(): Promise<void>;
14
- handleBannerAreaDelete(bannerArea: BannerArea): void;
15
- getLinkToBannerItems(areaAlias: string): string;
16
- }, unknown, Record<never, any>>;
17
- export default _default;
@@ -1,27 +0,0 @@
1
- import Vue from 'vue';
2
- import { FileType, Nullable } from '@tager/admin-services';
3
- import { BannerArea, BannerItem } from '../typings/model';
4
- declare type FormValues = {
5
- title: string;
6
- text: string;
7
- buttonLink: string;
8
- buttonLabel: string;
9
- buttonIsNewTab: boolean;
10
- image: Nullable<FileType>;
11
- };
12
- declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
13
- values: FormValues;
14
- errors: Record<string, string>;
15
- isContentLoading: boolean;
16
- bannerArea: Nullable<BannerArea>;
17
- }, {
18
- updateValues(): void;
19
- convertReviewToInitialValues(bannerItem: BannerItem): FormValues;
20
- submitForm(): void;
21
- }, {
22
- itemId: string;
23
- areaAlias: string;
24
- isCreation: boolean;
25
- bannerItemListUrl: string;
26
- }, Record<never, any>>;
27
- export default _default;
@@ -1,22 +0,0 @@
1
- import Vue from 'vue';
2
- import { ColumnDefinition } from '@tager/admin-ui';
3
- import { Nullable } from '@tager/admin-services';
4
- import { BannerArea, BannerItem } from '../typings/model';
5
- declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
6
- columnDefs: Array<ColumnDefinition<BannerItem>>;
7
- rowData: Array<BannerItem>;
8
- deletingBannerItemIdList: Array<number>;
9
- isBannerItemMoving: boolean;
10
- isRowDataLoading: boolean;
11
- errorMessage: Nullable<string>;
12
- bannerArea: Nullable<BannerArea>;
13
- }, {
14
- refreshBannerItemList(): Promise<void>;
15
- moveBannerItem(bannerItemId: number, direction: 'up' | 'down'): void;
16
- handleBannerItemDelete(bannerItem: BannerItem): void;
17
- getLinkToBannerItemForm(bannerItemId: number | string): string;
18
- }, {
19
- areaAlias: string;
20
- pageTitle: string;
21
- }, Record<never, any>>;
22
- export default _default;
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './constants/routes';
2
- export * from './constants/menu';
3
- export * from './constants/paths';
package/src/locales/en.js DELETED
@@ -1,3 +0,0 @@
1
- const EN = {};
2
-
3
- export default EN;
package/src/locales/ru.js DELETED
@@ -1,3 +0,0 @@
1
- const RU = {};
2
-
3
- export default RU;
@@ -1,173 +0,0 @@
1
- <template>
2
- <page
3
- :title="isCreation ? 'Create Banner Area' : 'Update Banner Area'"
4
- :is-content-loading="isContentLoading"
5
- :footer="{ onSubmit: submitForm, backHref: getAreaListUrl() }"
6
- >
7
- <template v-slot:content>
8
- <form novalidate @submit.prevent="submitForm">
9
- <form-field
10
- v-model="values.alias"
11
- name="alias"
12
- label="Alias"
13
- :error="errors.alias"
14
- />
15
-
16
- <form-field
17
- v-model="values.label"
18
- name="label"
19
- label="Label"
20
- :error="errors.label"
21
- />
22
-
23
- <form-field
24
- v-model="values.scenario"
25
- name="scenario"
26
- label="Scenario"
27
- :error="errors.scenario"
28
- />
29
- </form>
30
- </template>
31
- </page>
32
- </template>
33
-
34
- <script lang="ts">
35
- import Vue from 'vue';
36
- import { convertRequestErrorToMap } from '@tager/admin-services';
37
-
38
- import {
39
- BannerAreaCreatePayload,
40
- createBannerArea,
41
- getBannerAreaById,
42
- updateBannerArea,
43
- } from '../services/requests';
44
- import { BannerArea } from '../typings/model';
45
- import { getBannerAreaListUrl } from '../constants/paths';
46
-
47
- type FormValues = {
48
- alias: string;
49
- label: string;
50
- scenario: string;
51
- };
52
-
53
- const initialValues: FormValues = {
54
- alias: '',
55
- label: '',
56
- scenario: '',
57
- };
58
-
59
- export default Vue.extend({
60
- name: 'BannerAreaForm',
61
- data(): {
62
- values: FormValues;
63
- errors: Record<string, string>;
64
- isContentLoading: boolean;
65
- } {
66
- return {
67
- values: { ...initialValues },
68
- errors: {},
69
- isContentLoading: false,
70
- };
71
- },
72
- computed: {
73
- areaId(): string {
74
- return this.$route.params.areaId;
75
- },
76
- isCreation(): boolean {
77
- return this.areaId === 'create';
78
- },
79
- },
80
- watch: {
81
- areaId() {
82
- this.updateValues();
83
- },
84
- },
85
- mounted(): void {
86
- this.updateValues();
87
- },
88
- methods: {
89
- convertReviewToInitialValues(bannerArea: BannerArea): FormValues {
90
- return {
91
- alias: bannerArea.alias,
92
- label: bannerArea.label,
93
- scenario: bannerArea.scenario,
94
- };
95
- },
96
- updateValues() {
97
- if (this.isCreation) {
98
- this.values = { ...initialValues };
99
- } else {
100
- this.isContentLoading = true;
101
-
102
- getBannerAreaById(this.areaId)
103
- .then((response) => {
104
- this.values = this.convertReviewToInitialValues(response.data);
105
- })
106
- .catch(console.error)
107
- .finally(() => {
108
- this.isContentLoading = false;
109
- });
110
- }
111
- },
112
- submitForm() {
113
- const body: BannerAreaCreatePayload = {
114
- label: this.values.label,
115
- alias: this.values.alias,
116
- scenario: this.values.scenario,
117
- };
118
-
119
- const requestPromise = this.isCreation
120
- ? createBannerArea(body)
121
- : updateBannerArea(this.areaId, body);
122
-
123
- requestPromise
124
- .then(() => {
125
- this.errors = {};
126
- this.$router.push(getBannerAreaListUrl());
127
-
128
- this.$toast({
129
- variant: 'success',
130
- title: 'Success',
131
- body: `Banner Area was successfully ${
132
- this.isCreation ? 'created' : 'updated'
133
- }`,
134
- });
135
- })
136
- .catch((error) => {
137
- console.error(error);
138
- this.errors = convertRequestErrorToMap(error);
139
- this.$toast({
140
- variant: 'danger',
141
- title: 'Error',
142
- body: `Blog bannerArea ${
143
- this.isCreation ? 'creation' : 'update'
144
- } was failed`,
145
- });
146
- });
147
- },
148
- getAreaListUrl: getBannerAreaListUrl,
149
- },
150
- });
151
- </script>
152
-
153
- <style scoped lang="scss">
154
- .bottom {
155
- display: flex;
156
- justify-content: space-between;
157
- align-items: center;
158
- }
159
-
160
- .save-button {
161
- min-width: 100px;
162
- }
163
-
164
- .alias-field-inner {
165
- display: flex;
166
- align-items: center;
167
-
168
- span {
169
- font-size: 0.9em;
170
- margin-right: 10px;
171
- }
172
- }
173
- </style>