@tager/admin-administrators 0.2.6 → 1.0.1

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 (52) hide show
  1. package/dist/constants/paths.d.ts +6 -6
  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/index.mjs +940 -0
  8. package/dist/locales/apply.d.ts +1 -0
  9. package/dist/locales/en.d.ts +44 -41
  10. package/dist/locales/ru.d.ts +2 -3
  11. package/dist/main.d.ts +3 -3
  12. package/dist/services/requests.d.ts +36 -32
  13. package/dist/style.css +1 -0
  14. package/dist/typings/model.d.ts +27 -25
  15. package/dist/utils/paths.d.ts +8 -8
  16. package/dist/views/AdminForm/AdminForm.helpers.d.ts +15 -14
  17. package/dist/views/AdminForm/AdminForm.vue.d.ts +2686 -61
  18. package/dist/views/AdminForm/index.d.ts +1 -1
  19. package/dist/views/AdminList/AdminList.vue.d.ts +14 -33
  20. package/dist/views/AdminList/index.d.ts +1 -1
  21. package/dist/views/RoleForm/RoleForm.helpers.d.ts +13 -13
  22. package/dist/views/RoleForm/RoleForm.vue.d.ts +24 -59
  23. package/dist/views/RoleForm/index.d.ts +1 -1
  24. package/dist/views/RoleList/RoleList.vue.d.ts +20 -46
  25. package/dist/views/RoleList/index.d.ts +1 -1
  26. package/package.json +52 -50
  27. package/src/constants/routes.ts +19 -19
  28. package/src/dev/App.vue +57 -0
  29. package/src/dev/config.ts +23 -0
  30. package/src/dev/env.ts +17 -0
  31. package/src/dev/main.ts +50 -0
  32. package/src/locales/apply.ts +9 -0
  33. package/src/locales/en.ts +6 -3
  34. package/src/locales/ru.ts +6 -4
  35. package/src/main.ts +5 -9
  36. package/src/services/requests.ts +13 -0
  37. package/src/typings/model.ts +3 -0
  38. package/src/views/AdminForm/AdminForm.helpers.ts +10 -3
  39. package/src/views/AdminForm/AdminForm.vue +136 -43
  40. package/src/views/AdminList/AdminList.vue +54 -49
  41. package/src/views/RoleForm/RoleForm.vue +86 -81
  42. package/src/views/RoleList/RoleList.vue +78 -64
  43. package/CHANGELOG.md +0 -0
  44. package/dist/dev.d.ts +0 -1
  45. package/dist/index.esm.js +0 -1336
  46. package/dist/index.umd.js +0 -1359
  47. package/src/config/config.json +0 -20
  48. package/src/dev.ts +0 -51
  49. package/src/typings/sfc.d.ts +0 -12
  50. package/src/typings/shims-tsx.d.ts +0 -13
  51. package/src/typings/shims-vue.d.ts +0 -11
  52. package/src/views/App.vue +0 -52
package/src/locales/ru.ts CHANGED
@@ -1,6 +1,6 @@
1
- import EN from './en';
1
+ import { EN } from './en';
2
2
 
