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

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 (108) 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 +231 -28
  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 +28 -88
  24. package/_Build/vue/modules/AuthModule/js/store.js +15 -6
  25. package/_Build/vue/modules/AuthModule/{adminRoutes/PCompanies/Children/partials → routes/PCompanies}/form.vue +50 -18
  26. package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +259 -0
  27. package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +308 -0
  28. package/_Build/vue/modules/AuthModule/{adminRoutes/PUsers/Children/partials → routes/PUsers}/form.vue +30 -18
  29. package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +215 -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 +24 -28
  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 +2 -4
  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 +59 -0
  52. package/_Build/vue/modules/resource/Children/show.vue +140 -0
  53. package/_Build/vue/modules/resource/index.js +494 -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 +10 -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/show.vue +0 -262
  99. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/parent.vue +0 -36
  100. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/create.vue +0 -112
  101. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/edit.vue +0 -103
  102. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/index.vue +0 -112
  103. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +0 -120
  104. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +0 -36
  105. /package/_Build/vue/{modules/AuthModule/components → components/layout}/AuthModal.vue +0 -0
  106. /package/_Build/vue/{modules/AuthModule/components → components/layout}/Chip.vue +0 -0
  107. /package/_Build/vue/{modules/AuthModule/components/VPasswordValidation.vue → components/layout/PasswordValidation.vue} +0 -0
  108. /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,42 @@
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
+ @change="handleInput"
24
+ @clear="$emit('clear')"
25
+ @blur="$emit('blur')"
26
+ @visible-change="handleVisibleChange"
21
27
  >
22
28
  <template #default>
23
29
  <slot name="default">
24
- <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"
37
- :disabled="option.disabled"
38
- :value="castValue(option.value)"
39
- >
40
- </el-option>
30
+ <template v-if="!currentOptions[0]?.label">
31
+ <el-option
32
+ v-for="(label, value) in currentOptions"
33
+ :key="value"
34
+ :label="label"
35
+ :value="castValue(value)"
36
+ >
37
+ </el-option>
38
+ </template>
39
+ <template v-else>
40
+ <el-option
41
+ v-for="option in currentOptions"
42
+ :key="option.value"
43
+ :label="option.label"
44
+ :disabled="option.disabled"
45
+ :value="option"
46
+ >
47
+ </el-option>
48
+ </template>
41
49
  </slot>
42
50
  </template>
51
+ <template v-if="endpoint" #loading>
52
+ <div class="el-select-dropdown__loading">Loading...</div>
53
+ </template>
43
54
  </el-select>
44
55
  </XInput>
45
56
  </template>
@@ -47,17 +58,26 @@
47
58
  <script>
48
59
  import { ElSelect } from "element-plus";
49
60
  import { ElOption } from "element-plus";
61
+ import { ElNotification } from "element-plus";
50
62
  import input from "./input.js";
51
63
  import XInput from "./input.vue";
52
64
  import _ from "lodash";
65
+ import axios from "axios";
53
66
 
