@fishawack/lab-velocity 2.0.0-beta.3 → 2.0.0-beta.30

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 (106) hide show
  1. package/README.md +441 -37
  2. package/_Build/vue/components/basic/Button.vue +1 -1
  3. package/_Build/vue/components/form/Select.vue +2 -2
  4. package/_Build/vue/components/form/Spinner.vue +5 -0
  5. package/_Build/vue/components/layout/Alert.vue +5 -5
  6. package/_Build/vue/{modules/AuthModule/components/VBreadcrumbs.vue → components/layout/Breadcrumbs.vue} +4 -4
  7. package/_Build/vue/{modules/AuthModule/components → components/layout}/Chips.vue +2 -2
  8. package/_Build/vue/components/layout/Footer.vue +11 -10
  9. package/_Build/vue/{modules/AuthModule/components/VFormFooter.vue → components/layout/FormFooter.vue} +13 -7
  10. package/_Build/vue/{modules/AuthModule/components → components/layout}/FormRole.vue +10 -8
  11. package/_Build/vue/components/layout/Layout.vue +76 -0
  12. package/_Build/vue/components/layout/Navigation.vue +77 -0
  13. package/_Build/vue/{modules/AuthModule/components/VPageHeader.vue → components/layout/PageHeader.vue} +7 -2
  14. package/_Build/vue/components/layout/SideBar.vue +26 -0
  15. package/_Build/vue/{modules/AuthModule/components/VTable.vue → components/layout/Table.vue} +32 -16
  16. package/_Build/vue/{modules/AuthModule/components/VTableSorter.vue → components/layout/TableSorter.vue} +68 -43
  17. package/_Build/vue/components/layout/pageTitle.vue +1 -1
  18. package/_Build/vue/components/navigation/MenuItem.vue +7 -2
  19. package/_Build/vue/components/navigation/MenuItemGroup.vue +7 -2
  20. package/_Build/vue/modules/AuthModule/js/axios.js +19 -0
  21. package/_Build/vue/modules/AuthModule/js/router.js +28 -88
  22. package/_Build/vue/modules/AuthModule/js/store.js +15 -6
  23. package/_Build/vue/modules/AuthModule/{adminRoutes/PCompanies/Children/partials → routes/PCompanies}/form.vue +50 -18
  24. package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +259 -0
  25. package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +308 -0
  26. package/_Build/vue/modules/AuthModule/{adminRoutes/PUsers/Children/partials → routes/PUsers}/form.vue +30 -18
  27. package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +215 -0
  28. package/_Build/vue/modules/AuthModule/routes/account-exists.vue +2 -2
  29. package/_Build/vue/modules/AuthModule/routes/change-password.vue +23 -24
  30. package/_Build/vue/modules/AuthModule/routes/container.vue +2 -11
  31. package/_Build/vue/modules/AuthModule/routes/expired-reset.vue +4 -4
  32. package/_Build/vue/modules/AuthModule/routes/expired-verification.vue +9 -8
  33. package/_Build/vue/modules/AuthModule/routes/force-reset.vue +24 -28
  34. package/_Build/vue/modules/AuthModule/routes/forgot.vue +4 -4
  35. package/_Build/vue/modules/AuthModule/routes/login.vue +7 -11
  36. package/_Build/vue/modules/AuthModule/routes/logincallback.vue +2 -4
  37. package/_Build/vue/modules/AuthModule/routes/loginsso.vue +7 -9
  38. package/_Build/vue/modules/AuthModule/routes/logout.vue +1 -3
  39. package/_Build/vue/modules/AuthModule/routes/logoutheadless.vue +1 -3
  40. package/_Build/vue/modules/AuthModule/routes/register.vue +19 -21
  41. package/_Build/vue/modules/AuthModule/routes/reset.vue +14 -13
  42. package/_Build/vue/modules/AuthModule/routes/success-forgot.vue +8 -7
  43. package/_Build/vue/modules/AuthModule/routes/success-reset.vue +2 -2
  44. package/_Build/vue/modules/AuthModule/routes/success-verify.vue +1 -3
  45. package/_Build/vue/modules/AuthModule/routes/verify.vue +11 -14
  46. package/_Build/vue/modules/resource/Children/create.vue +70 -0
  47. package/_Build/vue/modules/resource/Children/edit.vue +92 -0
  48. package/_Build/vue/modules/resource/Children/index.vue +42 -0
  49. package/_Build/vue/modules/resource/Children/partials/form.vue +57 -0
  50. package/_Build/vue/modules/resource/Children/show.vue +133 -0
  51. package/_Build/vue/modules/resource/index.js +486 -0
  52. package/_Build/vue/modules/resource/parent.vue +63 -0
  53. package/_base.scss +0 -1
  54. package/_defaults.scss +2 -13
  55. package/_variables.scss +9 -4
  56. package/components/_alert.scss +5 -0
  57. package/components/_auth.scss +163 -0
  58. package/components/_basic.scss +55 -0
  59. package/components/_breadcrumbs.scss +39 -0
  60. package/components/_button.scss +304 -0
  61. package/components/_cascader.scss +12 -0
  62. package/components/_checkbox.scss +41 -0
  63. package/components/_chip.scss +24 -0
  64. package/components/_collapse.scss +24 -0
  65. package/components/_datepicker.scss +52 -0
  66. package/components/_descriptions.scss +2 -0
  67. package/components/_footer.scss +47 -0
  68. package/components/_form.scss +24 -0
  69. package/components/_header.scss +30 -0
  70. package/components/_icon.scss +25 -0
  71. package/components/_inputNumber.scss +22 -0
  72. package/components/_layout.scss +56 -0
  73. package/components/_link.scss +44 -0
  74. package/components/_loader.scss +43 -0
  75. package/components/_menu.scss +112 -0
  76. package/components/_modal.scss +24 -0
  77. package/components/_pageTitle.scss +8 -0
  78. package/components/_permissionLegend.scss +18 -0
  79. package/components/_select.scss +29 -0
  80. package/components/_sidebar.scss +41 -0
  81. package/components/_switch.scss +14 -0
  82. package/components/_table.scss +20 -0
  83. package/components/_tooltip.scss +4 -0
  84. package/components/_typography.scss +162 -0
  85. package/components/_upload.scss +15 -0
  86. package/components/_wysiwyg.scss +7 -0
  87. package/components/_wysiwyg2.scss +142 -0
  88. package/index.js +9 -1
  89. package/package.json +4 -2
  90. package/vendor.scss +0 -1
  91. package/_Build/vue/components/layout/sideBar.vue +0 -25
  92. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/Upload/upload.vue +0 -251
  93. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/create.vue +0 -62
  94. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/edit.vue +0 -98
  95. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/index.vue +0 -90
  96. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/show.vue +0 -262
  97. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/parent.vue +0 -36
  98. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/create.vue +0 -112
  99. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/edit.vue +0 -103
  100. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/index.vue +0 -112
  101. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +0 -120
  102. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +0 -36
  103. /package/_Build/vue/{modules/AuthModule/components → components/layout}/AuthModal.vue +0 -0
  104. /package/_Build/vue/{modules/AuthModule/components → components/layout}/Chip.vue +0 -0
  105. /package/_Build/vue/{modules/AuthModule/components/VPasswordValidation.vue → components/layout/PasswordValidation.vue} +0 -0
  106. /package/_Build/vue/{modules/AuthModule/components/VRoleLegend.vue → components/layout/RoleLegend.vue} +0 -0
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <el-sub-menu :index="index" v-bind="$props">
2
+ <el-sub-menu v-bind="$props" :index="`${index}`">
3
3
  <template #title>
