@fishawack/lab-velocity 2.0.0-beta.6 → 2.0.0-beta.61

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 (111) hide show
  1. package/README.md +467 -36
  2. package/_Build/js/libs/build-id.js +14 -0
  3. package/_Build/js/libs/filters.js +36 -0
  4. package/_Build/js/libs/globals.js +7 -0
  5. package/_Build/js/libs/router.js +22 -0
  6. package/_Build/js/libs/routes.js +29 -0
  7. package/_Build/js/libs/store.js +21 -0
  8. package/_Build/js/libs/utility.js +161 -0
  9. package/_Build/vue/components/basic/Button.vue +1 -1
  10. package/_Build/vue/components/form/Avatar.vue +90 -0
  11. package/_Build/vue/components/form/Checkbox.vue +10 -0
  12. package/_Build/vue/components/form/InputNumber.vue +1 -1
  13. package/_Build/vue/components/form/Select.vue +221 -31
  14. package/_Build/vue/components/form/Wysiwyg2.vue +87 -2
  15. package/_Build/vue/components/form/wysiwyg2-video.js +41 -0
  16. package/_Build/vue/components/layout/Alert.vue +5 -5
  17. package/_Build/vue/components/layout/Audit.vue +159 -0
  18. package/_Build/vue/{modules/AuthModule/components/VBreadcrumbs.vue → components/layout/Breadcrumbs.vue} +4 -4
  19. package/_Build/vue/{modules/AuthModule/components → components/layout}/Chips.vue +2 -2
  20. package/_Build/vue/components/layout/Footer.vue +11 -10
  21. package/_Build/vue/{modules/AuthModule/components/VFormFooter.vue → components/layout/FormFooter.vue} +2 -2
  22. package/_Build/vue/{modules/AuthModule/components → components/layout}/FormRole.vue +8 -8
  23. package/_Build/vue/components/layout/Layout.vue +94 -0
  24. package/_Build/vue/components/layout/Navigation.vue +83 -0
  25. package/_Build/vue/{modules/AuthModule/components/VPageHeader.vue → components/layout/PageHeader.vue} +14 -8
  26. package/_Build/vue/components/layout/SideBar.vue +26 -0
  27. package/_Build/vue/{modules/AuthModule/components/VTable.vue → components/layout/Table.vue} +24 -12
  28. package/_Build/vue/{modules/AuthModule/components/VTableSorter.vue → components/layout/TableSorter.vue} +92 -48
  29. package/_Build/vue/components/layout/TokenDisplay.vue +52 -0
  30. package/_Build/vue/components/layout/pageTitle.vue +1 -1
  31. package/_Build/vue/components/navigation/Menu.vue +6 -1
  32. package/_Build/vue/components/navigation/MenuItem.vue +7 -2
  33. package/_Build/vue/components/navigation/MenuItemGroup.vue +7 -2
  34. package/_Build/vue/modules/AuthModule/js/axios.js +21 -1
  35. package/_Build/vue/modules/AuthModule/js/clear-cookies.js +34 -0
  36. package/_Build/vue/modules/AuthModule/js/guest-request.js +32 -0
  37. package/_Build/vue/modules/AuthModule/js/impersonation-banner.js +102 -0
  38. package/_Build/vue/modules/AuthModule/js/router.js +91 -114
  39. package/_Build/vue/modules/AuthModule/js/store.js +23 -6
  40. package/_Build/vue/modules/AuthModule/routes/PCompanies/columns.js +268 -0
  41. package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +213 -0
  42. package/_Build/vue/modules/AuthModule/routes/PIntegrations/columns.js +58 -0
  43. package/_Build/vue/modules/AuthModule/routes/PIntegrations/resource.js +79 -0
  44. package/_Build/vue/modules/AuthModule/routes/PTeams/columns.js +78 -0
  45. package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +251 -0
  46. package/_Build/vue/modules/AuthModule/routes/PUsers/SetPasswordAction.vue +51 -0
  47. package/_Build/vue/modules/AuthModule/routes/PUsers/SetPasswordDialog.vue +138 -0
  48. package/_Build/vue/modules/AuthModule/routes/PUsers/columns.js +349 -0
  49. package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +239 -0
  50. package/_Build/vue/modules/AuthModule/routes/account-exists.vue +2 -2
  51. package/_Build/vue/modules/AuthModule/routes/change-password.vue +28 -32
  52. package/_Build/vue/modules/AuthModule/routes/container.vue +2 -11
  53. package/_Build/vue/modules/AuthModule/routes/expired-reset.vue +4 -4
  54. package/_Build/vue/modules/AuthModule/routes/expired-verification.vue +10 -9
  55. package/_Build/vue/modules/AuthModule/routes/force-reset.vue +44 -58
  56. package/_Build/vue/modules/AuthModule/routes/forgot.vue +10 -5
  57. package/_Build/vue/modules/AuthModule/routes/login.vue +12 -19
  58. package/_Build/vue/modules/AuthModule/routes/logincallback.vue +1 -3
  59. package/_Build/vue/modules/AuthModule/routes/loginsso.vue +14 -10
  60. package/_Build/vue/modules/AuthModule/routes/logout.vue +14 -5
  61. package/_Build/vue/modules/AuthModule/routes/logoutheadless.vue +16 -5
  62. package/_Build/vue/modules/AuthModule/routes/register.vue +24 -28
  63. package/_Build/vue/modules/AuthModule/routes/reset.vue +20 -14
  64. package/_Build/vue/modules/AuthModule/routes/success-forgot.vue +14 -8
  65. package/_Build/vue/modules/AuthModule/routes/success-reset.vue +2 -2
  66. package/_Build/vue/modules/AuthModule/routes/success-verify.vue +1 -3
  67. package/_Build/vue/modules/AuthModule/routes/verify.vue +11 -14
  68. package/_Build/vue/modules/resource/Children/create.vue +99 -0
  69. package/_Build/vue/modules/resource/Children/edit.vue +124 -0
  70. package/_Build/vue/modules/resource/Children/index.vue +42 -0
  71. package/_Build/vue/modules/resource/Children/partials/form.vue +111 -0
  72. package/_Build/vue/modules/resource/Children/show.vue +170 -0
  73. package/_Build/vue/modules/resource/index.js +562 -0
  74. package/_Build/vue/modules/resource/parent.vue +63 -0
  75. package/_Build/vue/modules/resource/trashable.js +104 -0
  76. package/_base.scss +0 -1
  77. package/_defaults.scss +2 -2
  78. package/components/_auth.scss +19 -61
  79. package/components/_datepicker.scss +1 -0
  80. package/components/_descriptions.scss +2 -0
  81. package/components/_footer.scss +1 -0
  82. package/components/_form.scss +18 -0
  83. package/components/_header.scss +3 -27
  84. package/components/_layout.scss +56 -0
  85. package/components/_menu.scss +0 -5
  86. package/components/_sidebar.scss +12 -27
  87. package/components/_table.scss +3 -0
  88. package/components/_token-display.scss +41 -0
  89. package/components/_wysiwyg2.scss +10 -0
  90. package/general.scss +1 -0
  91. package/index.js +31 -1
  92. package/package.json +7 -4
  93. package/_Build/vue/components/layout/sideBar.vue +0 -25
  94. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/Upload/upload.vue +0 -259
  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 -181
  99. package/_Build/vue/modules/AuthModule/adminRoutes/PCompanies/Children/show.vue +0 -266
  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 -173
  105. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/Children/show.vue +0 -123
  106. package/_Build/vue/modules/AuthModule/adminRoutes/PUsers/parent.vue +0 -36
  107. package/components/_input.scss +0 -0
  108. /package/_Build/vue/{modules/AuthModule/components → components/layout}/AuthModal.vue +0 -0
  109. /package/_Build/vue/{modules/AuthModule/components → components/layout}/Chip.vue +0 -0
  110. /package/_Build/vue/{modules/AuthModule/components/VPasswordValidation.vue → components/layout/PasswordValidation.vue} +0 -0
  111. /package/_Build/vue/{modules/AuthModule/components/VRoleLegend.vue → components/layout/RoleLegend.vue} +0 -0
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <VMenu>
3
+ <template v-for="(link, lkey) in links" :key="lkey">
4
+ <MenuItem v-if="!link.children" :index="resolveHref(link.href)">
5
+ <router-link :to="link.href">
6
+ <GIcon
7
+ class="icon icon--0.5"
8
+ :name="link.icon"
9
+ asis
10
+ embed
11
+ />
12
+ <span>{{ link.title }}</span>
13
+ </router-link>
14
+ </MenuItem>
15
+ <SubMenu v-else :id="lkey" :index="lkey">
16
+ <template #title>
17
+ <GIcon
18
+ class="icon icon--0.5"
19
+ :name="link.icon"
20
+ asis
21
+ embed
22
+ />
23
+ <span>{{ link.title }}</span>
24
+ </template>
25
+ <MenuItem
26
+ v-for="(child, cindex) in link.children"
27
+ :key="cindex"
28
+ :index="lkey + '-1-' + cindex"
29
+ >
30
+ <router-link :to="child.href">
31
+ <span>{{ child.title }}</span>
32
+ </router-link>
33
+ </MenuItem>
34
+ </SubMenu>
35
+ </template>
36
+ </VMenu>
37
+ </template>
38
+
39
+ <script>
40
+ export default {
41
+ name: "Navigation",
42
+
43
+ components: {
44
+ VMenu: require("../navigation/Menu.vue").default,
45
+ MenuItem: require("../navigation/MenuItem.vue").default,
46
+ SubMenu: require("../navigation/SubMenu.vue").default,
47
+ },
48
+
49
+ methods: {
50
+ resolveHref(href) {
51
+ return this.$router.resolve(href).path;
52
+ },
53
+ },
54
+
55
+ props: {
56
+ links: {
57
+ type: Array,
58
+ default: () => [
59
+ {
60
+ title: "Home",
61
+ href: { name: "index" },
62
+ icon: "icon-home",
63
+ },
64
+ {
65
+ title: "Companies",
66
+ href: { name: "companies.index" },
67
+ icon: "icon-cases",
68
+ },
69
+ {
70
+ title: "Users",
71
+ href: { name: "users.index" },
72
+ icon: "icon-user",
73
+ },
74
+ {
75
+ title: "Utilities",
76
+ href: { name: "index" },
77
+ icon: "icon-utility",
78
+ },
79
+ ],
80
+ },
81
+ },
82
+ };
83
+ </script>
@@ -1,28 +1,34 @@
1
1
  <template>
