@fishawack/lab-velocity 2.0.0-beta.4 → 2.0.0-beta.41

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 (110) hide show
  1. package/README.md +441 -37
  2. package/_Build/vue/components/basic/Button.vue +1 -1
  3. package/_Build/vue/components/form/Checkbox.vue +10 -0
  4. package/_Build/vue/components/form/Select.vue +223 -33
  5. package/_Build/vue/components/form/Spinner.vue +5 -0
  6. package/_Build/vue/components/layout/Alert.vue +5 -5
  7. package/_Build/vue/components/layout/Audit.vue +75 -0
  8. package/_Build/vue/{modules/AuthModule/components/VBreadcrumbs.vue → components/layout/Breadcrumbs.vue} +4 -4
  9. package/_Build/vue/{modules/AuthModule/components → components/layout}/Chips.vue +2 -2
  10. package/_Build/vue/components/layout/Footer.vue +11 -10
  11. package/_Build/vue/{modules/AuthModule/components/VFormFooter.vue → components/layout/FormFooter.vue} +13 -7
  12. package/_Build/vue/{modules/AuthModule/components → components/layout}/FormRole.vue +10 -8
  13. package/_Build/vue/components/layout/Layout.vue +76 -0
  14. package/_Build/vue/components/layout/Navigation.vue +77 -0
  15. package/_Build/vue/{modules/AuthModule/components/VPageHeader.vue → components/layout/PageHeader.vue} +7 -2
  16. package/_Build/vue/components/layout/SideBar.vue +26 -0
  17. package/_Build/vue/{modules/AuthModule/components/VTable.vue → components/layout/Table.vue} +32 -16
  18. package/_Build/vue/{modules/AuthModule/components/VTableSorter.vue → components/layout/TableSorter.vue} +68 -43
  19. package/_Build/vue/components/layout/pageTitle.vue +1 -1
  20. package/_Build/vue/components/navigation/MenuItem.vue +7 -2
  21. package/_Build/vue/components/navigation/MenuItemGroup.vue +7 -2
  22. package/_Build/vue/modules/AuthModule/js/axios.js +19 -0
  23. package/_Build/vue/modules/AuthModule/js/router.js +24 -89
  24. package/_Build/vue/modules/AuthModule/js/store.js +15 -6
  25. package/_Build/vue/modules/AuthModule/routes/PCompanies/columns.js +268 -0
  26. package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +213 -0
  27. package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +334 -0
  28. package/_Build/vue/modules/AuthModule/routes/PUsers/columns.js +349 -0
  29. package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +203 -0
  30. package/_Build/vue/modules/AuthModule/routes/account-exists.vue +2 -2
  31. package/_Build/vue/modules/AuthModule/routes/change-password.vue +23 -24
  32. package/_Build/vue/modules/AuthModule/routes/container.vue +2 -11
  33. package/_Build/vue/modules/AuthModule/routes/expired-reset.vue +4 -4
  34. package/_Build/vue/modules/AuthModule/routes/expired-verification.vue +9 -8
  35. package/_Build/vue/modules/AuthModule/routes/force-reset.vue +39 -50
  36. package/_Build/vue/modules/AuthModule/routes/forgot.vue +4 -4
  37. package/_Build/vue/modules/AuthModule/routes/login.vue +7 -11
  38. package/_Build/vue/modules/AuthModule/routes/logincallback.vue +1 -3
  39. package/_Build/vue/modules/AuthModule/routes/loginsso.vue +7 -9
  40. package/_Build/vue/modules/AuthModule/routes/logout.vue +1 -3
  41. package/_Build/vue/modules/AuthModule/routes/logoutheadless.vue +1 -3
  42. package/_Build/vue/modules/AuthModule/routes/register.vue +19 -21
  43. package/_Build/vue/modules/AuthModule/routes/reset.vue +14 -13
  44. package/_Build/vue/modules/AuthModule/routes/success-forgot.vue +8 -7
  45. package/_Build/vue/modules/AuthModule/routes/success-reset.vue +2 -2
  46. package/_Build/vue/modules/AuthModule/routes/success-verify.vue +1 -3
  47. package/_Build/vue/modules/AuthModule/routes/verify.vue +11 -14
  48. package/_Build/vue/modules/resource/Children/create.vue +81 -0
  49. package/_Build/vue/modules/resource/Children/edit.vue +106 -0
  50. package/_Build/vue/modules/resource/Children/index.vue +42 -0
  51. package/_Build/vue/modules/resource/Children/partials/form.vue +61 -0
  52. package/_Build/vue/modules/resource/Children/show.vue +144 -0
  53. package/_Build/vue/modules/resource/index.js +545 -0
  54. package/_Build/vue/modules/resource/parent.vue +63 -0
  55. package/_base.scss +0 -1
  56. package/_defaults.scss +2 -13
  57. package/_variables.scss +9 -4
  58. package/components/_alert.scss +5 -0
  59. package/components/_auth.scss +163 -0
  60. package/components/_basic.scss +55 -0
  61. package/components/_breadcrumbs.scss +39 -0
  62. package/components/_button.scss +304 -0
  63. package/components/_cascader.scss +12 -0
  64. package/components/_checkbox.scss +41 -0
  65. package/components/_chip.scss +24 -0
  66. package/components/_collapse.scss +24 -0
  67. package/components/_datepicker.scss +53 -0
  68. package/components/_descriptions.scss +2 -0
  69. package/components/_footer.scss +47 -0
  70. package/components/_form.scss +24 -0
  71. package/components/_header.scss +30 -0
  72. package/components/_icon.scss +25 -0
  73. package/components/_inputNumber.scss +22 -0
  74. package/components/_layout.scss +56 -0
  75. package/components/_link.scss +44 -0
  76. package/components/_loader.scss +43 -0
  77. package/components/_menu.scss +112 -0
  78. package/components/_modal.scss +24 -0
  79. package/components/_pageTitle.scss +8 -0
  80. package/components/_permissionLegend.scss +18 -0
  81. package/components/_select.scss +29 -0
  82. package/components/_sidebar.scss +41 -0
  83. package/components/_switch.scss +14 -0
  84. package/components/_table.scss +20 -0
  85. package/components/_tooltip.scss +4 -0
  86. package/components/_typography.scss +162 -0
  87. package/components/_upload.scss +15 -0
  88. package/components/_wysiwyg.scss +7 -0
  89. package/components/_wysiwyg2.scss +142 -0
  90. package/index.js +16 -1
  91. package/package.json +5 -3
  92. package/vendor.scss +0 -1
  93. package/_Build/vue/components/layout/sideBar.vue +0 -25
  94. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/Upload/upload.vue +0 -251
  95. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/create.vue +0 -62
  96. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/edit.vue +0 -98
  97. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/index.vue +0 -90
  98. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/partials/form.vue +0 -173
  99. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/show.vue +0 -262
  100. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/parent.vue +0 -36
  101. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/create.vue +0 -112
  102. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/edit.vue +0 -103
  103. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/index.vue +0 -112
  104. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/partials/form.vue +0 -169
  105. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +0 -120
  106. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +0 -36
  107. /package/_Build/vue/{modules/AuthModule/components → components/layout}/AuthModal.vue +0 -0
  108. /package/_Build/vue/{modules/AuthModule/components → components/layout}/Chip.vue +0 -0
  109. /package/_Build/vue/{modules/AuthModule/components/VPasswordValidation.vue → components/layout/PasswordValidation.vue} +0 -0
  110. /package/_Build/vue/{modules/AuthModule/components/VRoleLegend.vue → components/layout/RoleLegend.vue} +0 -0