4
4
  <slot name="title" />
5
5
  </template>
@@ -15,6 +15,11 @@ export default {
15
15
  components: {
16
16
  ElSubMenu,
17
17
  },
18
- props: ["index"],
18
+ props: {
19
+ index: {
20
+ type: [String, Number],
21
+ required: true,
22
+ },
23
+ },
19
24
  };
20
25
  </script>
@@ -1,4 +1,21 @@
1
1
  import axios from "axios";
2
+ import debounce from "lodash/debounce";
3
+
4
+ import { ElNotification } from "element-plus";
5
+
6
+ const displayErrorNotification = debounce(async function errors(e) {
7
+ if (e.response && !e.response.data.errors) {
8
+ ElNotification.error({
9
+ title: "Error",
10
+ message:
11
+ e.response.data.message ||
12
+ `${e.response.status}: ${
13
+ e.response.statusText || "Please try again later!"
14
+ }`,
15
+ duration: 10000,
16
+ });
17
+ }
18
+ }, 250);
2
19
 
3
20
  function setAxiosDefaults(baseUrl, router) {
4
21
  axios.defaults.baseURL = baseUrl;
@@ -25,6 +42,8 @@ function setAxiosDefaults(baseUrl, router) {
25
42
  }
26
43
  }
27
44
 
