@fishawack/lab-velocity 2.0.0-beta.5 → 2.0.0-beta.50
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.
- package/README.md +467 -36
- package/_Build/js/libs/build-id.js +14 -0
- package/_Build/js/libs/filters.js +36 -0
- package/_Build/js/libs/globals.js +7 -0
- package/_Build/js/libs/router.js +22 -0
- package/_Build/js/libs/routes.js +29 -0
- package/_Build/js/libs/store.js +21 -0
- package/_Build/js/libs/utility.js +161 -0
- package/_Build/vue/components/basic/Button.vue +1 -1
- package/_Build/vue/components/form/Avatar.vue +90 -0
- package/_Build/vue/components/form/Checkbox.vue +10 -0
- package/_Build/vue/components/form/InputNumber.vue +1 -1
- package/_Build/vue/components/form/Select.vue +223 -33
- package/_Build/vue/components/form/Spinner.vue +5 -0
- package/_Build/vue/components/layout/Alert.vue +5 -5
- package/_Build/vue/components/layout/Audit.vue +143 -0
- package/_Build/vue/{modules/AuthModule/components/VBreadcrumbs.vue → components/layout/Breadcrumbs.vue} +4 -4
- package/_Build/vue/{modules/AuthModule/components → components/layout}/Chips.vue +2 -2
- package/_Build/vue/components/layout/Footer.vue +11 -10
- package/_Build/vue/{modules/AuthModule/components/VFormFooter.vue → components/layout/FormFooter.vue} +13 -7
- package/_Build/vue/{modules/AuthModule/components → components/layout}/FormRole.vue +10 -8
- package/_Build/vue/components/layout/Layout.vue +94 -0
- package/_Build/vue/components/layout/Navigation.vue +77 -0
- package/_Build/vue/{modules/AuthModule/components/VPageHeader.vue → components/layout/PageHeader.vue} +14 -8
- package/_Build/vue/components/layout/SideBar.vue +26 -0
- package/_Build/vue/{modules/AuthModule/components/VTable.vue → components/layout/Table.vue} +37 -16
- package/_Build/vue/{modules/AuthModule/components/VTableSorter.vue → components/layout/TableSorter.vue} +108 -52
- package/_Build/vue/components/layout/TokenDisplay.vue +52 -0
- package/_Build/vue/components/layout/pageTitle.vue +1 -1
- package/_Build/vue/components/navigation/MenuItem.vue +7 -2
- package/_Build/vue/components/navigation/MenuItemGroup.vue +7 -2
- package/_Build/vue/modules/AuthModule/js/axios.js +21 -1
- package/_Build/vue/modules/AuthModule/js/guest-request.js +32 -0
- package/_Build/vue/modules/AuthModule/js/impersonation-banner.js +102 -0
- package/_Build/vue/modules/AuthModule/js/router.js +91 -114
- package/_Build/vue/modules/AuthModule/js/store.js +23 -6
- package/_Build/vue/modules/AuthModule/routes/PCompanies/columns.js +268 -0
- package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +213 -0
- package/_Build/vue/modules/AuthModule/routes/PIntegrations/columns.js +58 -0
- package/_Build/vue/modules/AuthModule/routes/PIntegrations/resource.js +79 -0
- package/_Build/vue/modules/AuthModule/routes/PTeams/columns.js +78 -0
- package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +251 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/SetPasswordAction.vue +51 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/SetPasswordDialog.vue +138 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/columns.js +349 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +239 -0
- package/_Build/vue/modules/AuthModule/routes/account-exists.vue +2 -2
- package/_Build/vue/modules/AuthModule/routes/change-password.vue +28 -32
- package/_Build/vue/modules/AuthModule/routes/container.vue +2 -11
- package/_Build/vue/modules/AuthModule/routes/expired-reset.vue +4 -4
- package/_Build/vue/modules/AuthModule/routes/expired-verification.vue +10 -9
- package/_Build/vue/modules/AuthModule/routes/force-reset.vue +44 -58
- package/_Build/vue/modules/AuthModule/routes/forgot.vue +10 -5
- package/_Build/vue/modules/AuthModule/routes/login.vue +12 -19
- package/_Build/vue/modules/AuthModule/routes/logincallback.vue +1 -3
- package/_Build/vue/modules/AuthModule/routes/loginsso.vue +14 -10
- package/_Build/vue/modules/AuthModule/routes/logout.vue +17 -5
- package/_Build/vue/modules/AuthModule/routes/logoutheadless.vue +1 -3
- package/_Build/vue/modules/AuthModule/routes/register.vue +24 -28
- package/_Build/vue/modules/AuthModule/routes/reset.vue +20 -14
- package/_Build/vue/modules/AuthModule/routes/success-forgot.vue +14 -8
- package/_Build/vue/modules/AuthModule/routes/success-reset.vue +2 -2
- package/_Build/vue/modules/AuthModule/routes/success-verify.vue +1 -3
- package/_Build/vue/modules/AuthModule/routes/verify.vue +11 -14
- package/_Build/vue/modules/resource/Children/create.vue +81 -0
- package/_Build/vue/modules/resource/Children/edit.vue +106 -0
- package/_Build/vue/modules/resource/Children/index.vue +42 -0
- package/_Build/vue/modules/resource/Children/partials/form.vue +111 -0
- package/_Build/vue/modules/resource/Children/show.vue +166 -0
- package/_Build/vue/modules/resource/index.js +561 -0
- package/_Build/vue/modules/resource/parent.vue +63 -0
- package/_Build/vue/modules/resource/trashable.js +104 -0
- package/_base.scss +0 -1
- package/_defaults.scss +2 -13
- package/_variables.scss +9 -4
- package/{modules/_AuthModule.scss → components/_auth.scss} +19 -68
- package/components/_datepicker.scss +1 -0
- package/components/_descriptions.scss +2 -0
- package/components/_footer.scss +1 -0
- package/components/_form.scss +18 -0
- package/components/_header.scss +3 -27
- package/components/_layout.scss +56 -0
- package/components/_menu.scss +0 -5
- package/components/_sidebar.scss +12 -27
- package/components/_table.scss +3 -0
- package/components/_token-display.scss +41 -0
- package/general.scss +1 -0
- package/index.js +31 -1
- package/package.json +7 -4
- package/vendor.scss +0 -1
- package/_Build/vue/components/layout/sideBar.vue +0 -25
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/Upload/upload.vue +0 -251
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/create.vue +0 -62
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/edit.vue +0 -98
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/index.vue +0 -90
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/partials/form.vue +0 -173
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/show.vue +0 -262
- package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/parent.vue +0 -36
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/create.vue +0 -112
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/edit.vue +0 -103
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/index.vue +0 -112
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/partials/form.vue +0 -169
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +0 -120
- package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +0 -36
- package/components/_input.scss +0 -0
- package/modules/_AuthVariables.scss +0 -7
- /package/_Build/vue/{modules/AuthModule/components → components/layout}/AuthModal.vue +0 -0
- /package/_Build/vue/{modules/AuthModule/components → components/layout}/Chip.vue +0 -0
- /package/_Build/vue/{modules/AuthModule/components/VPasswordValidation.vue → components/layout/PasswordValidation.vue} +0 -0
- /package/_Build/vue/{modules/AuthModule/components/VRoleLegend.vue → components/layout/RoleLegend.vue} +0 -0
- /package/{modules → components}/_modal.scss +0 -0
|
@@ -3,8 +3,22 @@
|
|
|
3
3
|
import { h } from "vue";
|
|
4
4
|
import { RouterView } from "vue-router";
|
|
5
5
|
|
|
6
|
+
import { routes as resourceRoutes } from "../../resource/index.js";
|
|
7
|
+
|
|
8
|
+
import defaultUserResource from "../routes/PUsers/resource.js";
|
|
9
|
+
import defaultCompanyResource from "../routes/PCompanies/resource.js";
|
|
10
|
+
import defaultTeamResource from "../routes/PTeams/resource.js";
|
|
11
|
+
import defaultIntegrationResource from "../routes/PIntegrations/resource.js";
|
|
12
|
+
|
|
6
13
|
// Admin routes export - minimal auth flow (headless login only)
|
|
7
|
-
export function adminRoutes(node) {
|
|
14
|
+
export function adminRoutes(node, overrides = {}) {
|
|
15
|
+
const {
|
|
16
|
+
userResource = defaultUserResource,
|
|
17
|
+
companyResource = defaultCompanyResource,
|
|
18
|
+
teamResource = defaultTeamResource,
|
|
19
|
+
integrationResource = defaultIntegrationResource,
|
|
20
|
+
} = overrides;
|
|
21
|
+
|
|
8
22
|
return [
|
|
9
23
|
{
|
|
10
24
|
path: "/auth",
|
|
@@ -37,96 +51,25 @@ export function adminRoutes(node) {
|
|
|
37
51
|
: require("../routes/logincallback.vue").default,
|
|
38
52
|
name: "auth.callback",
|
|
39
53
|
},
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
path: "/users",
|
|
44
|
-
component: node
|
|
45
|
-
? ""
|
|
46
|
-
: require("../adminRoutes/PUsers/parent.vue").default,
|
|
47
|
-
children: [
|
|
48
54
|
{
|
|
49
|
-
path: "",
|
|
50
|
-
component:
|
|
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
|
-
},
|
|
80
|
-
],
|
|
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",
|
|
55
|
+
path: "verify",
|
|
56
|
+
component: require("../routes/verify.vue").default,
|
|
57
|
+
name: "auth.verify",
|
|
127
58
|
},
|
|
128
59
|
],
|
|
129
60
|
},
|
|
61
|
+
...resourceRoutes(node, ...userResource),
|
|
62
|
+
...resourceRoutes(node, ...companyResource, [
|
|
63
|
+
...resourceRoutes(node, teamResource[0], {
|
|
64
|
+
...teamResource[1],
|
|
65
|
+
routeName: "companies.teams",
|
|
66
|
+
}),
|
|
67
|
+
]),
|
|
68
|
+
...resourceRoutes(node, teamResource[0], {
|
|
69
|
+
...teamResource[1],
|
|
70
|
+
routeName: "teams",
|
|
71
|
+
}),
|
|
72
|
+
...resourceRoutes(node, ...integrationResource),
|
|
130
73
|
];
|
|
131
74
|
}
|
|
132
75
|
|
|
@@ -241,50 +184,84 @@ export function routes(node) {
|
|
|
241
184
|
}
|
|
242
185
|
|
|
243
186
|
export function beforeEach(router, store) {
|
|
187
|
+
let initialLoad = true;
|
|
188
|
+
|
|
189
|
+
// These routes must always be reachable regardless of auth/verification state.
|
|
190
|
+
// Without this, force_password_change or unverified state can trap the user with
|
|
191
|
+
// no way to log out or complete an SSO callback.
|
|
192
|
+
const ALWAYS_ALLOW = new Set(["auth.logout", "auth.callback"]);
|
|
193
|
+
|
|
244
194
|
router.beforeEach(async (to, from, next) => {
|
|
245
|
-
//
|
|
246
|
-
|
|
195
|
+
// Refresh user state on initial page load (handles cross-app state sync)
|
|
196
|
+
// or when authenticated query param is present (bypass/redirect flow)
|
|
197
|
+
if (
|
|
198
|
+
(store.getters.authenticated && initialLoad) ||
|
|
199
|
+
to.query.authenticated
|
|
200
|
+
) {
|
|
247
201
|
await store.dispatch("getUser", {
|
|
248
202
|
errors: (e) => console.error(e),
|
|
249
203
|
});
|
|
250
204
|
}
|
|
251
205
|
|
|
206
|
+
initialLoad = false;
|
|
207
|
+
|
|
252
208
|
const { user, redirect } = store.state.auth;
|
|
209
|
+
const isGuestRoute = to.matched.some((d) => d.meta.guest) === true;
|
|
253
210
|
|
|
254
|
-
//
|
|
211
|
+
// Logout and SSO callback must always be reachable — prevents every
|
|
212
|
+
// possible "stuck" scenario caused by state-based redirects below.
|
|
213
|
+
if (ALWAYS_ALLOW.has(to.name)) {
|
|
214
|
+
return next();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Redirect already-verified users away from verification routes
|
|
255
218
|
if (
|
|
256
219
|
to.query.verified ||
|
|
257
220
|
(to.name === "auth.expired-verification" && user?.email_verified_at)
|
|
258
221
|
) {
|
|
259
|
-
next({ name: "auth.success-verify" });
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
222
|
+
return next({ name: "auth.success-verify" });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (store.getters.authenticated) {
|
|
226
|
+
// 1. Email verification is the highest priority redirect.
|
|
227
|
+
// Must come before force_password_change — there is no point forcing
|
|
228
|
+
// a password change on an account that hasn't been verified yet.
|
|
229
|
+
// Guest routes, auth.verify and auth.expired-verification are exempt
|
|
230
|
+
// so the user can always complete or re-request verification.
|
|
231
|
+
if (
|
|
269
232
|
!user?.email_verified_at &&
|
|
270
|
-
|
|
233
|
+
!isGuestRoute &&
|
|
234
|
+
to.name !== "auth.verify" &&
|
|
235
|
+
to.name !== "auth.expired-verification"
|
|
271
236
|
) {
|
|
272
|
-
|
|
273
|
-
next({ name: "auth.verify" });
|
|
274
|
-
} else {
|
|
275
|
-
// User is authenticated and authorized - proceed
|
|
276
|
-
next();
|
|
237
|
+
return next({ name: "auth.verify" });
|
|
277
238
|
}
|
|
278
|
-
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
239
|
+
|
|
240
|
+
// 2. Force password change applies only after verification is satisfied.
|
|
241
|
+
// Guest routes are exempt so the user can still navigate within /auth
|
|
242
|
+
// (e.g. auth.verify, auth.expired-verification) without looping.
|
|
243
|
+
if (
|
|
244
|
+
user?.force_password_change &&
|
|
245
|
+
!isGuestRoute &&
|
|
246
|
+
to.name !== "auth.force-reset"
|
|
247
|
+
) {
|
|
248
|
+
return next({ name: "auth.force-reset" });
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 3. Redirect an already-authenticated user away from the login page
|
|
252
|
+
if (to.name === "auth.login") {
|
|
253
|
+
return next({ name: redirect });
|
|
286
254
|
}
|
|
255
|
+
|
|
256
|
+
return next();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Unauthenticated: allow guest routes, otherwise redirect to login
|
|
260
|
+
if (isGuestRoute) {
|
|
261
|
+
return next();
|
|
287
262
|
}
|
|
263
|
+
|
|
264
|
+
return next({ name: "auth.login" });
|
|
288
265
|
});
|
|
289
266
|
}
|
|
290
267
|
|
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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,11 +60,19 @@ const store = {
|
|
|
51
60
|
.catch(errors);
|
|
52
61
|
},
|
|
53
62
|
|
|
54
|
-
logout({ commit }
|
|
63
|
+
logout({ commit }) {
|
|
55
64
|
commit("setUser", null);
|
|
56
65
|
|
|
57
66
|
return axios.post("/logout");
|
|
58
67
|
},
|
|
68
|
+
|
|
69
|
+
stopImpersonating({ commit }) {
|
|
70
|
+
return axios.post("/api/users/impersonate/stop").then((res) => {
|
|
71
|
+
commit("setUser", res.data.data);
|
|
72
|
+
|
|
73
|
+
return res.data.data;
|
|
74
|
+
});
|
|
75
|
+
},
|
|
59
76
|
},
|
|
60
77
|
};
|
|
61
78
|
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { h, resolveComponent } from "vue";
|
|
2
|
+
import { ElInput } from "element-plus";
|
|
3
|
+
|
|
4
|
+
import VelBasic from "../../../../components/form/basic.vue";
|
|
5
|
+
import VelButton from "../../../../components/basic/Button.vue";
|
|
6
|
+
import VelSelect from "../../../../components/form/Select.vue";
|
|
7
|
+
import VelFormRole from "../../../../components/layout/FormRole.vue";
|
|
8
|
+
import Chip from "../../../../components/layout/Chip.vue";
|
|
9
|
+
import Chips from "../../../../components/layout/Chips.vue";
|
|
10
|
+
|
|
11
|
+
export default [
|
|
12
|
+
{
|
|
13
|
+
key: "name",
|
|
14
|
+
sortable: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: "primary_contact",
|
|
18
|
+
label: "Primary Contact",
|
|
19
|
+
condition: {
|
|
20
|
+
table: false,
|
|
21
|
+
form: {
|
|
22
|
+
write: ({ method }) => method === "patch",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
preparation: ({ form }) => form.primary_contact?.id,
|
|
26
|
+
render: {
|
|
27
|
+
read: ({ model }) => h("span", model.primary_contact?.name),
|
|
28
|
+
write: ({ $route }) =>
|
|
29
|
+
h(VelSelect, {
|
|
30
|
+
endpoint: `api/users`,
|
|
31
|
+
params: {
|
|
32
|
+
"filter[company_id]": $route.params.companiesId,
|
|
33
|
+
},
|
|
34
|
+
labelKey: "name",
|
|
35
|
+
filterable: true,
|
|
36
|
+
searchParam: "name",
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "primary_contact_email",
|
|
42
|
+
label: "Primary Contact Email",
|
|
43
|
+
condition: {
|
|
44
|
+
table: false,
|
|
45
|
+
form: false,
|
|
46
|
+
},
|
|
47
|
+
render: {
|
|
48
|
+
read: ({ model }) => h("span", model.primary_contact?.email),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: "primary_contact_contacted",
|
|
53
|
+
label: "Primary Contact Contacted",
|
|
54
|
+
condition: {
|
|
55
|
+
table: false,
|
|
56
|
+
form: false,
|
|
57
|
+
},
|
|
58
|
+
render: {
|
|
59
|
+
read: ({ model }) =>
|
|
60
|
+
h("span", String(!!model.primary_contact_contacted)),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: "domains",
|
|
65
|
+
condition: {
|
|
66
|
+
table: false,
|
|
67
|
+
},
|
|
68
|
+
initial: ({ model }) => model?.domains || [],
|
|
69
|
+
render: {
|
|
70
|
+
read: ({ model }) => h("span", model.domains.join(", ")),
|
|
71
|
+
write: ({ form }) =>
|
|
72
|
+
h("div", { class: "form__group vel-basic" }, [
|
|
73
|
+
h("p", { class: "my-0" }, [
|
|
74
|
+
"Domain/s ",
|
|
75
|
+
h("sup", { class: "color-status-red-100" }, "*"),
|
|
76
|
+
]),
|
|
77
|
+
h(
|
|
78
|
+
"ul",
|
|
79
|
+
{ class: "list-none pl-0 mt mb-2" },
|
|
80
|
+
form.domains.map((domain, index) =>
|
|
81
|
+
h("li", { key: index, class: "mb-0.5" }, [
|
|
82
|
+
h(
|
|
83
|
+
ElInput,
|
|
84
|
+
{
|
|
85
|
+
modelValue: form.domains[index],
|
|
86
|
+
"onUpdate:modelValue": (val) => {
|
|
87
|
+
form.domains[index] = val;
|
|
88
|
+
},
|
|
89
|
+
placeholder: "avalerehealth.com",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
prepend: () => "@",
|
|
93
|
+
append: () =>
|
|
94
|
+
h(
|
|
95
|
+
VelButton,
|
|
96
|
+
{
|
|
97
|
+
type: "danger",
|
|
98
|
+
onClick: () =>
|
|
99
|
+
form.domains.splice(
|
|
100
|
+
index,
|
|
101
|
+
1,
|
|
102
|
+
),
|
|
103
|
+
},
|
|
104
|
+
() =>
|
|
105
|
+
h(
|
|
106
|
+
resolveComponent(
|
|
107
|
+
"GSvg",
|
|
108
|
+
),
|
|
109
|
+
{
|
|
110
|
+
class: "vel-icon",
|
|
111
|
+
name: "icon-trash",
|
|
112
|
+
},
|
|
113
|
+
),
|
|
114
|
+
),
|
|
115
|
+
},
|
|
116
|
+
),
|
|
117
|
+
form.errors?.has?.(`domains.${index}`) &&
|
|
118
|
+
h(
|
|
119
|
+
"small",
|
|
120
|
+
{
|
|
121
|
+
class: "form__error vel-basic__error",
|
|
122
|
+
},
|
|
123
|
+
form.errors.first(`domains.${index}`),
|
|
124
|
+
),
|
|
125
|
+
]),
|
|
126
|
+
),
|
|
127
|
+
),
|
|
128
|
+
h("div", [
|
|
129
|
+
h(
|
|
130
|
+
VelButton,
|
|
131
|
+
{
|
|
132
|
+
onClick: () => form.domains.push(""),
|
|
133
|
+
},
|
|
134
|
+
() => [
|
|
135
|
+
"Add Domain ",
|
|
136
|
+
h(resolveComponent("GIcon"), {
|
|
137
|
+
name: "icon-plus",
|
|
138
|
+
embed: true,
|
|
139
|
+
asis: true,
|
|
140
|
+
class: "fill-0 icon--0.5 ml",
|
|
141
|
+
}),
|
|
142
|
+
],
|
|
143
|
+
),
|
|
144
|
+
]),
|
|
145
|
+
]),
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
key: "seats",
|
|
150
|
+
label: "Available Seats",
|
|
151
|
+
type: "number",
|
|
152
|
+
min: 0,
|
|
153
|
+
condition: {
|
|
154
|
+
table: false,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
key: "user_count",
|
|
159
|
+
label: "Total Users",
|
|
160
|
+
width: "150",
|
|
161
|
+
condition: {
|
|
162
|
+
form: false,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
key: "sso_enabled",
|
|
167
|
+
label: "SSO Enabled",
|
|
168
|
+
condition: {
|
|
169
|
+
table: false,
|
|
170
|
+
form: false,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
key: "roles",
|
|
175
|
+
label: "Role",
|
|
176
|
+
condition: {
|
|
177
|
+
description: false,
|
|
178
|
+
form: {
|
|
179
|
+
write: ({ $store }) => $store.getters.can("edit roles"),
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
initial: ({ model }) =>
|
|
183
|
+
model?.roles.map((val) => ({
|
|
184
|
+
label: val.label,
|
|
185
|
+
value: val.id,
|
|
186
|
+
})) || [],
|
|
187
|
+
preparation: ({ form }) =>
|
|
188
|
+
form.roles.map((d) => (typeof d === "object" ? d.value : d)),
|
|
189
|
+
render: {
|
|
190
|
+
read: ({ model }) =>
|
|
191
|
+
h(
|
|
192
|
+
model.roles.length === 1 ? Chip : Chips,
|
|
193
|
+
model.roles.length === 1
|
|
194
|
+
? {
|
|
195
|
+
name: model.roles[0].name,
|
|
196
|
+
label: model.roles[0].label,
|
|
197
|
+
}
|
|
198
|
+
: { array: model.roles },
|
|
199
|
+
),
|
|
200
|
+
write: ({ model, form }) =>
|
|
201
|
+
h(VelFormRole, {
|
|
202
|
+
overrides: model?.overrides_roles_and_permissions,
|
|
203
|
+
form,
|
|
204
|
+
}),
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
key: "sso_type",
|
|
209
|
+
label: "Provider",
|
|
210
|
+
condition: {
|
|
211
|
+
table: false,
|
|
212
|
+
description: false,
|
|
213
|
+
form: {
|
|
214
|
+
write: ({ $store }) => $store.getters.can("edit sso"),
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
initial: ({ model }) => model?.sso_type || undefined,
|
|
218
|
+
preparation: ({ form }) => form.sso_type?.value,
|
|
219
|
+
render: {
|
|
220
|
+
write: () =>
|
|
221
|
+
h(VelSelect, {
|
|
222
|
+
clearable: true,
|
|
223
|
+
class: "mt-2",
|
|
224
|
+
options: [
|
|
225
|
+
{ value: "azure", label: "azure" },
|
|
226
|
+
{ value: "google", label: "google" },
|
|
227
|
+
],
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
key: "sso_client_id",
|
|
233
|
+
label: "Key",
|
|
234
|
+
condition: {
|
|
235
|
+
table: false,
|
|
236
|
+
description: false,
|
|
237
|
+
form: {
|
|
238
|
+
write: ({ $store }) => $store.getters.can("edit sso"),
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
initial: ({ model }) => model?.sso_client_id || undefined,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
key: "sso_tenant",
|
|
245
|
+
label: "Tenant",
|
|
246
|
+
condition: {
|
|
247
|
+
table: false,
|
|
248
|
+
description: false,
|
|
249
|
+
form: {
|
|
250
|
+
write: ({ $store }) => $store.getters.can("edit sso"),
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
initial: ({ model }) => model?.sso_tenant || undefined,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
key: "sso_client_secret",
|
|
257
|
+
label: "Secret",
|
|
258
|
+
type: "password",
|
|
259
|
+
condition: {
|
|
260
|
+
table: false,
|
|
261
|
+
description: false,
|
|
262
|
+
form: {
|
|
263
|
+
write: ({ $store }) => $store.getters.can("edit sso"),
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
initial: ({ model }) => model?.sso_client_secret || undefined,
|
|
267
|
+
},
|
|
268
|
+
];
|