3
- const RU: typeof EN = {
3
+ export const RU: typeof EN = {
4
4
  home: 'Главная',
5
5
  administrators: 'Администраторы',
6
6
  role: 'Роль',
@@ -39,6 +39,8 @@ const RU: typeof EN = {
39
39
  roleList: 'Список ролей',
40
40
  roleForm: 'Форма роли',
41
41
  andMorePrivilege: 'и еще {{count}} привилегий...',
42
+ tabs: {
43
+ general: 'Основное',
44
+ params: 'Параметры',
45
+ },
42
46
  };
43
-
44
- export default RU;
package/src/main.ts CHANGED
@@ -1,11 +1,7 @@
1
- import { i18n } from '@tager/admin-services';
1
+ import {applyTranslations} from "./locales/apply";
2
2
 
3
- import EN from './locales/en';
4
- import RU from './locales/ru';
3
+ applyTranslations();
5
4
 
6
- i18n.addTranslations('en', 'administrators', EN);
7
- i18n.addTranslations('ru', 'administrators', RU);
8
-
9
- export * from './constants/routes';
10
- export * from './services/requests';
11
- export * from './utils/paths';
5
+ export * from "./constants/routes";
6
+ export * from "./utils/paths";
7
+ export * from "./services/requests";
@@ -1,9 +1,20 @@
1
1
  import { request, ResponseBody } from '@tager/admin-services';
2
+ import {
3
+ FieldConfigUnion,
4
+ FieldShortType,
5
+ OutgoingValueUnion,
6
+ } from '@tager/admin-dynamic-field';
2
7
 
3
8
  import { AdminType, RoleType, ScopeGroupsData } from '../typings/model';
4
9
 
5
10
  type SuccessData = { success: boolean };
6
11
 
12
+ /** Fields */
13
+
14
+ export function getFieldList(): Promise<ResponseBody<Array<FieldConfigUnion>>> {
15
+ return request.get({ path: '/admin/admins/fields' });
16
+ }
17
+
7
18
  /** Roles */
8
19
 
9
20
  export function getRoleList(): Promise<ResponseBody<Array<RoleType>>> {
@@ -63,6 +74,8 @@ export type AdminUpdatePayload = {
63
74
  email: string;
64
75
  roles: Array<number>;
65
76
  password: string;
77
+
78
+ params: Array<FieldShortType<OutgoingValueUnion>>;
66
79
  };
67
80
 
68
81
  export type AdminCreationPayload = AdminUpdatePayload;
@@ -1,3 +1,5 @@
1
+ import { FieldShortType, IncomingValueUnion } from '@tager/admin-dynamic-field';
2
+
1
3
  export type ScopeType = {
2
4
  readonly value: string;
3
5
  readonly label: string;
@@ -25,4 +27,5 @@ export type AdminType = {
25
27
  readonly roles: Array<RoleType>;
26
28
  readonly isSelf: boolean;
27
29
  readonly isSuperAdmin: boolean;
30
+ readonly params: Array<FieldShortType<IncomingValueUnion>>;
28
31
  };
@@ -1,5 +1,6 @@
1
1
  import { Nullable, createId } from '@tager/admin-services';
2
2
  import { OptionType } from '@tager/admin-ui';
3
+ import { FieldUnion, universalFieldUtils } from '@tager/admin-dynamic-field';
3
4
 
4
5
  import { AdminType, RoleType } from '../../typings/model';
5
6
  import {
@@ -39,21 +40,27 @@ export function convertAdminToFormValues(
39
40
  }
40
41
 
41
42
  export function convertFormValuesToAdminUpdatePayload(
42
- values: FormValues
43
+ values: FormValues,
44
+ paramsValues: Array<FieldUnion> = []
43
45
  ): AdminUpdatePayload {
44
46
  return {
45
47
  name: values.name,
46
48
  email: values.email,
47
49
  roles: values.roles.map((role) => role.value),
48
50
  password: values.password,
51
+ params: paramsValues.map((field) => ({
52
+ value: universalFieldUtils.getOutgoingValue(field),
53
+ name: field.config.name,
54
+ })),
49
55
  };
50
56
  }
51
57
 
52
58
  export function convertFormValuesToAdminCreationPayload(
53
- values: FormValues
59
+ values: FormValues,
60
+ paramsValues: Array<FieldUnion> = []
54
61
  ): AdminCreationPayload {
55
62
  return {
56
- ...convertFormValuesToAdminUpdatePayload(values),
63
+ ...convertFormValuesToAdminUpdatePayload(values, paramsValues),
57
64
  };
58
65
  }
59
66
 
@@ -1,49 +1,59 @@
1
1
  <template>
2
- <page :title="pageTitle" :is-content-loading="isContentLoading">
2
+ <Page :title="pageTitle" :is-content-loading="isContentLoading">
3
3
  <form novalidate @submit.prevent>
4
- <template>
5
- <form-field
6
- v-model="values.name"
4
+ <TabList v-model:tab-id="selectedTabId" :tab-list="tabList" />
5
+
6
+ <template v-if="selectedTabId === 'general'">
7
+ <FormField
8
+ v-model:value="values.name"
7
9
  name="name"
8
10
  :error="errors.name"
9
- :label="t('administrators:name')"
11
+ :label="$i18n.t('administrators:name')"
10
12
  />
11
- <form-field
12
- v-model="values.email"
13
+ <FormField
14
+ v-model:value="values.email"
13
15
  name="email"
14
16
  :error="errors.email"
15
- :label="t('administrators:email')"
17
+ :label="$i18n.t('administrators:email')"
16
18
  />
17
- <form-field-multi-select
18
- v-model="values.roles"
19
+ <FormFieldMultiSelect
20
+ v-model:selected-options="values.roles"
19
21
  name="roles"
20
- :label="t('administrators:roles')"
22
+ :label="$i18n.t('administrators:roles')"
21
23
  :options="roleOptionList"
22
24
  :error="errors.roles"
23
25
  />
24
- <form-field
25
- v-model="values.password"
26
+ <FormField
27
+ v-model:value="values.password"
26
28
  name="password"
27
29
  :error="errors.password"
28
30
  :label="
29
31
  isCreation
30
- ? t('administrators:password')
31
- : t('administrators:newPassword')
32
+ ? $i18n.t('administrators:password')
33
+ : $i18n.t('administrators:newPassword')
32
34
  "
33
35
  />
34
36
  </template>
37
+
38
+ <template v-if="selectedTabId === 'params'">
39
+ <DynamicField
40
+ v-for="field of templateValues"
41
+ :key="field.config.name"
42
+ :field="field"
43
+ />
44
+ </template>
35
45
  </form>
36
46
 
37
- <template v-slot:footer>
47
+ <template #footer>
38
48
  <FormFooter
39
49
  :back-href="backButtonUrl"
40
- :on-submit="submitForm"
41
50
  :is-submitting="isSubmitting"
42
51
  :is-creation="isCreation"
43
52
  :can-create-another="isCreation"
53
+ @submit="submitForm"
44
54
  />
45
55
  </template>
46
- </page>
56
+ </Page>
47
57
  </template>
48
58
 
49
59
  <script lang="ts">
@@ -54,19 +64,42 @@ import {
54
64
  ref,
55
65
  SetupContext,
56
66
  watch,
57
- } from '@vue/composition-api';
67
+ } from 'vue';
68
+ import { useRoute, useRouter } from 'vue-router';
58
69
 
70
+ import { Page } from '@tager/admin-layout';
59
71
  import {
60
72
  convertRequestErrorToMap,
73
+ navigateBack,
74
+ notEmpty,
61
75
  Nullable,
62
76
  useResource,
77
+ useToast,
63
78
  } from '@tager/admin-services';
64
- import { OptionType, FormFooter, TagerFormSubmitEvent, useTranslation } from '@tager/admin-ui';
79
+ import {
80
+ OptionType,
81
+ FormFooter,
82
+ TagerFormSubmitEvent,
83
+ FormField,
84
+ FormFieldMultiSelect,
85
+ TabType,
86
+ TabList,
87
+ } from '@tager/admin-ui';
88
+ import { useI18n } from '@tager/admin-services';
89
+ import {
90
+ DynamicField,
91
+ FieldConfigUnion,
92
+ FieldShortType,
93
+ FieldUnion,
94
+ IncomingValueUnion,
95
+ universalFieldUtils,
96
+ } from '@tager/admin-dynamic-field';
65
97
 
66
98
  import { AdminType, RoleType } from '../../typings/model';
67
99
  import {
68
100
  createAdmin,
69
101
  getAdmin,
102
+ getFieldList,
70
103
  getRoleList,
71
104
  updateAdmin,
72
105
  } from '../../services/requests';
@@ -82,39 +115,54 @@ import {
82
115
 
83
116
  export default defineComponent({
84
117
  name: 'AdminForm',
85
- components: { FormFooter },
86
- setup(props, context: SetupContext) {
87
- const { t } = useTranslation(context);
118
+ components: {
119
+ DynamicField,
120
+ TabList,
121
+ Page,
122
+ FormFooter,
123
+ FormField,
124
+ FormFieldMultiSelect,
125
+ },
126
+ setup() {
127
+ const { t } = useI18n();
88
128
 
89
- const adminId = computed<string>(() => context.root.$route.params.adminId);
129
+ const route = useRoute();
130
+ const router = useRouter();
131
+ const toast = useToast();
90
132
 
91
- const isCreation = computed<boolean>(() => adminId.value === 'create');
133
+ const adminId = computed(() => route.params.adminId as string | number);
134
+
135
+ const isCreation = computed(() => adminId.value === 'create');
92
136
 
93
137
  const [fetchAdmin, { data: admin, loading: isAdminLoading }] = useResource<
94
138
  Nullable<AdminType>
95
139
  >({
96
140
  fetchResource: () => getAdmin(adminId.value),
97
141
  initialValue: null,
98
- context,
99
142
  resourceName: 'Admin',
100
143
  });
101
144
 
102
145
  /** Fetch role list */
103
146
 
104
- const [
105
- fetchRoleList,
106
- { data: roleList, loading: isRoleListLoading },
107
- ] = useResource<Array<RoleType>>({
108
- fetchResource: getRoleList,
109
- initialValue: [],
110
- context,
111
- resourceName: 'Role list',
112
- });
147
+ const [fetchRoleList, { data: roleList, loading: isRoleListLoading }] =
148
+ useResource<Array<RoleType>>({
149
+ fetchResource: getRoleList,
150
+ initialValue: [],
151
+ resourceName: 'Role List',
152
+ });
153
+
154
+ const [fetchFieldList, { data: fieldList, loading: isFieldListLoading }] =
155
+ useResource<Array<FieldConfigUnion>>({
156
+ fetchResource: getFieldList,
157
+ initialValue: [],
158
+ resourceName: 'Field List',
159
+ });
113
160
 
114
161
  onMounted(() => {
115
162
  fetchRoleList();
163
+ fetchFieldList();
164
+ updateTemplateValues();
116
165
  if (isCreation.value) return;
117
-
118
166
  fetchAdmin();
119
167
  });
120
168
 
@@ -143,10 +191,14 @@ export default defineComponent({
143
191
  if (admin.value && admin.value.isSelf) return;
144
192
 
145
193
  const creationBody = convertFormValuesToAdminCreationPayload(
146
- values.value
194
+ values.value,
195
+ templateValues.value
147
196
  );
148
197
 
149
- const updateBody = convertFormValuesToAdminUpdatePayload(values.value);
198
+ const updateBody = convertFormValuesToAdminUpdatePayload(
199
+ values.value,
200
+ templateValues.value
201
+ );
150
202
 
151
203
  const requestPromise = isCreation.value
152
204
  ? createAdmin(creationBody)
@@ -157,18 +209,18 @@ export default defineComponent({
157
209
  errors.value = {};
158
210
 
159
211
  if (event.type === 'create') {
160
- context.root.$router.push(getAdminFormUrl({ adminId: data.id }));
212
+ router.push(getAdminFormUrl({ adminId: data.id }));
161
213
  }
162
214
 
163
215
  if (event.type === 'create_exit' || event.type === 'save_exit') {
164
- context.root.$router.push(getAdminListUrl());
216
+ navigateBack(router, getAdminListUrl());
165
217
  }
166
218
 
167
219
  if (event.type === 'create_create-another') {
168
220
  values.value = convertAdminToFormValues(null, roleOptionList.value);
169
221
  }
170
222
 
171
- context.root.$toast({
223
+ toast.show({
172
224
  variant: 'success',
173
225
  title: t('administrators:success'),
174
226
  body: isCreation.value
@@ -179,7 +231,7 @@ export default defineComponent({
179
231
  .catch((error) => {
180
232
  console.error(error);
181
233
  errors.value = convertRequestErrorToMap(error);
182
- context.root.$toast({
234
+ toast.show({
183
235
  variant: 'danger',
184
236
  title: t('administrators:error'),
185
237
  body: isCreation.value
@@ -199,9 +251,47 @@ export default defineComponent({
199
251
  });
200
252
 
201
253
  const isContentLoading = computed<boolean>(
202
- () => isAdminLoading.value || isRoleListLoading.value
254
+ () =>
255
+ isAdminLoading.value ||
256
+ isRoleListLoading.value ||
257
+ isFieldListLoading.value
203
258
  );
204
259
 
260
+ /** Tabs */
261
+
262
+ const shouldDisplayParamsTab = computed<boolean>(
263
+ () => fieldList.value.length > 0
264
+ );
265
+
266
+ const tabList = computed<Array<TabType>>(() => {
267
+ return [
268
+ { id: 'general', label: t('administrators:tabs.general') },
269
+ shouldDisplayParamsTab.value
270
+ ? { id: 'params', label: t('administrators:tabs.params') }
271
+ : null,
272
+ ].filter(notEmpty);
273
+ });
274
+
275
+ const selectedTabId = ref<string>(tabList.value[0].id);
276
+
277
+ const templateValues = ref<Array<FieldUnion>>([]);
278
+
279
+ function updateTemplateValues() {
280
+ const incomingFieldList: Array<FieldShortType<IncomingValueUnion>> =
281
+ admin.value?.params ?? [];
282
+
283
+ templateValues.value = fieldList.value.map((fieldConfig, index) =>
284
+ universalFieldUtils.createFormField(
285
+ fieldConfig,
286
+ incomingFieldList[index]?.value
287
+ )
288
+ );
289
+ }
290
+
291
+ watch([admin, fieldList], () => {
292
+ updateTemplateValues();
293
+ });
294
+
205
295
  return {
206
296
  t,
207
297
  backButtonUrl: getAdminListUrl(),
@@ -214,6 +304,9 @@ export default defineComponent({
214
304
  pageTitle,
215
305
  isCreation,
216
306
  roleOptionList,
307
+ tabList,
308
+ selectedTabId,
309
+ templateValues,
217
310
  };
218
311
  },
219
312
  });
@@ -1,75 +1,81 @@
1
1
  <template>
2
- <page
3
- :title="t('administrators:administrators')"
4
- :header-buttons="[
2
+ <Page
3
+ :title="$i18n.t('administrators:administrators')"
4
+ :header-buttons="[
5
5
  {
6
- text: t('administrators:createAdministrator'),
6
+ text: $i18n.t('administrators:createAdministrator'),
7
7
  href: getAdminFormUrl({ adminId: 'create' }),
8
8
  },
9
9
  ]"
10
10
  >
11
- <template v-slot:content>
12
- <base-table
11
+ <DataTable
13
12
  :column-defs="columnDefs"
14
13
  :row-data="rowData"
15
14
  :loading="isRowDataLoading"
16
15
  :error-message="errorMessage"
17
- >
18
- <template v-slot:cell(roles)="{ row }">
19
- <ul>
20
- <li v-for="role of row.roles" :key="role.id">
21
- {{ role.name }}
22
- </li>
23
- </ul>
24
- </template>
25
- <template v-slot:cell(actions)="{ row }">
26
- <base-button
16
+ >
17
+ <template v-slot:cell(roles)="{ row }">
18
+ <ul>
19
+ <li v-for="role of row.roles" :key="role.id">
20
+ {{ role.name }}
21
+ </li>
22
+ </ul>
23
+ </template>
24
+ <template #cell(actions)="{ row }">
25
+ <BaseButton
27
26
  v-if="!row.isSelf"
28
27
  variant="icon"
29
- :title="t('administrators:edit')"
28
+ :title="$i18n.t('administrators:edit')"
30
29
  :disabled="isBusy(row.id)"
31
30
  :href="getAdminFormUrl({ adminId: row.id })"
32
- >
33
- <svg-icon name="edit"></svg-icon>
34
- </base-button>
35
- <base-button
31
+ >
32
+ <EditIcon/>
33
+ </BaseButton>
34
+ <BaseButton
36
35
  v-if="!row.isSuperAdmin || !row.isSelf"
37
36
  variant="icon"
38
- :title="t('administrators:delete')"
37
+ :title="$i18n.t('administrators:delete')"
39
38
  :disabled="isBusy(row.id)"
40
39
  @click="handleAdminDelete(row.id)"
41
- >
42
- <svg-icon name="delete"></svg-icon>
43
- </base-button>
44
- </template>
45
- </base-table>
46
- </template>
47
- </page>
40
+ >
41
+ <DeleteIcon/>
42
+ </BaseButton>
43
+ </template>
44
+ </DataTable>
45
+ </Page>
48
46
  </template>
49
47
 
50
48
  <script lang="ts">
51
- import { defineComponent, onMounted, SetupContext } from '@vue/composition-api';
49
+ import {defineComponent, onMounted} from 'vue';
52
50
 
53
- import { useResource, useResourceDelete } from '@tager/admin-services';
54
- import { ColumnDefinition, useTranslation } from '@tager/admin-ui';
51
+ import {useResourceDelete} from '@tager/admin-services';
52
+ import {ColumnDefinition, DataTable, BaseButton, DeleteIcon, EditIcon, useDataTable} from '@tager/admin-ui';
53
+ import {useI18n} from "@tager/admin-services";
55
54
 
56
- import { AdminType } from '../../typings/model';
57
- import { deleteAdmin, getAdminList } from '../../services/requests';
58
- import { getAdminFormUrl } from '../../utils/paths';
55
+ import {AdminType} from '../../typings/model';
56
+ import {deleteAdmin, getAdminList} from '../../services/requests';
57
+ import {getAdminFormUrl} from '../../utils/paths';
58
+
59
+ import {Page} from "@tager/admin-layout";
59
60
 
60
61
  export default defineComponent({
61
62
  name: 'AdminList',
62
- setup(props, context: SetupContext) {
63
- const { t } = useTranslation(context);
63
+ components: {
64
+ Page, DataTable, BaseButton, DeleteIcon, EditIcon
65
+ },
66
+ setup() {
67
+ const {t} = useI18n();
64
68
 
65
- const [
66
- fetchAdminList,
67
- { data: adminList, loading: isAdminLoading, error },
68
- ] = useResource<Array<AdminType>>({
69
- fetchResource: getAdminList,
69
+ const {
70
+ fetchEntityList: fetchAdminList,
71
+ isLoading: isAdminListLoading,
72
+ rowData: adminList,
73
+ errorMessage: error,
74
+ } = useDataTable<AdminType>({
75
+ fetchEntityList: () => getAdminList(),
70
76
  initialValue: [],
71
- context,
72
- resourceName: 'Admin list',
77
+ resourceName: "Admin list",
78
+ pageSize: 100,
73
79
  });
74
80
 
75
81
  onMounted(() => {
@@ -83,11 +89,10 @@ export default defineComponent({
83
89
  deleteResource: deleteAdmin,
84
90
  resourceName: 'Admin',
85
91
  onSuccess: fetchAdminList,
86
- context,
87
92
  });
88
93
 
89
94
  function isBusy(adminId: number): boolean {
90
- return isDeleting(adminId) || isAdminLoading.value;
95
+ return isDeleting(adminId) || isAdminListLoading.value;
91
96
  }
92
97
 
93
98
  const columnDefs: Array<ColumnDefinition<AdminType>> = [
@@ -110,8 +115,8 @@ export default defineComponent({
110
115
  id: 4,
111
116
  name: t('administrators:actions'),
112
117
  field: 'actions',
113
- style: { width: '180px', textAlign: 'center', whiteSpace: 'nowrap' },
114
- headStyle: { width: '180px', textAlign: 'center' },
118
+ style: {width: '180px', textAlign: 'center', whiteSpace: 'nowrap'},
119
+ headStyle: {width: '180px', textAlign: 'center'},
115
120
  },
116
121
  ];
117
122
 
@@ -119,7 +124,7 @@ export default defineComponent({
119
124
  t,
120
125
  columnDefs,
121
126
  rowData: adminList,
122
- isRowDataLoading: isAdminLoading,
127
+ isRowDataLoading: isAdminListLoading,
123
128
  errorMessage: error,
124
129
  isBusy,
125
130
  handleAdminDelete,