45
+ displayErrorNotification(error);
46
+
28
47
  return Promise.reject(error);
29
48
  });
30
49
 
@@ -1,10 +1,24 @@
1
1
  "use strict";
2
2
 
3
+ import { merge } from "lodash";
4
+
3
5
  import { h } from "vue";
4
6
  import { RouterView } from "vue-router";
5
7
 
8
+ import { routes as resourceRoutes } from "../../resource/index.js";
9
+
10
+ import userResource from "../routes/PUsers/resource.js";
11
+ import companyResource from "../routes/PCompanies/resource.js";
12
+ import teamResource from "../routes/PTeams/resource.js";
13
+
6
14
  // Admin routes export - minimal auth flow (headless login only)
7
- export function adminRoutes(node) {
15
+ export function adminRoutes(node, overrides = {}) {
16
+ const {
17
+ userResource: overrideUserResource = {},
18
+ companyResource: overrideCompanyResource = {},
19
+ teamResource: overrideTeamResource = {},
20
+ } = overrides;
21
+
8
22
  return [
9
23
  {
10
24
  path: "/auth",
@@ -39,94 +53,20 @@ export function adminRoutes(node) {
39
53
  },
40
54
  ],
41
55
  },
42
- {
43
- path: "/users",
44
- component: node
45
- ? ""
46
- : require("../adminRoutes/PUsers/parent.vue").default,
47
- children: [
48
- {
49
- path: "",
50
- component: node
51
- ? ""
52
- : require("../adminRoutes/PUsers/Children/index.vue")
53
- .default,
54
- name: "users.index",
55
- },
56
- {
57
- path: "create",
58
- component: node
59
- ? ""
60
- : require("../adminRoutes/PUsers/Children/create.vue")
61
- .default,
62
- name: "users.create",
63
- },
64
- {
65
- path: ":id",
66
- component: node
67
- ? ""
68
- : require("../adminRoutes/PUsers/Children/show.vue")
69
- .default,
70
- name: "users.show",
71
- },
72
- {
73
- path: ":id/edit",
74
- component: node
75
- ? ""
76
- : require("../adminRoutes/PUsers/Children/edit.vue")
77
- .default,
78
- name: "users.edit",
79
- },
56
+ ...resourceRoutes(
57
+ node,
58
+ ...merge(userResource, [undefined, overrideUserResource]),
59
+ ),
60
+ ...resourceRoutes(
61
+ node,
62
+ ...merge(companyResource, [undefined, overrideCompanyResource]),
63
+ [
64
+ ...resourceRoutes(
65
+ node,
66
+ ...merge(teamResource, [undefined, overrideTeamResource]),
67
+ ),
80
68
  ],
81
- },
82
- {
83
- path: "/companies",
84
- component: node
85
- ? ""
86
- : require("../adminRoutes/PCompanies/parent.vue").default,
87
- children: [
88
- {
89
- path: "",
90
- component: node
91
- ? ""
92
- : require("../adminRoutes/PCompanies/Children/index.vue")
93
- .default,
94
- name: "companies.index",
95
- },
96
- {
97
- path: "create",
98
- component: node
99
- ? ""
100
- : require("../adminRoutes/PCompanies/Children/create.vue")
101
- .default,
102
- name: "companies.create",
103
- },
104
- {
105
- path: ":id",
106
- component: node
107
- ? ""
108
- : require("../adminRoutes/PCompanies/Children/show.vue")
109
- .default,
110
- name: "companies.show",
111
- },
112
- {
113
- path: ":id/edit",
114
- component: node
115
- ? ""
116
- : require("../adminRoutes/PCompanies/Children/edit.vue")
117
- .default,
118
- name: "companies.edit",
119
- },
120
- {
121
- path: ":id/upload",
122
- component: node
123
- ? ""
124
- : require("../adminRoutes/PCompanies/Children/Upload/upload.vue")
125
- .default,
126
- name: "companies.upload",
127
- },
128
- ],
129
- },
69
+ ),
130
70
  ];
131
71
  }
132
72
 
@@ -7,6 +7,9 @@ const store = {
7
7
  intended: null,
8
8
  user: null,
9
9
  redirect: process.env.HYDRATE_REDIRECT ?? "index",
10
+ logo: process.env.HYDRATE_LOGO ?? "example-logo",
11
+ logoReverse:
12
+ process.env.HYDRATE_LOGO_REVERSE ?? process.env.HYDRATE_LOGO,
10
13
  contact:
11
14
  process.env.HYDRATE_CONTACT ?? "mailto:det@avalerehealth.com",
12
15
  };
@@ -15,12 +18,18 @@ const store = {
15
18
  getters: {
16
19
  authenticated: (state) => !!state.user,
17
20
  can: (state) => (permission) => {
18
- return state.user?.permissions
19
- .map(({ name }) => name)
20
- .includes(permission);
21
+ const arr = Array.isArray(permission) ? permission : [permission];
22
+ const userPermissions = state.user?.permissions.map(
23
+ ({ name }) => name,
24
+ );
25
+
26
+ return arr.every((name) => userPermissions?.includes(name));
21
27
  },
22
28
  hasRole: (state) => (role) => {
23
- return state.user?.roles.map(({ name }) => name).includes(role);
29
+ const arr = Array.isArray(role) ? role : [role];
30
+ const userRoles = state.user?.roles.map(({ name }) => name);
31
+
32
+ return arr.every((name) => userRoles?.includes(name));
24
33
  },
25
34
  },
26
35
 
@@ -38,7 +47,7 @@ const store = {
38
47
  },
39
48
 
40
49
  actions: {
41
- getUser({ commit }, { errors, query = "", params }) {
50
+ getUser({ commit }, { errors = console.log, query = "", params } = {}) {
42
51
  return axios
43
52
  .get(`/api/users/self${query}`, {
44
53
  params,
@@ -51,7 +60,7 @@ const store = {
51
60
  .catch(errors);
52
61
  },
53
62
 
54
- logout({ commit }, { errors }) {
63
+ logout({ commit }) {
55
64
  commit("setUser", null);
56
65
 
57
66
  return axios.post("/logout");
@@ -1,7 +1,7 @@
1
1
  <!-- eslint-disable vue/no-mutating-props -->
2
2
  <template>
3
3
  <form class="" @submit.prevent="submit">
4
- <el-basic
4
+ <VelBasic
5
5
  v-model="form.name"
6
6
  name="name"
7
7
  :error="form.errors"
@@ -12,9 +12,9 @@
12
12
  <template #label>
13
13
  Company name <sup class="color-status-red-100">*</sup>
14
14
  </template>
15
- </el-basic>
15
+ </VelBasic>
16
16
 
17
- <el-select
17
+ <VelSelect
18
18
  v-if="method === 'patch'"
19
19
  v-model="form.primary_contact"
20
20
  name="primary_contact"
@@ -45,12 +45,12 @@
45
45
  >
46
46
  <template #prepend>@</template>
47
47
  <template #append>
48
- <el-button
48
+ <VelButton
49
49
  type="danger"
50
50
  @click="form.domains.splice(index, 1)"
51
51
  >
52
52
  <GSvg class="vel-icon" name="trash" />
53
- </el-button>
53
+ </VelButton>
54
54
  </template>
55
55
  </el-input>
56
56
 
@@ -63,17 +63,37 @@
63
63
  </ul>
64
64
 
65
65
  <div>
66
- <el-button @click="form.domains.push('')">
66
+ <VelButton @click="form.domains.push('')">
67
67
  Add Domain
68
68
 
69
- <GIcon name="icon-plus" embed asis class="fill-0 ml" />
70
- </el-button>
69
+ <GIcon
70
+ name="icon-plus"
71
+ embed
72
+ asis
73
+ class="fill-0 icon--0.5 ml"
74
+ />
75
+ </VelButton>
71
76
  </div>
72
77
 
78
+ <VelBasic
79
+ v-model="form.seats"
80
+ name="seats"
81
+ :error="form.errors"
82
+ type="number"
83
+ placeholder="Company seats"
84
+ label="Company seats"
85
+ min="0"
86
+ class="mb-0 mt-2"
87
+ >
88
+ <template #label>
89
+ Company seats <sup class="color-status-red-100">*</sup>
90
+ </template>
91
+ </VelBasic>
92
+
73
93
  <hr class="my-5 hr-muted" />
74
94
 
75
95
  <template v-if="$store.getters.can('edit roles')">
76
- <FormRole :form="form" />
96
+ <VelFormRole :form="form" />
77
97
 
78
98
  <hr class="my-5 hr-muted" />
79
99
  </template>
@@ -81,7 +101,7 @@
81
101
  <template v-if="$store.getters.can('edit sso')">
82
102
  <h3 class="h3 mb-2">SSO Settings</h3>
83
103
 
84
- <el-select
104
+ <VelSelect
85
105
  v-model="form.sso_type"
86
106
  name="sso_type"
87
107
  :error="form.errors"
@@ -99,7 +119,7 @@
99
119
  },
100
120
  ]"
101
121
  />
102
- <el-basic
122
+ <VelBasic
103
123
  v-model="form.sso_client_id"
104
124
  name="sso_client_id"
105
125
  :error="form.errors"
@@ -107,7 +127,7 @@
107
127
  placeholder="Key"
108
128
  label="Key"
109
129
  />
110
- <el-basic
130
+ <VelBasic
111
131
  v-model="form.sso_tenant"
112
132
  name="sso_tenant"
113
133
  :error="form.errors"
@@ -115,7 +135,7 @@
115
135
  placeholder="Tenant"
116
136
  label="Tenant"
117
137
  />
118
- <el-basic
138
+ <VelBasic
119
139
  v-model="form.sso_client_secret"
120
140
  name="sso_client_secret"
121
141
  :error="form.errors"
@@ -127,18 +147,28 @@
127
147
  <hr class="my-3 hr-muted" />
128
148
  </template>
129
149
 
130
- <VFormFooter :form="form" />
150
+ <VelFormFooter :form="form" />
131
151
  </form>
132
152
  </template>
133
153
 
134
154
  <!-- eslint-disable vue/no-mutating-props -->
135
155
  <script>
136
156
  import axios from "axios";
157
+ import VelButton from "../../../../components/basic/Button.vue";
158
+ import VelSelect from "../../../../components/form/Select.vue";
159
+ import VelBasic from "../../../../components/form/basic.vue";
160
+ import VelFormRole from "../../../../components/layout/FormRole.vue";
161
+ import VelFormFooter from "../../../../components/layout/FormFooter.vue";
162
+ import { ElInput } from "element-plus";
137
163
 
138
164
  export default {
139
165
  components: {
140
- VFormFooter: require("../../../../components/VFormFooter.vue").default,
141
- FormRole: require("../../../../components/FormRole.vue").default,
166
+ VelFormFooter,
167
+ VelFormRole,
168
+ VelButton,
169
+ VelSelect,
170
+ VelBasic,
171
+ ElInput,
142
172
  },
143
173
 
144
174
  props: {
@@ -151,8 +181,8 @@ export default {
151
181
  type: Function,
152
182
  },
153
183
  method: {
154
- required: true,
155
184
  type: String,
185
+ default: "post",
156
186
  },
157
187
  },
158
188
 
@@ -164,7 +194,9 @@ export default {
164
194
 
165
195
  mounted() {
166
196
  axios
167
- .getAll(`/api/users?filter[company_id]=${this.$route.params.id}`)
197
+ .getAll(
198
+ `/api/users?filter[company_id]=${this.$route.params.companiesId}`,
199
+ )
168
200
  .then((res) => {
169
201
  this.users = res.data.data;
170
202
  });
@@ -0,0 +1,259 @@
1
+ import VelFormRole from "../../../../components/layout/FormRole.vue";
2
+ import VelButton from "../../../../components/basic/Button.vue";
3
+ import Chip from "../../../../components/layout/Chip.vue";
4
+ import Chips from "../../../../components/layout/Chips.vue";
5
+ import VelTableSorter from "../../../../components/layout/TableSorter.vue";
6
+ import VelRoleLegend from "../../../../components/layout/RoleLegend.vue";
7
+ import component from "./form.vue";
8
+ import userResource from "../PUsers/resource.js";
9
+ import teamResource from "../PTeams/resource.js";
10
+ import { defaultResource, meta } from "../../../resource/index.js";
11
+
12
+ import { ElNotification } from "element-plus";
13
+ import { h, resolveComponent } from "vue";
14
+ import axios from "axios";
15
+
16
+ export default [
17
+ "companies",
18
+ {
19
+ api: {
20
+ params: {
21
+ show: () => ({ include: "primary_contact" }),
22
+ },
23
+ },
24
+ permissions: {
25
+ create: ({ $store }) => $store.getters.can("write companies"),
26
+ edit: ({ $store }) => $store.getters.can("write companies"),
27
+ delete: ({ $store }) => $store.getters.can("delete companies"),
28
+ },
29
+ singular: "company",
30
+ icon: "icon-cases",
31
+ form: {
32
+ component,
33
+ fields: ({ model }) => ({
34
+ name: model?.name || null,
35
+ primary_contact: model?.primary_contact?.id || null,
36
+ domains: model?.domains || [],
37
+ seats: model?.seats != null ? model.seats : null,
38
+ roles: model?.roles.map((val) => val.id) || [],
39
+ sso_client_id: model?.sso_client_id || undefined,
40
+ sso_tenant: model?.sso_tenant || undefined,
41
+ sso_client_secret: model?.sso_client_secret || undefined,
42
+ sso_type: model?.sso_type || undefined,
43
+ }),
44
+ },
45
+ table: {
46
+ structure: [
47
+ {
48
+ key: "name",
49
+ sortable: true,
50
+ },
51
+ {
52
+ key: "user_count",
53
+ label: "Total users",
54
+ width: "150",
55
+ },
56
+ {
57
+ key: "role",
58
+ render: ({ model }) =>
59
+ h(
60
+ model.roles.length === 1 ? Chip : Chips,
61
+ model.roles.length === 1
62
+ ? {
63
+ name: model.roles[0].name,
64
+ label: model.roles[0].label,
65
+ }
66
+ : { array: model.roles },
67
+ ),
68
+ },
69
+ ],
70
+ },
71
+ description: {
72
+ structure: [
73
+ {
74
+ key: "domains",
75
+ render: ({ model }) => h("span", model.domains.join(", ")),
76
+ },
77
+ {
78
+ key: "sso_enabled",
79
+ label: "SSO Enabled",
80
+ },
81
+ {
82
+ key: "primary_contact",
83
+ label: "Primary Contact",
84
+ render: ({ model }) =>
85
+ h("span", model.primary_contact?.name),
86
+ },
87
+ {
88
+ key: "primary_contact_email",
89
+ label: "Primary Contact Email",
90
+ render: ({ model }) =>
91
+ h("span", model.primary_contact?.email),
92
+ },
93
+ {
94
+ key: "primary_contact_contacted",
95
+ label: "Primary Contact Contacted",
96
+ render: ({ model }) =>
97
+ h("span", !!model.primary_contact_contacted),
98
+ },
99
+ {
100
+ label: "Total Users",
101
+ key: "user_count",
102
+ },
103
+ {
104
+ label: "Available Seats",
105
+ key: "seats",
106
+ },
107
+ ],
108
+ },
109
+ index: {
110
+ layout: [
111
+ ...defaultResource.index.layout,
112
+ () =>
113
+ h(VelRoleLegend, {
114
+ class: "mt-5",
115
+ }),
116
+ ],
117
+ },
118
+ show: {
119
+ actions: [
120
+ ({ model }) =>
121
+ model.primary_contact &&
122
+ h(
123
+ VelButton,
124
+ {
125
+ type: "primary",
126
+ async onClick() {
127
+ try {
128
+ const res = await axios.post(
129
+ `/api/companies/${model.id}/welcome`,
130
+ );
131
+ ElNotification({
132
+ title: "Success",
133
+ message: res.data.message,
134
+ type: "success",
135
+ });
136
+
137
+ model.primary_contact_contacted = true;
138
+ } catch (e) {
139
+ ElNotification({
140
+ title: "Warning",
141
+ message:
142
+ e.response?.data?.message ||
143
+ e.message,
144
+ type: "warning",
145
+ });
146
+ }
147
+ },
148
+ },
149
+ "Send welcome email",
150
+ ),
151
+ ...defaultResource.show.actions,
152
+ ],
153
+ layout: [
154
+ ...defaultResource.show.layout,
155
+ ({ model }) => ({
156
+ label: "Access control",
157
+ component: h(VelFormRole, {
158
+ overrides: model.overrides_roles_and_permissions,
159
+ form: { roles: model.roles.map((d) => d.id) },
160
+ readonly: true,
161
+ }),
162
+ }),
163
+ ({ model, $store, $router, $route, ...rest }) => {
164
+ const resource = meta(...teamResource);
165
+
166
+ const props = {
167
+ model,
168
+ $store,
169
+ $router,
170
+ $route,
171
+ ...rest,
172
+ resource,
173
+ };
174
+
175
+ return {
176
+ label: "Teams",
177
+ component: h("div", [
178
+ h("div", { class: "flex justify-end items-end" }, [
179
+ resource.permissions.create(props) &&
180
+ h(
181
+ VelButton,
182
+ {
183
+ tag: "a",
184
+ type: "primary",
185
+ size: "large",
186
+ onClick: () => {
187
+ $router.push({
188
+ name: `${resource.slug}.create`,
189
+ });
190
+ },
191
+ },
192
+ () => [
193
+ h(resolveComponent("GIcon"), {
194
+ class: "fill-0 mr-0.5 icon--0.5",
195
+ name: "icon-plus",
196
+ embed: true,
197
+ artboard: true,
198
+ }),
199
+ `Create ${resource.singular}`,
200
+ ],
201
+ ),
202
+ ]),
203
+ h(VelTableSorter, resource.index.structure(props)),
204
+ ]),
205
+ };
206
+ },
207
+ ({ model, $store, $router, $route, ...rest }) => {
208
+ const resource = meta(...userResource);
209
+
210
+ resource.api.params.index = ({ $route }) => ({
211
+ include: "company",
212
+ "filter[company_id]": $route.params.companiesId,
213
+ });
214
+
215
+ const props = {
216
+ model,
217
+ $store,
218
+ $router,
219
+ $route,
220
+ ...rest,
221
+ resource,
222
+ };
223
+
224
+ return {
225
+ label: "Users",
226
+ component: h("div", [
227
+ h("div", { class: "flex justify-end items-end" }, [
228
+ resource.permissions.create(props) &&
229
+ h(
230
+ VelButton,
231
+ {
232
+ tag: "a",
233
+ type: "primary",
234
+ size: "large",
235
+ onClick: () => {
236
+ $router.push({
237
+ name: `${resource.slug}.create`,
238
+ });
239
+ },
240
+ },
241
+ () => [
242
+ h(resolveComponent("GIcon"), {
243
+ class: "fill-0 mr-0.5 icon--0.5",
244
+ name: "icon-plus",
245
+ embed: true,
246
+ artboard: true,
247
+ }),
248
+ `Create ${resource.singular}`,
249
+ ],
250
+ ),
251
+ ]),
252
+ h(VelTableSorter, resource.index.structure(props)),
253
+ ]),
254
+ };
255
+ },
256
+ ],
257
+ },
258
+ },
259
+ ];