@@ -5,6 +5,7 @@
5
5
  </template>
6
6
 
7
7
  <el-select
8
+ ref="select"
8
9
  v-model="content"
9
10
  :class="baseClass"
10
11
  :multiple="multiple"
@@ -14,32 +15,35 @@
14
15
  :collapse-tags="collapseTags"
15
16
  :filterable="filterable"
16
17
  :value-on-clear="null"
17
- @change="handleInput"
18
- @clear="this.$emit('clear')"
19
- @blur="this.$emit('blur')"
18
+ remote-show-suffix
19
+ :remote="!!endpoint"
20
+ :remote-method="endpoint ? handleSearch : undefined"
21
+ :loading="initialLoading"
20
22
  :empty-values="[null, undefined]"
23
+ :value-key="effectiveValueKey"
24
+ @change="handleInput"
25
+ @clear="$emit('clear')"
26
+ @blur="$emit('blur')"
27
+ @visible-change="handleVisibleChange"
21
28
  >
22
29
  <template #default>
23
30
  <slot name="default">
24
31
  <el-option
25
- v-if="!options[0]?.label"
26
- v-for="(label, value) in options"
27
- :key="value"
28
- :label="label"
29
- :value="castValue(value)"
30
- >
31
- </el-option>
32
- <el-option
33
- v-else
34
- v-for="option in options"
35
- :key="option.value"
36
- :label="option.label"
32
+ v-for="option in currentOptions"
33
+ :key="option[effectiveValueKey]"
34
+ :label="option[labelKey]"
37
35
  :disabled="option.disabled"
