@fishawack/lab-velocity 1.11.1 → 2.0.0-beta.2

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 (132) hide show
  1. package/README.md +13 -7
  2. package/_Build/vue/components/Icon.vue +33 -0
  3. package/_Build/vue/components/Svg.vue +45 -0
  4. package/{basic → _Build/vue/components/basic}/Button.vue +16 -18
  5. package/{basic → _Build/vue/components/basic}/link.vue +8 -7
  6. package/{form → _Build/vue/components/form}/Cascader.vue +13 -13
  7. package/{form → _Build/vue/components/form}/CheckboxGroup.vue +28 -6
  8. package/{form → _Build/vue/components/form}/DatePicker.vue +23 -7
  9. package/{form → _Build/vue/components/form}/InputNumber.vue +1 -2
  10. package/{form → _Build/vue/components/form}/Select.vue +8 -9
  11. package/{form → _Build/vue/components/form}/Switch.vue +2 -2
  12. package/{form → _Build/vue/components/form}/Upload.vue +4 -6
  13. package/{form → _Build/vue/components/form}/Wysiwyg.vue +14 -14
  14. package/_Build/vue/components/form/Wysiwyg2.vue +577 -0
  15. package/{form → _Build/vue/components/form}/basic.vue +25 -7
  16. package/{form → _Build/vue/components/form}/file.vue +1 -1
  17. package/{form → _Build/vue/components/form}/input.js +2 -2
  18. package/{form → _Build/vue/components/form}/input.vue +31 -11
  19. package/{layout → _Build/vue/components/layout}/Alert.vue +10 -10
  20. package/_Build/vue/components/layout/Footer.vue +50 -0
  21. package/{layout → _Build/vue/components/layout}/Header.vue +5 -7
  22. package/_Build/vue/components/layout/Loader.vue +59 -0
  23. package/{layout → _Build/vue/components/layout}/Tooltip.vue +12 -12
  24. package/{layout → _Build/vue/components/layout}/pageTitle.vue +4 -4
  25. package/{layout → _Build/vue/components/layout}/sideBar.vue +4 -6
  26. package/{navigation → _Build/vue/components/navigation}/Breadcrumbs.vue +15 -10
  27. package/{navigation → _Build/vue/components/navigation}/BreadcrumbsItem.vue +6 -6
  28. package/_Build/vue/components/navigation/Menu.vue +14 -0
  29. package/_Build/vue/components/navigation/MenuItem.vue +20 -0
  30. package/_Build/vue/components/navigation/MenuItemGroup.vue +20 -0
  31. package/_Build/vue/components/navigation/SubMenu.vue +20 -0
  32. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/Upload/upload.vue +251 -0
  33. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/create.vue +62 -0
  34. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/edit.vue +98 -0
  35. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/index.vue +90 -0
  36. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/partials/form.vue +173 -0
  37. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/show.vue +262 -0
  38. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/parent.vue +36 -0
  39. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/create.vue +112 -0
  40. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/edit.vue +103 -0
  41. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/index.vue +112 -0
  42. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/partials/form.vue +169 -0
  43. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +120 -0
  44. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +36 -0
  45. package/{AuthModule → _Build/vue/modules/AuthModule}/components/AuthModal.vue +30 -35
  46. package/_Build/vue/modules/AuthModule/components/Chip.vue +70 -0
  47. package/_Build/vue/modules/AuthModule/components/Chips.vue +26 -0
  48. package/_Build/vue/modules/AuthModule/components/FormRole.vue +115 -0
  49. package/_Build/vue/modules/AuthModule/components/VBreadcrumbs.vue +32 -0
  50. package/_Build/vue/modules/AuthModule/components/VFormFooter.vue +46 -0
  51. package/_Build/vue/modules/AuthModule/components/VPageHeader.vue +38 -0
  52. package/_Build/vue/modules/AuthModule/components/VPasswordValidation.vue +106 -0
  53. package/_Build/vue/modules/AuthModule/components/VRoleLegend.vue +43 -0
  54. package/_Build/vue/modules/AuthModule/components/VTable.vue +127 -0
  55. package/_Build/vue/modules/AuthModule/components/VTableSorter.vue +240 -0
  56. package/_Build/vue/modules/AuthModule/js/FakeAPI.js +78 -0
  57. package/_Build/vue/modules/AuthModule/js/axios.js +62 -0
  58. package/_Build/vue/modules/AuthModule/js/router.js +295 -0
  59. package/_Build/vue/modules/AuthModule/js/store.js +62 -0
  60. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/account-exists.vue +5 -7
  61. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/change-password.vue +28 -25
  62. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/container.vue +4 -8
  63. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/expired-reset.vue +13 -11
  64. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/expired-verification.vue +12 -12
  65. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/force-reset.vue +36 -26
  66. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/forgot.vue +11 -7
  67. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/login.vue +20 -15
  68. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/logincallback.vue +5 -10
  69. package/_Build/vue/modules/AuthModule/routes/loginheadless.vue +21 -0
  70. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/loginsso.vue +32 -25
  71. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/logout.vue +6 -6
  72. package/_Build/vue/modules/AuthModule/routes/logoutheadless.vue +27 -0
  73. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/register.vue +43 -25
  74. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/reset.vue +24 -14
  75. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/success-forgot.vue +14 -12
  76. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/success-reset.vue +4 -4
  77. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/success-verify.vue +10 -7
  78. package/{AuthModule → _Build/vue/modules/AuthModule}/routes/verify.vue +15 -12
  79. package/_base.scss +1 -1
  80. package/_defaults.scss +2 -3
  81. package/_variables.scss +16 -18
  82. package/general.scss +1 -2
  83. package/index.js +38 -30
  84. package/package.json +103 -102
  85. package/vendor.scss +2 -2
  86. package/AuthModule/components/VPasswordValidation.vue +0 -66
  87. package/AuthModule/js/AuthAxios.js +0 -59
  88. package/AuthModule/js/AuthRoutes.js +0 -186
  89. package/AuthModule/js/AuthStore.js +0 -99
  90. package/AuthModule/js/FakeAPI.js +0 -84
  91. package/AuthModule/routes/loginheadless.vue +0 -16
  92. package/Icon.vue +0 -33
  93. package/Svg.vue +0 -40
  94. package/components/_alert.scss +0 -5
  95. package/components/_basic.scss +0 -54
  96. package/components/_breadcrumbs.scss +0 -40
  97. package/components/_button.scss +0 -305
  98. package/components/_cascader.scss +0 -12
  99. package/components/_checkbox.scss +0 -40
  100. package/components/_collapse.scss +0 -25
  101. package/components/_datepicker.scss +0 -51
  102. package/components/_footer.scss +0 -46
  103. package/components/_form.scss +0 -22
  104. package/components/_header.scss +0 -55
  105. package/components/_icon.scss +0 -24
  106. package/components/_input.scss +0 -0
  107. package/components/_inputNumber.scss +0 -21
  108. package/components/_link.scss +0 -44
  109. package/components/_loader.scss +0 -44
  110. package/components/_menu.scss +0 -112
  111. package/components/_pageTitle.scss +0 -8
  112. package/components/_select.scss +0 -28
  113. package/components/_sidebar.scss +0 -57
  114. package/components/_switch.scss +0 -14
  115. package/components/_table.scss +0 -20
  116. package/components/_tooltip.scss +0 -4
  117. package/components/_typography.scss +0 -153
  118. package/components/_upload.scss +0 -15
  119. package/components/_wysiwyg.scss +0 -6
  120. package/components/_wysiwyg2.scss +0 -136
  121. package/form/Wysiwyg2.vue +0 -278
  122. package/layout/Footer.vue +0 -35
  123. package/layout/Loader.vue +0 -39
  124. package/modules/_AuthModule.scss +0 -209
  125. package/modules/_AuthVariables.scss +0 -7
  126. package/modules/_modal.scss +0 -24
  127. package/navigation/Menu.vue +0 -16
  128. package/navigation/MenuItem.vue +0 -20
  129. package/navigation/MenuItemGroup.vue +0 -20
  130. package/navigation/SubMenu.vue +0 -20
  131. /package/{form → _Build/vue/components/form}/Checkbox.vue +0 -0
  132. /package/{form → _Build/vue/components/form}/color.vue +0 -0