54
67
  export default {
68
+ components: {
69
+ XInput,
70
+ ElOption,
71
+ ElSelect,
72
+ },
73
+
55
74
  mixins: [input],
75
+
56
76
  props: {
57
77
  ...input.props,
58
78
  modelValue: {
59
- type: Array,
60
- default: [],
79
+ type: [Array, Number],
80
+ default: () => [],
61
81
  },
62
82
  baseClass: {
63
83
  type: String,
@@ -77,21 +97,123 @@ export default {
77
97
  },
78
98
  options: {
79
99
  type: Array,
80
- default: [],
100
+ default: () => [],
81
101
  },
82
102
  multiple: {
83
103
  type: Boolean,
84
104
  default: false,
85
105
  },
106
+ endpoint: {
107
+ type: String,
108
+ default: null,
109
+ },
110
+ params: {
111
+ type: Object,
112
+ default: () => ({}),
113
+ },
114
+ labelKey: {
115
+ type: String,
116
+ default: "label",
117
+ },
118
+ valueKey: {
119
+ type: String,
120
+ default: "id",
121
+ },
122
+ searchParam: {
123
+ type: String,
124
+ default: "name",
125
+ },
126
+ perPage: {
127
+ type: Number,
128
+ default: 10,
129
+ },
86
130
  },
87
131
 
88
- components: {
89
- XInput,
90
- ElOption,
91
- ElSelect,
132
+ emits: ["change", "clear", "blur"],
133
+
134
+ data() {
135
+ return {
136
+ initialLoading: false,
137
+ loadingMore: false,
138
+ asyncOptions: [],
139
+ currentPage: 1,
140
+ hasMore: false,
141
+ searchQuery: "",
142
+ lastSearchQuery: "",
143
+ initialLoadDone: false,
144
+ scrollListener: null,
145
+ wrapScrollTop: 0,
146
+ wrapScrollLeft: 0,
147
+ };
148
+ },
149
+
150
+ computed: {
151
+ currentOptions() {
152
+ // If endpoint is provided, use async options, otherwise use static options
153
+ if (this.endpoint) {
154
+ return this.asyncOptions;
155
+ }
156
+ return this.options;
157
+ },
158
+ },
159
+
160
+ mounted() {
161
+ if (this.endpoint && this.$refs.select?.$refs?.scrollbarRef) {
162
+ const scrollbar = this.$refs.select.$refs.scrollbarRef;
163
+ const wrapRef = scrollbar.wrapRef;
164
+
165
+ this.scrollListener = () => {
166
+ if (!wrapRef) return;
167
+
168
+ const distance = 10;
169
+ const prevTop = this.wrapScrollTop;
170
+ const prevLeft = this.wrapScrollLeft;
171
+
172
+ this.wrapScrollTop = wrapRef.scrollTop;
173
+ this.wrapScrollLeft = wrapRef.scrollLeft;
174
+
175
+ const arrivedStates = {
176
+ bottom:
177
+ this.wrapScrollTop + wrapRef.clientHeight >=
178
+ wrapRef.scrollHeight - distance,
179
+ top: this.wrapScrollTop <= distance && prevTop !== 0,
180
+ right:
181
+ this.wrapScrollLeft + wrapRef.clientWidth >=
182
+ wrapRef.scrollWidth - distance &&
183
+ prevLeft !== this.wrapScrollLeft,
184
+ left: this.wrapScrollLeft <= distance && prevLeft !== 0,
185
+ };
186
+
187
+ let direction = null;
188
+ if (prevTop !== this.wrapScrollTop) {
189
+ direction = this.wrapScrollTop > prevTop ? "bottom" : "top";
190
+ }
191
+ if (prevLeft !== this.wrapScrollLeft) {
192
+ direction =
193
+ this.wrapScrollLeft > prevLeft ? "right" : "left";
194
+ }
195
+
196
+ if (direction && arrivedStates[direction]) {
197
+ this.handleEndReached(direction);
198
+ }
199
+ };
200
+
201
+ wrapRef.addEventListener("scroll", this.scrollListener);
202
+ }
203
+ },
204
+
205
+ beforeUnmount() {
206
+ if (
207
+ this.scrollListener &&
208
+ this.$refs.select?.$refs?.scrollbarRef?.wrapRef
209
+ ) {
210
+ this.$refs.select.$refs.scrollbarRef.wrapRef.removeEventListener(
211
+ "scroll",
212
+ this.scrollListener,
213
+ );
214
+ }
92
215
  },
93
216
 
94
- emits: ["change", "clear", "blur"],
95
217
  methods: {
96
218
  castValue(value) {
97
219
  if (
@@ -104,6 +226,87 @@ export default {
104
226
  }
105
227
  return value;
106
228
  },
229
+
230
+ async handleVisibleChange(visible) {
231
+ // Load data when dropdown is opened for the first time
232
+ if (visible && this.endpoint && !this.initialLoadDone) {
233
+ await this.fetchOptions(1, "");
234
+ this.initialLoadDone = true;
235
+ }
236
+ },
237
+
238
+ async handleSearch(query) {
239
+ if (!this.endpoint) return;
240
+ if (query === this.lastSearchQuery) return;
241
+
242
+ this.searchQuery = query;
243
+ this.lastSearchQuery = query;
244
+ this.currentPage = 1;
245
+ this.asyncOptions = [];
246
+ await this.fetchOptions(1, query);
247
+ },
248
+
249
+ handleEndReached(direction) {
250
+ if (!this.endpoint) return;
251
+ if (direction !== "bottom") return;
252
+ if (!this.hasMore || this.loadingMore) return;
253
+ this.fetchOptions(this.currentPage + 1, this.searchQuery);
254
+ },
255
+
256
+ async fetchOptions(page, searchQuery = "") {
257
+ const isInitialLoad = page === 1;
258
+ const loadingKey = isInitialLoad ? "initialLoading" : "loadingMore";
259
+
260
+ if (this[loadingKey]) return;
261
+
262
+ this[loadingKey] = true;
263
+
264
+ try {
265
+ const requestParams = {
266
+ ...this.params,
267
+ page,
268
+ per_page: this.perPage,
269
+ };
270
+
271
+ // Add search filter if query is provided
272
+ if (searchQuery) {
273
+ requestParams[`filter[${this.searchParam}]`] = searchQuery;
274
+ }
275
+
276
+ const response = await axios.get(this.endpoint, {
277
+ params: requestParams,
278
+ });
279
+
280
+ const data = response.data.data || [];
281
+ const meta = response.data.meta;
282
+
283
+ // Transform API data to option format
284
+ const newOptions = data.map((item) => ({
285
+ label: item[this.labelKey],
286
+ value: item[this.valueKey],
287
+ disabled: item.disabled || false,
288
+ }));
289
+
290
+ // If it's the first page, replace options, otherwise append
291
+ if (page === 1) {
292
+ this.asyncOptions = newOptions;
293
+ } else {
294
+ this.asyncOptions = [...this.asyncOptions, ...newOptions];
295
+ }
296
+
297
+ this.currentPage = page;
298
+ this.hasMore = meta && meta.current_page < meta.last_page;
299
+ } catch (error) {
300
+ console.error("Error fetching select options:", error);
301
+ ElNotification.error({
302
+ title: "Error",
303
+ message: "Failed to load options. Please try again.",
304
+ duration: 5000,
305
+ });
306
+ } finally {
307
+ this[loadingKey] = false;
308
+ }
309
+ },
107
310
  },
108
311
  };
109
312
  </script>
@@ -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
  );