2
- <div class="grid justify-between">
3
- <div class="grid__4/6 flex justify-start">
2
+ <div class="flex flex-wrap items-start gap" style="row-gap: 16px">
3
+ <div class="flex justify-start items-center">
4
4
  <span v-if="icon">
5
5
  <div
6
6
  class="p-1.5 mr-2 border-radius border border-solid border-muted flex items-center justify-center"
7
7
  >
8
- <GIcon class="icon--3 fill-1" :name="icon" embed artboard />
8
+ <GIcon
9
+ class="fill-1 icon--0.5"
10
+ :name="icon"
11
+ embed
12
+ artboard
13
+ />
9
14
  </div>
10
15
  </span>
11
16
 
12
17
  <h2 class="m-0 font-500 text-secondary">{{ title }}</h2>
13
18
  </div>
14
19
 
15
- <div class="grid__2/6 flex gap justify-end items-start">
16
- <div class="flex gap items-center">
17
- <slot />
18
- </div>
20
+ <div
21
+ class="flex flex-wrap gap items-center justify-end"
22
+ style="margin-left: auto"
23
+ >
24
+ <slot />
19
25
  </div>
20
26
  </div>
21
27
  </template>
22
28
 
23
29
  <script>
24
30
  export default {
25
- name: "VShowPageHeader",
31
+ name: "PageHeader",
26
32
 
27
33
  props: {
28
34
  icon: {
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <div class="vel-sidebar" :class="{ active: active }">
3
+ <div class="vel-sidebar__inner">
4
+ <div class="vel-sidebar__top">
5
+ <slot name="navigation" />
6
+ </div>
7
+ <div class="vel-sidebar__bottom">
8
+ <button class="vel-sidebar__button" @click="active = !active">
9
+ <slot name="expand"> > </slot>
10
+ </button>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ export default {
18
+ name: "SideBar",
19
+
20
+ data() {
21
+ return {
22
+ active: true,
23
+ };
24
+ },
25
+ };
26
+ </script>
@@ -2,6 +2,7 @@
2
2
  <el-table
3
3
  :data="$props.data"
4
4
  :height="fixedHeight ? 762 : undefined"
5
+ :row-class-name="rowClassName"
5
6
  style="width: 100%"
6
7
  @sort-change="handleSort"
7
8
  >
@@ -13,24 +14,25 @@
13
14
  <el-table-column
14
15
  :width="item.width ?? 'auto'"
15
16
  :sortable="!!item.sortable ? 'custom' : false"
16
- :label="item.label"
17
+ :label="
18
+ item.label ||
19
+ item.key[0].toUpperCase() + item.key.slice(1)
20
+ "
17
21
  :prop="item.key"
18
22
  :show-overflow-tooltip="true"
19
23
  >
20
24
  <!-- Support a custom render function -->
21
25
  <template v-if="item.render" #default="scope">
22
- {{ item.render(scope.row) }}
23
- </template>
24
-
25
- <!-- Support module passed (as a raw component or :is property) -->
26
- <template v-else-if="item.component" #default="scope">
27
26
  <component
28
27
  :is="
29
- item.component.is
30
- ? item.component.is(scope.row)
31
- : item.component.module(scope.row)
28
+ item.render(
29
+ {
30
+ model: scope.row,
31
+ ...additionalInfo,
32
+ },
33
+ this,
34
+ )
32
35
  "
33
- v-bind="item.component.props(scope.row)"
34
36
  />
35
37
  </template>
36
38
  </el-table-column>
@@ -68,7 +70,7 @@
68
70
 
69
71
  <script>
70
72
  import { ElTable, ElTableColumn } from "element-plus";
71
- import VelButton from "../../../components/basic/Button.vue";
73
+ import VelButton from "../basic/Button.vue";
72
74
 
73
75
  export default {
74
76
  name: "VTable",
@@ -79,6 +81,12 @@ export default {
79
81
  VelButton,
80
82
  },
81
83
 
84
+ inject: {
85
+ additionalInfo: {
86
+ default: () => ({}),
87
+ },
88
+ },
89
+
82
90
  props: {
83
91
  data: {
84
92
  type: [Array, Object],
@@ -124,8 +132,12 @@ export default {
124
132
  type: Boolean,
125
133
  default: true,
126
134
  },
135
+ rowClassName: {
136
+ type: [Function, String],
137
+ default: undefined,
138
+ },
127
139
  },
128
- emits: ["sort"],
140
+ emits: ["sort", "reload"],
129
141
 
130
142
  methods: {
131
143
  handleSort(data) {
@@ -25,19 +25,23 @@
25
25
  @update:model-value="handleSearch"
26
26
  >
27
27
  <template #prepend
28
- ><GIcon embed asis name="icon-search"
28
+ ><GIcon
29
+ embed
30
+ asis
31
+ name="icon-search"
32
+ class="icon--0.5"
29
33
  /></template>
30
34
  </VelBasic>
31
35
  <slot v-if="displayActions" name="table-action">
32
36
  <VelButton
33
- v-if="displayEditAction"
37
+ v-if="displayCreateAction"
34
38
  size="large"
35
39
  type="primary"
36
40
  tag="a"
37
41
  class="ml-2"
38
42
  @click="
39
43
  $router.push({
40
- name: `${jsonData.pageLink}.create`,
44
+ name: `${jsonData.slug}.create`,
41
45
  })
42
46
  "
43
47
  >
@@ -45,7 +49,7 @@
45
49
  name="icon-plus"
46
50
  embed
47
51
  asis
48
- class="fill-0 mr-0.5"
52
+ class="fill-0 icon--0.5 mr-0.5"
49
53
  />
50
54
  Create new {{ jsonData.label }}
51
55
  </VelButton>
@@ -54,31 +58,33 @@
54
58
  </slot>
55
59
  </div>
56
60
  <div class="bg-0 p-0.5 box-shadow-1 border-r-4">
57
- <VTable
61
+ <VelTable
58
62
  :data="table_data"
59
63
  :structure="jsonData.tableStructure"
60
64
  :label="jsonData.label"
61
65
  :over-write-id="jsonData.overWriteId"
62
66
  :fixed-height="fixedHeight"
67
+ :row-class-name="jsonData.rowClassName"
63
68
  :target-action="
64
69
  (item) => ({
65
- name: `${jsonData.pageLink}.show`,
66
- params: { id: item.id },
70
+ name: `${jsonData.slug}.show`,
71
+ params: { [idKey]: item.id },
67
72
  })
68
73
  "
69
74
  :edit-action="
70
75
  (item) => ({
71
- name: `${jsonData.pageLink}.edit`,
72
- params: { id: item.id },
76
+ name: `${jsonData.slug}.edit`,
77
+ params: { [idKey]: item.id },
73
78
  })
74
79
  "
75
80
  :display-actions="displayActions"
76
81
  :display-show-action="displayShowAction"
77
82
  :display-edit-action="displayEditAction"
78
83
  @sort="handleSort"
84
+ @reload="reload"
79
85
  >
80
86
  <slot name="table-content"></slot>
81
- </VTable>
87
+ </VelTable>
82
88
 
83
89
  <div class="flex justify-center items-center py-2">
84
90
  <el-pagination
@@ -99,16 +105,17 @@
99
105
 
100
106
  <script>
101
107
  import axios from "axios";
108
+ import { debounce } from "lodash";
102
109
  import { ElPagination } from "element-plus";
103
- import VelButton from "../../../components/basic/Button.vue";
104
- import VelBasic from "../../../components/form/basic.vue";
105
- import VelSpinner from "../../../components/form/Spinner.vue";
110
+ import VelButton from "../basic/Button.vue";
111
+ import VelBasic from "../form/basic.vue";
112
+ import VelSpinner from "../form/Spinner.vue";
106
113
 
107
114
  export default {
108
- name: "VTableSorter",
115
+ name: "TableSorter",
109
116
 
110
117
  components: {
111
- VTable: require("./VTable.vue").default,
118
+ VelTable: require("./Table.vue").default,
112
119
  VelButton,
113
120
  VelBasic,
114
121
  ElPagination,
@@ -124,14 +131,10 @@ export default {
124
131
  default: true,
125
132
  type: Boolean,
126
133
  },
127
- api: {
128
- required: true,
129
- type: String,
130
- },
131
- defaults: {
134
+ apiParams: {
132
135
  required: false,
133
- type: String,
134
- default: "",
136
+ type: Object,
137
+ default: () => ({}),
135
138
  },
136
139
  displayActions: {
137
140
  type: Boolean,
@@ -141,44 +144,79 @@ export default {
141
144
  type: Boolean,
142
145
  default: true,
143
146
  },
147
+ displayCreateAction: {
148
+ type: Boolean,
149
+ default: true,
150
+ },
144
151
  displayEditAction: {
145
152
  type: Boolean,
146
153
  default: true,
147
154
  },
155
+ idKey: {
156
+ type: String,
157
+ default: "id",
158
+ },
148
159
  },
149
160
 
150
161
  data() {
151
162
  return {
152
163
  search: null,
153
164
  sort: "-id",
154
- query: [],
165
+ query: {},
155
166
  table_data: [],
156
167
  table_meta: null,
168
+ _abortController: null,
157
169
  };
158
170
  },
159
171
 
172
+ created() {
173
+ this.debouncedSearch = debounce(this._executeSearch, 300);
174
+ },
175
+
176
+ beforeUnmount() {
177
+ this.debouncedSearch.cancel();
178
+ this._abortController?.abort();
179
+ },
180
+
160
181
  mounted() {
161
182
  this.sort = this.jsonData.defaultSort || "-id";
162
183
  this.fetchData({ page: 1 }).then((data) => {
163
- this.table_data = data.data;
164
- this.table_meta = data.meta;
184
+ if (data) {
185
+ this.table_data = data.data;
186
+ this.table_meta = data.meta;
165
187
 
166
- this.table_curr_page = this.table_meta.current_page;
188
+ this.table_curr_page = this.table_meta.current_page;
189
+ }
167
190
  });
168
191
  },
169
192
 
170
193
  methods: {
194
+ reload() {
195
+ this.fetchData({ page: this.table_meta.current_page }).then(
196
+ (data) => {
197
+ if (data) {
198
+ this.table_data = data.data;
199
+ this.table_meta = data.meta;
200
+ }
201
+ },
202
+ );
203
+ },
171
204
  handleSearch(data) {
172
205
  if (data === null || data.length < 3) {
173
- this.query = [];
206
+ this.query = {};
174
207
  } else {
175
- this.query = [
176
- `filter[${this.$refs.search.$el.dataset.key}]=${data}`,
177
- ];
208
+ this.query = {
209
+ [`filter[${this.$refs.search.$el.dataset.key}]`]: data,
210
+ };
178
211
  }
212
+ this.debouncedSearch();
213
+ },
214
+ _executeSearch() {
179
215
  this.fetchData({}).then((data) => {
180
- this.table_data = data.data;
181
- this.table_meta = data.meta;
216
+ if (data) {
217
+ this.table_data = data.data;
218
+ this.table_meta = data.meta;
219
+ }
182
220
  });
183
221
  },
184
222
  handleSort(data) {
@@ -189,27 +227,31 @@ export default {
189
227
  data.order === "ascending" ? data.prop : "-" + data.prop;
190
228
  }
191
229
  this.fetchData({}).then((data) => {
192
- this.table_data = data.data;
193
- this.table_meta = data.meta;
230
+ if (data) {
231
+ this.table_data = data.data;
232
+ this.table_meta = data.meta;
233
+ }
194
234
  });
195
235
  },
196
236
 
197
237
  fetchData: function ({ page = "1" }) {
198
- const mergedQuery = [
199
- ...this.query,
200
- this.defaults,
201
- `sort=${this.sort}`,
202
- `page=${page}`,
203
- ];
204
-
205
- const query = mergedQuery.join("&");
238
+ this._abortController?.abort();
239
+ this._abortController = new AbortController();
206
240
 
207
241
  return axios
208
- .get(`/api/${this.$props.api}${query ? "?" + query : ""}`)
209
- .then((res) => {
210
- return res.data;
242
+ .get(`${this.$props.jsonData.api}`, {
243
+ params: {
244
+ sort: this.sort,
245
+ page: page,
246
+ ...this.query,
247
+ ...this.apiParams,
248
+ },
249
+ signal: this._abortController.signal,
211
250
  })
212
- .catch(this.$root.errors);
251
+ .then((res) => res.data)
252
+ .catch((err) => {
253
+ if (!axios.isCancel(err)) console.log(err);
254
+ });
213
255
  },
214
256
 
215
257
  getStatusLabel(status) {
@@ -225,8 +267,10 @@ export default {
225
267
 
226
268
  handleCurrentPageChange(val) {
227
269
  this.fetchData({ page: val }).then((data) => {
228
- this.table_data = data.data;
229
- this.table_meta = data.meta;
270
+ if (data) {
271
+ this.table_data = data.data;
272
+ this.table_meta = data.meta;
273
+ }
230
274
  });
231
275
  },
232
276
 
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <el-dialog
3
+ :model-value="true"
4
+ title="Token Created"
5
+ width="560px"
6
+ class="token-display"
7
+ :close-on-click-modal="false"
8
+ :close-on-press-escape="false"
9
+ :show-close="false"
10
+ >
11
+ <p class="token-display__warning">
12
+ <strong>The token below will not be shown again.</strong> Ensure
13
+ you've taken a copy before closing this window.
14
+ </p>
15
+
16
+ <div class="token-display__block">
17
+ <div class="token-display__header">
18
+ <span class="token-display__label">Bearer Token</span>
19
+ <el-button size="small" plain @click="copy">
20
+ {{ copied ? "Copied ✓" : "Copy" }}
21
+ </el-button>
22
+ </div>
23
+ <pre class="token-display__value">{{ token }}</pre>
24
+ </div>
25
+
26
+ <template #footer>
27
+ <el-button type="primary" @click="$emit('close')">Done</el-button>
28
+ </template>
29
+ </el-dialog>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref } from "vue";
34
+ import { ElDialog, ElButton } from "element-plus";
35
+
36
+ const props = defineProps({
37
+ token: {
38
+ type: String,
39
+ required: true,
40
+ },
41
+ });
42
+
43
+ defineEmits(["close"]);
44
+
45
+ const copied = ref(false);
46
+
47
+ async function copy() {
48
+ await navigator.clipboard.writeText(props.token);
49
+ copied.value = true;
50
+ setTimeout(() => (copied.value = false), 2000);
51
+ }
52
+ </script>
@@ -6,7 +6,7 @@
6
6
 
7
7
  <script>
8
8
  export default {
9
- name: "VPageTitle",
9
+ name: "PageTitle",
10
10
 
11
11
  props: {
12
12
  title: {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <el-menu class="vel-menu">
2
+ <el-menu class="vel-menu" :default-active="activeRoute">
3
3
  <slot />
4
4
  </el-menu>
5
5
  </template>
@@ -10,5 +10,10 @@ export default {
10
10
  components: {
11
11
  ElMenu,
12
12
  },
13
+ computed: {
14
+ activeRoute() {
15
+ return this.$route.path.replace(/\/$/, "") || "/";
16
+ },
17
+ },
13
18
  };
14
19
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <el-menu-item :index="index" class="vel-menu-item" v-bind="$props">
2
+ <el-menu-item class="vel-menu-item" v-bind="$props" :index="`${index}`">
3
3
  <template #title>
4
4
  <slot name="title" />
5
5
  </template>
@@ -15,6 +15,11 @@ export default {
15
15
  components: {
16
16
  ElMenuItem,
17
17
  },
18
- props: ["index"],
18
+ props: {
19
+ index: {
20
+ type: [String, Number],
21
+ required: true,
22
+ },
23
+ },
19
24
  };
20
25
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <el-sub-menu :index="index" v-bind="$props">
2
+ <el-sub-menu v-bind="$props" :index="`${index}`">
3
3
  <template #title>
4
4
  <slot name="title" />
5
5
  </template>
@@ -15,6 +15,11 @@ export default {
15
15
  components: {
16
16
  ElSubMenu,
17
17
  },
18
- props: ["index"],
18
+ props: {
19
+ index: {
20
+ type: [String, Number],
21
+ required: true,
22
+ },
23
+ },
19
24
  };
20
25
  </script>
@@ -1,4 +1,21 @@
1
1
  import axios from "axios";
2
+ import debounce from "lodash/debounce";
3
+
4
+ import { ElNotification } from "element-plus";
5
+
6
+ const displayErrorNotification = debounce(async function errors(e) {
7
+ if (e.response && !e.response.data.errors) {
8
+ ElNotification.error({
9
+ title: "Error",
10
+ message:
11
+ e.response.data.message ||
12
+ `${e.response.status}: ${
13
+ e.response.statusText || "Please try again later!"
14
+ }`,
15
+ duration: 10000,
16
+ });
17
+ }
18
+ }, 250);
2
19
 
3
20
  function setAxiosDefaults(baseUrl, router) {
4
21
  axios.defaults.baseURL = baseUrl;
@@ -12,7 +29,8 @@ function setAxiosDefaults(baseUrl, router) {
12
29
  axios.interceptors.response.use(null, (error) => {
13
30
  if (error.response) {
14
31
  if (
15
- error.response.status === 401 &&
32
+ (error.response.status === 401 ||
33
+ error.response.status === 419) &&
16
34
  router.currentRoute.value.name !== "auth.logout"
17
35
  ) {
18
36
  router.push({
@@ -25,6 +43,8 @@ function setAxiosDefaults(baseUrl, router) {
25
43
  }
26
44
  }
27
45
 
46
+ displayErrorNotification(error);
47
+
28
48
  return Promise.reject(error);
29
49
  });
30
50