@@ -0,0 +1,262 @@
1
+ <template>
2
+ <VBreadcrumbs
3
+ :items="addBreadcrumbs"
4
+ class="mb-8"
5
+ container-classes="m-0"
6
+ />
7
+
8
+ <div class="container px-6 tablet:px-4 mobile:px-2 mb-8 ml-0 mr-0">
9
+ <div class="grid__1/1">
10
+ <template v-if="company">
11
+ <div class="bg-0 p-3 box-shadow-1 border-r-4 mb-6">
12
+ <VPageHeader icon="icon-business" :title="company.name">
13
+ <!--
14
+ Temporarily disabled
15
+ <el-button tag="a" type="secondary" :href="`/companies/${company.id}/upload`">
16
+ <GIcon class="fill-1 mr-0.5" name="icon-plus" embed artboard /> Import users
17
+ </el-button>
18
+ <el-button tag="a" type="secondary" :href="`/api/companies/${company.id}/export`">
19
+ <GIcon class="fill-1 mr-0.5" name="icon-download" embed artboard /> Export users
20
+ </el-button>
21
+ Temporarily disabled
22
+ -->
23
+
24
+ <el-button
25
+ v-if="company.primary_contact"
26
+ type="primary"
27
+ @click="sendWelcome"
28
+ >
29
+ Send welcome email
30
+ </el-button>
31
+
32
+ <el-button
33
+ v-if="$store.getters.can('write companies')"
34
+ tag="a"
35
+ type="primary"
36
+ @click="
37
+ $router.push({
38
+ name: 'companies.edit',
39
+ param: company.id,
40
+ })
41
+ "
42
+ >
43
+ <GIcon
44
+ class="fill-0 mr-0.5"
45
+ name="icon-edit"
46
+ embed
47
+ artboard
48
+ />
49
+ Edit company
50
+ </el-button>
51
+ </VPageHeader>
52
+
53
+ <hr class="my-3 hr-muted" />
54
+
55
+ <table>
56
+ <tbody>
57
+ <tr>
58
+ <td class="p">Domains</td>
59
+ <td class="p">
60
+ {{ company.domains.join(", ") }}
61
+ </td>
62
+ </tr>
63
+ <tr>
64
+ <td class="p">SSO Enabled</td>
65
+ <td class="p">
66
+ {{ company.sso_enabled }}
67
+ </td>
68
+ </tr>
69
+ <tr>
70
+ <td class="p">Primary Contact</td>
71
+ <td class="p">
72
+ {{ company.primary_contact?.name }}
73
+ </td>
74
+ </tr>
75
+ <tr>
76
+ <td class="p">Primary Contact Email</td>
77
+ <td class="p">
78
+ {{ company.primary_contact?.email }}
79
+ </td>
80
+ </tr>
81
+ <tr>
82
+ <td class="p">Primary Contact Contacted</td>
83
+ <td class="p">
84
+ {{ !!company.primary_contact_contacted }}
85
+ </td>
86
+ </tr>
87
+ <tr>
88
+ <td class="p">Total users</td>
89
+ <td class="p">
90
+ {{ company.user_count }}
91
+ </td>
92
+ </tr>
93
+ </tbody>
94
+ </table>
95
+
96
+ <hr class="my-3 hr-muted" />
97
+
98
+ <FormRole
99
+ :form="{ roles: company.roles.map((d) => d.id) }"
100
+ :readonly="true"
101
+ />
102
+ </div>
103
+
104
+ <VTableSorter
105
+ key="PShow"
106
+ api="users"
107
+ :json-data="jsonData"
108
+ :defaults="`filter[company_id]=${id}`"
109
+ :fixed-height="false"
110
+ >
111
+ <template #table-action>
112
+ <el-button
113
+ type="primary"
114
+ tag="a"
115
+ class="ml-2"
116
+ @click="
117
+ $router.push({
118
+ name: `${jsonData.pageLink}.create`,
119
+ query: { company_id: id },
120
+ })
121
+ "
122
+ >
123
+ <GIcon
124
+ name="icon-plus"
125
+ embed
126
+ asis
127
+ class="fill-0 mr-0.5"
128
+ />
129
+ Create new {{ jsonData.label }}
130
+ </el-button>
131
+ </template>
132
+ </VTableSorter>
133
+ </template>
134
+
135
+ <div v-else class="absolute transform-center text-center">
136
+ <GSpinner class="fill-5" />
137
+ <p v-text="`Loading...`" />
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </template>
142
+
143
+ <script>
144
+ import axios from "axios";
145
+
146
+ export default {
147
+ name: "PShow",
148
+
149
+ components: {
150
+ VBreadcrumbs: require("../../../components/VBreadcrumbs.vue").default,
151
+ VTableSorter: require("../../../components/VTableSorter.vue").default,
152
+ VPageHeader: require("../../../components/VPageHeader.vue").default,
153
+ },
154
+ props: {
155
+ breadcrumbs: {
156
+ type: Array,
157
+ required: true,
158
+ },
159
+ },
160
+
161
+ data() {
162
+ return {
163
+ processing: false,
164
+ company: null,
165
+ id: null,
166
+ addBreadcrumbs: [...this.$props.breadcrumbs],
167
+ jsonData: {
168
+ label: "user",
169
+ multiLabel: "users",
170
+ pageLink: "users",
171
+ api: "/api/users",
172
+ searchable: {
173
+ label: "Search users",
174
+ value: "name",
175
+ },
176
+ tableStructure: [
177
+ {
178
+ label: "Name",
179
+ key: "name",
180
+ sortable: true,
181
+ },
182
+ {
183
+ label: "Email",
184
+ key: "email",
185
+ sortable: true,
186
+ },
187
+ {
188
+ label: "Role",
189
+ component: {
190
+ module: (row) => {
191
+ if (
192
+ !row.overrides_roles_and_permissions ||
193
+ row.roles.length === 1
194
+ )
195
+ return require("../../../components/Chip.vue")
196
+ .default;
197
+
198
+ return require("../../../components/Chips.vue")
199
+ .default;
200
+ },
201
+ props: (row) => {
202
+ if (!row.overrides_roles_and_permissions)
203
+ return {
204
+ name: "inherited",
205
+ label: "Inherited",
206
+ };
207
+
208
+ return row.roles.length === 1
209
+ ? {
210
+ name: row.roles[0].name,
211
+ label: row.roles[0].label,
212
+ }
213
+ : { array: row.roles };
214
+ },
215
+ },
216
+ },
217
+ ],
218
+ },
219
+ };
220
+ },
221
+
222
+ mounted() {
223
+ this.id = this.$route.params.id;
224
+
225
+ axios
226
+ .get(`/api/companies/${this.id}?include=primary_contact`)
227
+ .then((res) => {
228
+ this.company = res.data.data;
229
+ this.addBreadcrumbs.push({
230
+ href: {
231
+ name: "companies.show",
232
+ param: this.company.id,
233
+ },
234
+ text: this.company.name,
235
+ });
236
+ });
237
+ },
238
+
239
+ methods: {
240
+ async sendWelcome() {
241
+ try {
242
+ const res = await axios.post(
243
+ `/api/companies/${this.id}/welcome`,
244
+ );
245
+ this.$notify({
246
+ title: "Success",
247
+ message: res.data.message,
248
+ type: "success",
249
+ });
250
+
251
+ this.company.primary_contact_contacted = true;
252
+ } catch (e) {
253
+ this.$notify({
254
+ title: "Warning",
255
+ message: e.response?.data?.message || e.message,
256
+ type: "warning",
257
+ });
258
+ }
259
+ },
260
+ },
261
+ };
262
+ </script>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <PageTitle title="Companies" />
3
+
4
+ <router-view :key="$route.path" :breadcrumbs="breadcrumbs" />
5
+ </template>
6
+
7
+ <script>
8
+ import { PageTitle } from "@fishawack/lab-velocity";
9
+
10
+ export default {
11
+ name: "PCompanies",
12
+
13
+ components: {
14
+ PageTitle,
15
+ },
16
+
17
+ data() {
18
+ return {
19
+ breadcrumbs: [
20
+ {
21
+ href: {
22
+ name: "index",
23
+ },
24
+ text: "Home",
25
+ },
26
+ {
27
+ href: {
28
+ name: "companies.index",
29
+ },
30
+ text: "Companies",
31
+ },
32
+ ],
33
+ };
34
+ },
35
+ };
36
+ </script>
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <VBreadcrumbs :items="breadcrumbs" class="mb-8" container-classes="m-0" />
3
+
4
+ <div class="container px-6 tablet:px-4 mobile:px-2 mb-8 ml-0 mr-0">
5
+ <div class="grid__1/1">
6
+ <div class="grid__1/1 mb-4">
7
+ <h2 class="h1">Create User</h2>
8
+ </div>
9
+ <div class="grid__1/2">
10
+ <XForm ref="form" :form="form" :submit="submit" />
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { ElMessageBox } from "element-plus";
18
+ import Form from "form-backend-validation";
19
+
20
+ export default {
21
+ name: "PCreate",
22
+
23
+ components: {
24
+ VBreadcrumbs: require("../../../components/VBreadcrumbs.vue").default,
25
+ XForm: require("./partials/form.vue").default,
26
+ },
27
+
28
+ props: {
29
+ breadcrumbs: {
30
+ type: Array,
31
+ required: true,
32
+ },
33
+ },
34
+
35
+ data() {
36
+ return {
37
+ form: new Form(
38
+ {
39
+ name: null,
40
+ email: null,
41
+ roles: [],
42
+ notify_user: true,
43
+ company_id: null,
44
+ force_password_change: true,
45
+ set_password: true,
46
+ password: null,
47
+ password_confirmation: null,
48
+ },
49
+ {
50
+ resetOnSuccess: false,
51
+ },
52
+ ),
53
+ };
54
+ },
55
+
56
+ methods: {
57
+ generatePassword(
58
+ length = 20,
59
+ characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$",
60
+ ) {
61
+ return Array.from(crypto.getRandomValues(new Uint32Array(length)))
62
+ .map((x) => characters[x % characters.length])
63
+ .join("");
64
+ },
65
+ async submit() {
66
+ try {
67
+ if (this.form.set_password) {
68
+ const password = this.generatePassword();
69
+ this.form.password = password;
70
+ this.form.password_confirmation = password;
71
+ }
72
+
73
+ let res = await this.form.post(`/api/users`);
74
+
75
+ if (!this.form.set_password) {
76
+ this.open(res.data.id);
77
+ } else {
78
+ this.$notify({
79
+ title: "Success",
80
+ message: "User created a notified of their new account",
81
+ type: "success",
82
+ });
83
+
84
+ this.$router.replace({
85
+ name: "users.show",
86
+ params: { id: res.data.id },
87
+ });
88
+ }
89
+ } catch (e) {
90
+ this.$root.errors(e);
91
+ }
92
+ },
93
+ open(id) {
94
+ ElMessageBox.alert(
95
+ `<p>The password below will not be shown again. Ensure you've taken a copy if you plan to send manually. <br><br><strong>Email</strong>: ${this.form.email}<br> <strong>Password</strong>: ${this.form.password}</p>`,
96
+ "User Created",
97
+ {
98
+ confirmButtonText: "Ok",
99
+ dangerouslyUseHTMLString: true,
100
+ },
101
+ )
102
+ .then(() => {
103
+ this.$router.replace({
104
+ name: "users.show",
105
+ params: { id },
106
+ });
107
+ })
108
+ .catch(() => {});
109
+ },
110
+ },
111
+ };
112
+ </script>
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <VBreadcrumbs
3
+ :items="addBreadcrumbs"
4
+ class="mb-8"
5
+ container-classes="m-0"
6
+ />
7
+
8
+ <div class="container px-6 tablet:px-4 mobile:px-2 mb-8 ml-0 mr-0">
9
+ <div class="grid__1/1">
10
+ <div class="grid__1/1 mb-4">
11
+ <h2 class="h1">Edit User</h2>
12
+ </div>
13
+ <div class="grid__1/2">
14
+ <XForm
15
+ :id="id"
16
+ ref="form"
17
+ :form="form"
18
+ :submit="submit"
19
+ method="patch"
20
+ />
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </template>
25
+
26
+ <script>
27
+ import Form from "form-backend-validation";
28
+
29
+ export default {
30
+ name: "PEdit",
31
+
32
+ components: {
33
+ VBreadcrumbs: require("../../../components/VBreadcrumbs.vue").default,
34
+ XForm: require("./partials/form.vue").default,
35
+ },
36
+
37
+ props: {
38
+ breadcrumbs: {
39
+ type: Array,
40
+ required: true,
41
+ },
42
+ },
43
+
44
+ data() {
45
+ return {
46
+ id: null,
47
+ form: new Form({
48
+ name: null,
49
+ email: null,
50
+ company_id: null,
51
+ roles: [],
52
+ }),
53
+ addBreadcrumbs: [...this.$props.breadcrumbs],
54
+ };
55
+ },
56
+
57
+ async mounted() {
58
+ this.id = this.$route.params.id;
59
+ window.axios
60
+ .get(`/api/users/${this.id}?include=company`)
61
+ .then((res) => {
62
+ const user = res.data.data;
63
+ this.form.name = user.name;
64
+ this.form.email = user.email;
65
+ this.form.company_id = user.company_id;
66
+ this.form.roles = user.overrides_roles_and_permissions
67
+ ? user.roles.map((val) => {
68
+ return val.id;
69
+ })
70
+ : [];
71
+ this.addBreadcrumbs.push({
72
+ href: {
73
+ name: "users.show",
74
+ param: this.id,
75
+ },
76
+ text: user.name,
77
+ });
78
+ });
79
+ },
80
+
81
+ methods: {
82
+ async submit() {
83
+ try {
84
+ let res = await this.form.patch(`/api/users/${this.id}`);
85
+
86
+ // if changing ourselves, re-fetch user data
87
+ if (res.data.id === this.$store.state.auth.user.id) {
88
+ await this.$store.dispatch("getUser", {
89
+ errors: this.$root.errors,
90
+ });
91
+ }
92
+
93
+ this.$router.replace({
94
+ name: "users.show",
95
+ params: { id: res.data.id },
96
+ });
97
+ } catch (e) {
98
+ this.$root.errors(e);
99
+ }
100
+ },
101
+ },
102
+ };
103
+ </script>
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <VBreadcrumbs :items="breadcrumbs" />
3
+
4
+ <div class="container px-6 tablet:px-4 mobile:px-2 mb-8 ml-0 mr-0">
5
+ <div class="grid__1/1">
6
+ <h2 class="h1 pb-4">
7
+ {{ breadcrumbs[breadcrumbs.length - 1].text }}
8
+ </h2>
9
+
10
+ <VTableSorter
11
+ key="PIndex"
12
+ api="users"
13
+ :json-data="jsonData"
14
+ defaults="include=company"
15
+ :fixed-height="false"
16
+ :display-edit-action="$store.getters.can('write users')"
17
+ />
18
+
19
+ <VRoleLegend class="mt-5" />
20
+ </div>
21
+ </div>
22
+ </template>
23
+
24
+ <script>
25
+ export default {
26
+ name: "PIndex",
27
+
28
+ components: {
29
+ VBreadcrumbs: require("../../../components/VBreadcrumbs.vue").default,
30
+ VTableSorter: require("../../../components/VTableSorter.vue").default,
31
+ VRoleLegend: require("../../../components/VRoleLegend.vue").default,
32
+ },
33
+
34
+ props: {
35
+ breadcrumbs: {
36
+ type: Array,
37
+ required: true,
38
+ },
39
+ },
40
+
41
+ data() {
42
+ return {
43
+ jsonData: {
44
+ label: "user",
45
+ multiLabel: "users",
46
+ pageLink: "users",
47
+ api: "/api/users",
48
+ searchable: {
49
+ label: "Search users",
50
+ value: "email",
51
+ },
52
+ tableStructure: [
53
+ {
54
+ label: "Name",
55
+ key: "name",
56
+ sortable: true,
57
+ },
58
+ {
59
+ label: "Email",
60
+ key: "email",
61
+ sortable: true,
62
+ },
63
+ {
64
+ label: "Company",
65
+ sortable: true,
66
+ component: {
67
+ is: () => "router-link",
68
+ props: (row) => ({
69
+ to: {
70
+ name: "companies.show",
71
+ params: { id: row.company_id },
72
+ },
73
+ text: row.company.name,
74
+ }),
75
+ },
76
+ },
77
+ {
78
+ label: "Role",
79
+ component: {
80
+ module: (row) => {
81
+ if (
82
+ !row.overrides_roles_and_permissions ||
83
+ row.roles.length === 1
84
+ )
85
+ return require("../../../components/Chip.vue")
86
+ .default;
87
+
88
+ return require("../../../components/Chips.vue")
89
+ .default;
90
+ },
91
+ props: (row) => {
92
+ if (!row.overrides_roles_and_permissions)
93
+ return {
94
+ name: "inherited",
95
+ label: "Inherited",
96
+ };
97
+
98
+ return row.roles.length === 1
99
+ ? {
100
+ name: row.roles[0].name,
101
+ label: row.roles[0].label,
102
+ }
103
+ : { array: row.roles };
104
+ },
105
+ },
106
+ },
107
+ ],
108
+ },
109
+ };
110
+ },
111
+ };
112
+ </script>