38
- :value="castValue(option.value)"
36
+ :value="option"
39
37
  >
40
38
  </el-option>
41
39
  </slot>
42
40
  </template>
41
+ <template v-if="endpoint" #loading>
42
+ <div class="el-select-dropdown__loading">Loading...</div>
43
+ </template>
44
+ <template #label="{ value }">
45
+ {{ value[labelKey] || value }}
46
+ </template>
43
47
  </el-select>
44
48
  </XInput>
45
49
  </template>
@@ -47,17 +51,26 @@
47
51
  <script>
48
52
  import { ElSelect } from "element-plus";
49
53
  import { ElOption } from "element-plus";
54
+ import { ElNotification } from "element-plus";
50
55
  import input from "./input.js";
51
56
  import XInput from "./input.vue";
52
57
  import _ from "lodash";
58
+ import axios from "axios";
53
59
 
54
60
  export default {
61
+ components: {
62
+ XInput,
63
+ ElOption,
64
+ ElSelect,
65
+ },
66
+
55
67
  mixins: [input],
68
+
56
69
  props: {
57
70
  ...input.props,
58
71
  modelValue: {
59
- type: Array,
60
- default: [],
72
+ type: [Array, Number],
73
+ default: () => [],
61
74
  },
62
75
  baseClass: {
63
76
  type: String,
@@ -77,32 +90,209 @@ export default {
77
90
  },
78
91
  options: {
79
92
  type: Array,
80
- default: [],
93
+ default: () => [],
81
94
  },
82
95
  multiple: {
83
96
  type: Boolean,
84
97
  default: false,
85
98
  },
99
+ endpoint: {
100
+ type: String,
101
+ default: null,
102
+ },
103
+ params: {
104
+ type: Object,
105
+ default: () => ({}),
106
+ },
107
+ labelKey: {
108
+ type: String,
109
+ default: "label",
110
+ },
111
+ valueKey: {
112
+ type: String,
113
+ default: null,
114
+ },
115
+ searchParam: {
116
+ type: String,
117
+ default: "name",
118
+ },
119
+ perPage: {
120
+ type: Number,
121
+ default: 10,
122
+ },
86
123
  },
87
124
 
88
- components: {
89
- XInput,
90
- ElOption,
91
- ElSelect,
125
+ emits: ["change", "clear", "blur"],
126
+
127
+ data() {
128
+ return {
129
+ initialLoading: false,
130
+ loadingMore: false,
131
+ asyncOptions: [],
132
+ currentPage: 1,
133
+ hasMore: false,
134
+ searchQuery: "",
135
+ lastSearchQuery: "",
136
+ initialLoadDone: false,
137
+ scrollListener: null,
138
+ wrapScrollTop: 0,
139
+ wrapScrollLeft: 0,
140
+ };
141
+ },
142
+
143
+ computed: {
144
+ currentOptions() {
145
+ // If endpoint is provided, use async options, otherwise use static options
146
+ if (this.endpoint) {
147
+ return this.asyncOptions;
148
+ }
149
+ return this.options;
150
+ },
151
+ effectiveValueKey() {
152
+ // If valueKey was explicitly provided, use it
153
+ if (this.valueKey !== null) {
154
+ return this.valueKey;
155
+ }
156
+ // Otherwise, use "id" for endpoints, "value" for static options
157
+ return this.endpoint ? "id" : "value";
158
+ },
159
+ },
160
+
161
+ mounted() {
162
+ if (this.endpoint && this.$refs.select?.$refs?.scrollbarRef) {
163
+ const scrollbar = this.$refs.select.$refs.scrollbarRef;
164
+ const wrapRef = scrollbar.wrapRef;
165
+
166
+ this.scrollListener = () => {
167
+ if (!wrapRef) return;
168
+
169
+ const distance = 10;
170
+ const prevTop = this.wrapScrollTop;
171
+ const prevLeft = this.wrapScrollLeft;
172
+
173
+ this.wrapScrollTop = wrapRef.scrollTop;
174
+ this.wrapScrollLeft = wrapRef.scrollLeft;
175
+
176
+ const arrivedStates = {
177
+ bottom:
178
+ this.wrapScrollTop + wrapRef.clientHeight >=
179
+ wrapRef.scrollHeight - distance,
180
+ top: this.wrapScrollTop <= distance && prevTop !== 0,
181
+ right:
182
+ this.wrapScrollLeft + wrapRef.clientWidth >=
183
+ wrapRef.scrollWidth - distance &&
184
+ prevLeft !== this.wrapScrollLeft,
185
+ left: this.wrapScrollLeft <= distance && prevLeft !== 0,
186
+ };
187
+
188
+ let direction = null;
189
+ if (prevTop !== this.wrapScrollTop) {
190
+ direction = this.wrapScrollTop > prevTop ? "bottom" : "top";
191
+ }
192
+ if (prevLeft !== this.wrapScrollLeft) {
193
+ direction =
194
+ this.wrapScrollLeft > prevLeft ? "right" : "left";
195
+ }
196
+
197
+ if (direction && arrivedStates[direction]) {
198
+ this.handleEndReached(direction);
199
+ }
200
+ };
201
+
202
+ wrapRef.addEventListener("scroll", this.scrollListener);
203
+ }
204
+ },
205
+
206
+ beforeUnmount() {
207
+ if (
208
+ this.scrollListener &&
209
+ this.$refs.select?.$refs?.scrollbarRef?.wrapRef
210
+ ) {
211
+ this.$refs.select.$refs.scrollbarRef.wrapRef.removeEventListener(
212
+ "scroll",
213
+ this.scrollListener,
214
+ );
215
+ }
92
216
  },
93
217
 
94
- emits: ["change", "clear", "blur"],
95
218
  methods: {
96
- castValue(value) {
97
- if (
98
- !_.isNull(value) &&
99
- typeof value === "string" &&
100
- value !== "" &&
101
- !isNaN(Number(value))
102
- ) {
103
- return parseInt(value);
219
+ async handleVisibleChange(visible) {
220
+ // Load data when dropdown is opened for the first time
221
+ if (visible && this.endpoint && !this.initialLoadDone) {
222
+ await this.handleSearch("");
223
+ }
224
+ },
225
+
226
+ async handleSearch(query) {
227
+ if (!this.endpoint) return;
228
+
229
+ // For initial load, allow empty query even if it matches lastSearchQuery
230
+ if (!this.initialLoadDone || query !== this.lastSearchQuery) {
231
+ this.searchQuery = query;
232
+ this.lastSearchQuery = query;
233
+ this.currentPage = 1;
234
+ this.asyncOptions = [];
235
+ await this.fetchOptions(1, query);
236
+
237
+ if (!this.initialLoadDone) {
238
+ this.initialLoadDone = true;
239
+ }
240
+ }
241
+ },
242
+
243
+ handleEndReached(direction) {
244
+ if (!this.endpoint) return;
245
+ if (direction !== "bottom") return;
246
+ if (!this.hasMore || this.loadingMore) return;
247
+ this.fetchOptions(this.currentPage + 1, this.searchQuery);
248
+ },
249
+
250
+ async fetchOptions(page, searchQuery = "") {
251
+ const isInitialLoad = page === 1;
252
+ const loadingKey = isInitialLoad ? "initialLoading" : "loadingMore";
253
+
254
+ if (this[loadingKey]) return;
255
+
256
+ this[loadingKey] = true;
257
+
258
+ try {
259
+ const requestParams = {
260
+ ...this.params,
261
+ page,
262
+ per_page: this.perPage,
263
+ };
264
+
265
+ // Add search filter if query is provided
266
+ if (searchQuery) {
267
+ requestParams[`filter[${this.searchParam}]`] = searchQuery;
268
+ }
269
+
270
+ const response = await axios.get(this.endpoint, {
271
+ params: requestParams,
272
+ });
273
+
274
+ const data = response.data.data || [];
275
+ const meta = response.data.meta;
276
+
277
+ // If it's the first page, replace options, otherwise append
278
+ if (page === 1) {
279
+ this.asyncOptions = data;
280
+ } else {
281
+ this.asyncOptions = [...this.asyncOptions, ...data];
282
+ }
283
+
284
+ this.currentPage = page;
285
+ this.hasMore = meta && meta.current_page < meta.last_page;
286
+ } catch (error) {
287
+ console.error("Error fetching select options:", error);
288
+ ElNotification.error({
289
+ title: "Error",
290
+ message: "Failed to load options. Please try again.",
291
+ duration: 5000,
292
+ });
293
+ } finally {
294
+ this[loadingKey] = false;
104
295
  }
105
- return value;
106
296
  },
107
297
  },
108
298
  };
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <p>Loading...</p>
3
+ </template>
4
+
5
+ <script></script>
@@ -11,7 +11,11 @@
11
11
  <script>
12
12
  import { ElAlert } from "element-plus";
13
13
  export default {
14
- name: "VPageTitle",
14
+ name: "Alert",
15
+
16
+ components: {
17
+ ElAlert,
18
+ },
15
19
 
16
20
  props: {
17
21
  effect: {
@@ -30,9 +34,5 @@ export default {
30
34
  default: true,
31
35
  },
32
36
  },
33
-
34
- components: {
35
- ElAlert,
36
- },
37
37
  };
38
38
  </script>
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <el-table
3
+ :data="audits"
4
+ :default-sort="
5
+ query && {
6
+ prop: query.sort_by,
7
+ order: query.sort_dir === 'asc' ? 'ascending' : 'descending',
8
+ }
9
+ "
10
+ @sort-change="$emit('sort-change')"
11
+ >
12
+ <el-table-column label="Previous" :fit="false">
13
+ <template #default="scope">
14
+ <p
15
+ :key="key"
16
+ v-for="{ key, value } in scope?.row?.old_values"
17
+ class="truncate color-9"
18
+ >
19
+ <strong>{{ $filters.ucfirst(key) }}</strong
20
+ ><br />{{ value }}
21
+ </p>
22
+ </template>
23
+ </el-table-column>
24
+
25
+ <el-table-column label="New" :fit="false">
26
+ <template #default="scope">
27
+ <p
28
+ :key="key"
29
+ v-for="{ key, value } in scope?.row?.new_values"
30
+ class="truncate"
31
+ >
32
+ <strong>{{ $filters.ucfirst(key) }}</strong
33
+ ><br />{{ value }}
34
+ </p>
35
+ </template>
36
+ </el-table-column>
37
+
38
+ <el-table-column label="User" prop="user.email" :fit="false" />
39
+
40
+ <el-table-column label="Date" :fit="false">
41
+ <template #default="scope">
42
+ {{ $filters.calendarFormat(scope?.row?.created_at) }}
43
+ </template>
44
+ </el-table-column>
45
+ </el-table>
46
+ </template>
47
+
48
+ <script>
49
+ import { ElTable, ElTableColumn } from "element-plus";
50
+
51
+ export default {
52
+ components: {
53
+ ElTable,
54
+ ElTableColumn,
55
+ },
56
+
57
+ props: ["data", "query"],
58
+
59
+ computed: {
60
+ audits() {
61
+ return (this.data || [])
62
+ .map((d) => {
63
+ d.new_values = Object.entries(d.new_values)
64
+ .filter(([key, value]) => value)
65
+ .map(([key, value]) => ({ key, value }));
66
+ d.old_values = Object.entries(d.old_values)
67
+ .filter(([key, value]) => value)
68
+ .map(([key, value]) => ({ key, value }));
69
+ return d;
70
+ })
71
+ .reverse();
72
+ },
73
+ },
74
+ };
75
+ </script>
@@ -3,7 +3,7 @@
3
3
  <div class="container px-6 tablet:px-4 mobile:px-2 mb-8 ml-0 mr-0">
4
4
  <div class="grid__1/1">
5
5
  <div class="flex items-center">
6
- <breadcrumbs :crumbs="items" />
6
+ <VelBreadcrumbs :crumbs="items" />
7
7
  </div>
8
8
  </div>
9
9
  </div>
@@ -11,12 +11,12 @@
11
11
  </template>
12
12
 
13
13
  <script>
14
- import Breadcrumbs from "../../../components/navigation/Breadcrumbs.vue";
14
+ import VelBreadcrumbs from "../navigation/Breadcrumbs.vue";
15
15
 
16
16
  export default {
17
- name: "VBreadcrumbs",
17
+ name: "Breadcrumbs",
18
18
  components: {
19
- Breadcrumbs,
19
+ VelBreadcrumbs,
20
20
  },
21
21
 
22
22
  props: {
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="chips">
3
3
  <template v-for="(item, index) in array" :key="item.name">
4
- <Chip
4
+ <VelChip
5
5
  class="chip--round"
6
6
  :name="item.name"
7
7
  :label="`${item.label}${index < array.length - 1 ? ',' : ''}`"
@@ -13,7 +13,7 @@
13
13
  <script>
14
14
  export default {
15
15
  components: {
16
- Chip: require("./Chip.vue").default,
16
+ VelChip: require("./Chip.vue").default,
17
17
  },
18
18
 
19
19
  props: {
@@ -8,25 +8,25 @@
8
8
  <div class="vel-footer__bottom">
9
9
  <div class="vel-footer__bottom__links">
10
10
  <p class="color-0">&copy;2025 Avalere Health.</p>
11
- <el-link
11
+ <VelLink
12
12
  underline
13
13
  class="color-0 ml"
14
14
  href="https://avalerehealth.com/privacy-policy/"
15
15
  target="_blank"
16
- >Privacy Policy</el-link
16
+ >Privacy Policy</VelLink
17
17
  >
18
- <el-link
18
+ <VelLink
19
19
  underline
20
20
  class="color-0 ml"
21
21
  href="https://avalerehealth.com/corporate-policies/"
22
22
  target="_blank"
23
- >Corporate policies and compliance</el-link
23
+ >Corporate policies and compliance</VelLink
24
24
  >
25
25
  </div>
26
26
  <div class="vel-footer__bottom__end">
27
27
  <p class="color-0">Have a question?</p>
28
- <el-link underline class="color-0 ml" :href="contact"
29
- >Contact our Support Team</el-link
28
+ <VelLink underline class="color-0 ml" :href="contact"
29
+ >Contact our Support Team</VelLink
30
30
  >
31
31
  </div>
32
32
  </div>
@@ -34,17 +34,18 @@
34
34
  </template>
35
35
 
36
36
  <script>
37
- import elLink from "../basic/link.vue";
37
+ import VelLink from "../basic/link.vue";
38
38
 
39
39
  export default {
40
+ components: {
41
+ VelLink,
42
+ },
43
+
40
44
  props: {
41
45
  contact: {
42
46
  required: true,
43
47
  type: String,
44
48
  },
45
49
  },
46
- components: {
47
- elLink,
48
- },
49
50
  };
50
51
  </script>
@@ -1,15 +1,15 @@
1
1
  <template>
2
2
  <div class="grid items-center my-4">
3
3
  <slot>
4
- <el-button type="primary" native-type="submit" :loading="loading">
4
+ <VelButton type="primary" native-type="submit" :loading="loading">
5
5
  Save changes
6
- </el-button>
6
+ </VelButton>
7
7
 
8
- <el-button tag="a" class="ml-2" @click="$router.go(-1)">
8
+ <VelButton tag="a" class="ml-2" @click="$router.go(-1)">
9
9
  Discard changes
10
- </el-button>
10
+ </VelButton>
11
11
 
12
- <el-button
12
+ <VelButton
13
13
  v-if="method === 'patch' && preview"
14
14
  class="ml-2"
15
15
  tag="a"
@@ -18,14 +18,20 @@
18
18
  link
19
19
  >
20
20
  <span v-text="`Preview`" />
21
- </el-button>
21
+ </VelButton>
22
22
  </slot>
23
23
  </div>
24
24
  </template>
25
25
 
26
26
  <script>
27
+ import VelButton from "../basic/Button.vue";
28
+
27
29
  export default {
28
- name: "VFormFooter",
30
+ name: "FormFooter",
31
+
32
+ components: {
33
+ VelButton,
34
+ },
29
35
 
30
36
  props: {
31
37
  loading: {
@@ -5,7 +5,7 @@
5
5
  <template v-if="readonly">
6
6
  <p>Roles</p>
7
7
  <div v-if="!overrides" class="my-2">
8
- <Chip
8
+ <VelChip
9
9
  class="mr mb inline-block"
10
10
  name="inherited"
11
11
  label="Inherited"
@@ -17,14 +17,14 @@
17
17
  :key="roles.find((d) => d.id === role)"
18
18
  class="mr mb inline-block"
19
19
  >
20
- <Chip
20
+ <VelChip
21
21
  :name="roles.find((d) => d.id === role)?.name"
22
22
  :label="roles.find((d) => d.id === role)?.label"
23
23
  />
24
24
  </li>
25
25
  </ul>
26
26
  </template>
27
- <el-select
27
+ <VelSelect
28
28
  v-else
29
29
  v-model="form.roles"
30
30
  class="mt-2"
@@ -49,21 +49,23 @@
49
49
  :key="index"
50
50
  class="mr mb inline-block"
51
51
  >
52
- <Chip :name="permission.name" :label="permission.label" />
52
+ <VelChip :name="permission.name" :label="permission.label" />
53
53
  </li>
54
54
  </ul>
55
55
  </template>
56
56
 
57
- <VRoleLegend class="mt-2" />
57
+ <VelRoleLegend class="mt-2" />
58
58
  </template>
59
59
 
60
60
  <script>
61
61
  import axios from "axios";
62
+ import VelSelect from "../form/Select.vue";
62
63
 
63
64
  export default {
64
65
  components: {
65
- VRoleLegend: require("./VRoleLegend.vue").default,
66
- Chip: require("./Chip.vue").default,
66
+ VelRoleLegend: require("./RoleLegend.vue").default,
67
+ VelChip: require("./Chip.vue").default,
68
+ VelSelect,
67
69
  },
68
70
 
69
71
  props: {
@@ -89,7 +91,7 @@ export default {
89
91
 
90
92
  computed: {
91
93
  permissions() {
92
- const allPermissions = this.form.roles.reduce((acc, id) => {
94
+ const allPermissions = (this.form.roles || []).reduce((acc, id) => {
93
95
  return acc.concat(
94
96
  this.roles.find((d) => d.id === id)?.permissions || [],
95
97
  );