@fishawack/lab-velocity 2.0.0-beta.40 → 2.0.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/_Build/js/libs/build-id.js +14 -0
- package/_Build/js/libs/filters.js +36 -0
- package/_Build/js/libs/globals.js +7 -0
- package/_Build/js/libs/router.js +22 -0
- package/_Build/js/libs/routes.js +29 -0
- package/_Build/js/libs/store.js +21 -0
- package/_Build/js/libs/utility.js +161 -0
- package/_Build/vue/components/form/Avatar.vue +86 -0
- package/_Build/vue/components/layout/Audit.vue +124 -56
- package/_Build/vue/components/layout/Layout.vue +19 -1
- package/_Build/vue/components/layout/TableSorter.vue +42 -12
- package/_Build/vue/modules/AuthModule/js/router.js +20 -36
- package/_Build/vue/modules/AuthModule/routes/PCompanies/columns.js +268 -0
- package/_Build/vue/modules/AuthModule/routes/PCompanies/resource.js +173 -232
- package/_Build/vue/modules/AuthModule/routes/PIntegrations/resource.js +122 -0
- package/_Build/vue/modules/AuthModule/routes/PTeams/resource.js +1 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/columns.js +349 -0
- package/_Build/vue/modules/AuthModule/routes/PUsers/resource.js +142 -262
- package/_Build/vue/modules/resource/Children/create.vue +2 -2
- package/_Build/vue/modules/resource/Children/edit.vue +2 -2
- package/_Build/vue/modules/resource/Children/partials/form.vue +71 -21
- package/_Build/vue/modules/resource/Children/show.vue +24 -2
- package/_Build/vue/modules/resource/index.js +12 -4
- package/components/_form.scss +18 -0
- package/components/_menu.scss +0 -5
- package/index.js +16 -0
- package/package.json +3 -1
- package/_Build/vue/modules/AuthModule/routes/PCompanies/form.vue +0 -205
- package/_Build/vue/modules/AuthModule/routes/PUsers/form.vue +0 -193
package/README.md
CHANGED
|
@@ -187,6 +187,7 @@ There are two different set of sass imports for the admin and the frontend route
|
|
|
187
187
|
@import "@fishawack/lab-velocity/components/sidebar";
|
|
188
188
|
@import "@fishawack/lab-velocity/components/menu";
|
|
189
189
|
@import "@fishawack/lab-velocity/components/layout";
|
|
190
|
+
@import "@fishawack/lab-velocity/components/descriptions";
|
|
190
191
|
@import "element-plus/theme-chalk/el-tabs";
|
|
191
192
|
@import "element-plus/theme-chalk/el-tab-pane";
|
|
192
193
|
```
|
|
@@ -218,8 +219,9 @@ Ensure Content has Velocity pulled in & copy out the svg folder contents into th
|
|
|
218
219
|
|
|
219
220
|
```json
|
|
220
221
|
{
|
|
221
|
-
"
|
|
222
|
-
"location": "
|
|
222
|
+
"aws-s3": "fishawack",
|
|
223
|
+
"location": "fw-auto-content/lab-velocity",
|
|
224
|
+
"key": "fw-s3-lab-velocity"
|
|
223
225
|
}
|
|
224
226
|
```
|
|
225
227
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
if (process.env.NODE_ENV === "production") {
|
|
2
|
+
let uuid = document.documentElement.dataset.build;
|
|
3
|
+
let last = window.localStorage.getItem(`${process.env.REPO_NAME}-build-id`);
|
|
4
|
+
|
|
5
|
+
if (!last) {
|
|
6
|
+
console.log("no build detected - setting");
|
|
7
|
+
window.localStorage.clear();
|
|
8
|
+
window.localStorage.setItem(`${process.env.REPO_NAME}-build-id`, uuid);
|
|
9
|
+
} else if (uuid !== last) {
|
|
10
|
+
console.log("new build detected - resetting storage");
|
|
11
|
+
window.localStorage.clear();
|
|
12
|
+
window.localStorage.setItem(`${process.env.REPO_NAME}-build-id`, uuid);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import calendar from "dayjs/plugin/calendar";
|
|
3
|
+
import localizedFormat from "dayjs/plugin/localizedFormat";
|
|
4
|
+
import "dayjs/locale/en-gb";
|
|
5
|
+
|
|
6
|
+
dayjs.extend(calendar);
|
|
7
|
+
dayjs.extend(localizedFormat);
|
|
8
|
+
dayjs.locale(navigator.language.toLowerCase());
|
|
9
|
+
|
|
10
|
+
export function ucfirst(value) {
|
|
11
|
+
if (!value) return "";
|
|
12
|
+
value = value.toString();
|
|
13
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function calendarFormat(value) {
|
|
17
|
+
return !value
|
|
18
|
+
? ""
|
|
19
|
+
: dayjs(value).calendar(null, {
|
|
20
|
+
sameElse: "DD/MM/YYYY",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function dateFormat(value) {
|
|
25
|
+
return !value ? "" : dayjs(value).format("LLL");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
install(Vue) {
|
|
30
|
+
Vue.config.globalProperties.$filters = {
|
|
31
|
+
ucfirst,
|
|
32
|
+
calendarFormat,
|
|
33
|
+
dateFormat,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRouter, createWebHistory } from "vue-router";
|
|
2
|
+
import { Auth } from "../../../index.js";
|
|
3
|
+
|
|
4
|
+
const router = createRouter({
|
|
5
|
+
history: createWebHistory(),
|
|
6
|
+
linkExactActiveClass: "active",
|
|
7
|
+
base: process.env.BASE_URL,
|
|
8
|
+
routes: require("./routes.js")(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
router.beforeEach((to, from, next) => {
|
|
12
|
+
// Enforce routes have trailing forward slash
|
|
13
|
+
if (to.path.substr(-1) != "/") {
|
|
14
|
+
return next({ path: `${to.path}/`, query: to.query, hash: to.hash });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return next();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
Auth.Router.beforeEach(router);
|
|
21
|
+
|
|
22
|
+
export default router;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = (node) => [
|
|
4
|
+
{
|
|
5
|
+
path: "/",
|
|
6
|
+
component: node ? "" : require("../../vue/routes/PIndex.vue").default,
|
|
7
|
+
name: "index",
|
|
8
|
+
meta: {
|
|
9
|
+
guest: true,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
path: "/404",
|
|
14
|
+
component: node ? "" : require("../../vue/routes/P404.vue").default,
|
|
15
|
+
meta: {
|
|
16
|
+
guest: true,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
path: "/index.html",
|
|
21
|
+
redirect: "/",
|
|
22
|
+
prerender: false,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
path: "/:pathMatch(.*)*",
|
|
26
|
+
redirect: "/404",
|
|
27
|
+
prerender: false,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createStore } from "vuex";
|
|
2
|
+
import VuexPersistedState from "vuex-persistedstate";
|
|
3
|
+
import { Auth } from "../../../index.js";
|
|
4
|
+
|
|
5
|
+
const store = createStore({
|
|
6
|
+
modules: {
|
|
7
|
+
auth: Auth.Store,
|
|
8
|
+
},
|
|
9
|
+
plugins: [
|
|
10
|
+
VuexPersistedState({
|
|
11
|
+
key: document.title,
|
|
12
|
+
paths: ["auth"],
|
|
13
|
+
}),
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
state: {},
|
|
17
|
+
|
|
18
|
+
mutations: {},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export default store;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
export function eachNode(nodes, cb) {
|
|
2
|
+
nodes = document.querySelectorAll(nodes);
|
|
3
|
+
|
|
4
|
+
for (var i = 0, len = nodes.length; i < len; i++) {
|
|
5
|
+
cb(nodes[i], i);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function parse_query_string(query) {
|
|
10
|
+
var vars = query.split("&");
|
|
11
|
+
var query_string = {};
|
|
12
|
+
for (var i = 0; i < vars.length; i++) {
|
|
13
|
+
var pair = vars[i].split("=");
|
|
14
|
+
// If first entry with this name
|
|
15
|
+
if (typeof query_string[pair[0]] === "undefined") {
|
|
16
|
+
query_string[pair[0]] = decodeURIComponent(pair[1]);
|
|
17
|
+
// If second entry with this name
|
|
18
|
+
} else if (typeof query_string[pair[0]] === "string") {
|
|
19
|
+
var arr = [query_string[pair[0]], decodeURIComponent(pair[1])];
|
|
20
|
+
query_string[pair[0]] = arr;
|
|
21
|
+
// If third or later entry with this name
|
|
22
|
+
} else {
|
|
23
|
+
query_string[pair[0]].push(decodeURIComponent(pair[1]));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return query_string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function load(path, mimetype, pages, index, arr) {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
index = index || 1;
|
|
32
|
+
|
|
33
|
+
var xobj = new XMLHttpRequest();
|
|
34
|
+
if (mimetype) {
|
|
35
|
+
xobj.overrideMimeType(mimetype);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
xobj.open(
|
|
39
|
+
"GET",
|
|
40
|
+
pages ? `${path}?per_page=100&page=${index}` : path,
|
|
41
|
+
true,
|
|
42
|
+
);
|
|
43
|
+
xobj.onreadystatechange = function () {
|
|
44
|
+
if (
|
|
45
|
+
xobj.readyState === 4 &&
|
|
46
|
+
(+xobj.status === 200 || +xobj.status === 0)
|
|
47
|
+
) {
|
|
48
|
+
var data = JSON.parse(xobj.responseText);
|
|
49
|
+
|
|
50
|
+
if (!pages) {
|
|
51
|
+
resolve(data);
|
|
52
|
+
} else {
|
|
53
|
+
var current = +xobj.getResponseHeader("x-wp-totalpages");
|
|
54
|
+
|
|
55
|
+
if (!arr) {
|
|
56
|
+
arr = data || [];
|
|
57
|
+
} else {
|
|
58
|
+
arr = arr.concat(data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (current && current !== index) {
|
|
62
|
+
load(path, mimetype, pages, ++index, arr).then((res) =>
|
|
63
|
+
resolve(res),
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
resolve(arr);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
xobj.send(null);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function classList(el) {
|
|
76
|
+
var list = el.classList;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
toggle: function (c) {
|
|
80
|
+
list.toggle(c);
|
|
81
|
+
return this;
|
|
82
|
+
},
|
|
83
|
+
add: function (c) {
|
|
84
|
+
list.add(c);
|
|
85
|
+
return this;
|
|
86
|
+
},
|
|
87
|
+
remove: function (c) {
|
|
88
|
+
list.remove(c);
|
|
89
|
+
return this;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var blueprints = {};
|
|
95
|
+
export function blueprint(selector, array, cb, root, node) {
|
|
96
|
+
var nodes;
|
|
97
|
+
|
|
98
|
+
if (!node) {
|
|
99
|
+
nodes = (root || document).querySelectorAll(selector);
|
|
100
|
+
} else {
|
|
101
|
+
nodes = [node];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var blueprint;
|
|
105
|
+
|
|
106
|
+
if (blueprints[selector]) {
|
|
107
|
+
blueprint = blueprints[selector];
|
|
108
|
+
} else {
|
|
109
|
+
blueprint = nodes[0].children[0];
|
|
110
|
+
blueprint.classList.remove("ut-hide");
|
|
111
|
+
blueprints[selector] = blueprint;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
var docFrag = document.createDocumentFragment();
|
|
115
|
+
|
|
116
|
+
array.forEach(function (d, i, arr) {
|
|
117
|
+
var item = blueprint.cloneNode(true);
|
|
118
|
+
|
|
119
|
+
cb(item, d, i, arr);
|
|
120
|
+
|
|
121
|
+
docFrag.appendChild(item);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
for (var i = nodes.length; i--; ) {
|
|
125
|
+
nodes[i].innerHTML = "";
|
|
126
|
+
|
|
127
|
+
nodes[i].appendChild(docFrag);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function styleguide() {
|
|
132
|
+
let colors = [].slice
|
|
133
|
+
.call(document.styleSheets[0].cssRules)
|
|
134
|
+
.filter((d) => d.selectorText && d.selectorText.includes(".color-"))
|
|
135
|
+
.map((d) => d.selectorText);
|
|
136
|
+
|
|
137
|
+
let length = 0;
|
|
138
|
+
/* jshint ignore:start */
|
|
139
|
+
while (colors.find((d) => d === `.color-${length}`)) {
|
|
140
|
+
length++;
|
|
141
|
+
}
|
|
142
|
+
/* jshint ignore:end */
|
|
143
|
+
eachNode(".js-styleguide-dynamic", (node) => {
|
|
144
|
+
let name = node.dataset.styleguideDynamic;
|
|
145
|
+
blueprint(
|
|
146
|
+
name,
|
|
147
|
+
Array(length).fill(0),
|
|
148
|
+
(item, d, i) => {
|
|
149
|
+
let text = item.querySelector(".js-styleguide-index");
|
|
150
|
+
if (text) {
|
|
151
|
+
text.innerText = i;
|
|
152
|
+
}
|
|
153
|
+
classList(item.querySelector(`.${name}`) || item)
|
|
154
|
+
.remove(name)
|
|
155
|
+
.add(`${name}${i}`);
|
|
156
|
+
},
|
|
157
|
+
null,
|
|
158
|
+
node,
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<XInput v-bind="$props">
|
|
3
|
+
<template #label>
|
|
4
|
+
<slot name="label" />
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<el-upload
|
|
8
|
+
action="#"
|
|
9
|
+
:auto-upload="false"
|
|
10
|
+
:show-file-list="false"
|
|
11
|
+
accept="image/*"
|
|
12
|
+
:on-change="onFileChange"
|
|
13
|
+
>
|
|
14
|
+
<img
|
|
15
|
+
v-if="imgSrc"
|
|
16
|
+
:src="imgSrc"
|
|
17
|
+
style="
|
|
18
|
+
max-width: 150px;
|
|
19
|
+
max-height: 150px;
|
|
20
|
+
display: block;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
margin-bottom: 0.5rem;
|
|
23
|
+
"
|
|
24
|
+
/>
|
|
25
|
+
<el-button v-else type="primary" plain> Upload Avatar </el-button>
|
|
26
|
+
</el-upload>
|
|
27
|
+
<div v-if="content" style="margin-top: 0.5rem">
|
|
28
|
+
<el-button type="danger" size="small" @click="cancel">
|
|
29
|
+
Clear
|
|
30
|
+
</el-button>
|
|
31
|
+
</div>
|
|
32
|
+
</XInput>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import { ElUpload, ElButton } from "element-plus";
|
|
37
|
+
import input from "./input.js";
|
|
38
|
+
import XInput from "./input.vue";
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
mixins: [input],
|
|
42
|
+
|
|
43
|
+
components: { XInput, ElUpload, ElButton },
|
|
44
|
+
|
|
45
|
+
props: {
|
|
46
|
+
...input.props,
|
|
47
|
+
baseClass: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: "vel-basic",
|
|
50
|
+
},
|
|
51
|
+
preview: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: null,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
data() {
|
|
58
|
+
return {
|
|
59
|
+
imgSrc: null,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
mounted() {
|
|
64
|
+
this.imgSrc = this.preview;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
watch: {
|
|
68
|
+
preview(val) {
|
|
69
|
+
if (!this.content) this.imgSrc = val;
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
methods: {
|
|
74
|
+
onFileChange(uploadFile) {
|
|
75
|
+
this.content = uploadFile.raw;
|
|
76
|
+
this.imgSrc = URL.createObjectURL(uploadFile.raw);
|
|
77
|
+
this.handleInput();
|
|
78
|
+
},
|
|
79
|
+
cancel() {
|
|
80
|
+
this.content = null;
|
|
81
|
+
this.imgSrc = this.preview;
|
|
82
|
+
this.handleInput();
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
</script>
|
|
@@ -1,74 +1,142 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
:data="audits"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
<div>
|
|
3
|
+
<el-table :data="audits" v-loading="loading">
|
|
4
|
+
<el-table-column label="Old" :fit="false">
|
|
5
|
+
<template #default="scope">
|
|
6
|
+
<template v-if="scope?.row?.event !== 'created'">
|
|
7
|
+
<p
|
|
8
|
+
:key="key"
|
|
9
|
+
v-for="{ key, value } in formatValues(
|
|
10
|
+
scope?.row?.old_values,
|
|
11
|
+
)"
|
|
12
|
+
class="truncate color-9"
|
|
13
|
+
>
|
|
14
|
+
<strong>{{ ucfirst(key) }}</strong
|
|
15
|
+
><br />{{ value }}
|
|
16
|
+
</p>
|
|
17
|
+
</template>
|
|
18
|
+
</template>
|
|
19
|
+
</el-table-column>
|
|
20
|
+
|
|
21
|
+
<el-table-column label="New" :fit="false">
|
|
22
|
+
<template #default="scope">
|
|
23
|
+
<template v-if="scope?.row?.event === 'created'">
|
|
24
|
+
<span class="color-13">Resource Created</span>
|
|
25
|
+
</template>
|
|
26
|
+
<template v-else>
|
|
27
|
+
<p
|
|
28
|
+
:key="key"
|
|
29
|
+
v-for="{ key, value } in formatValues(
|
|
30
|
+
scope?.row?.new_values,
|
|
31
|
+
)"
|
|
32
|
+
class="truncate"
|
|
33
|
+
>
|
|
34
|
+
<strong>{{ ucfirst(key) }}</strong
|
|
35
|
+
><br />{{ value }}
|
|
36
|
+
</p>
|
|
37
|
+
</template>
|
|
38
|
+
</template>
|
|
39
|
+
</el-table-column>
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<strong>{{ $filters.ucfirst(key) }}</strong
|
|
33
|
-
><br />{{ value }}
|
|
34
|
-
</p>
|
|
35
|
-
</template>
|
|
36
|
-
</el-table-column>
|
|
41
|
+
<el-table-column label="User" :fit="false">
|
|
42
|
+
<template #default="scope">
|
|
43
|
+
<span :title="scope?.row?.user?.email">
|
|
44
|
+
{{ scope?.row?.user?.name || scope?.row?.user?.email }}
|
|
45
|
+
</span>
|
|
46
|
+
</template>
|
|
47
|
+
</el-table-column>
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
<el-table-column label="Date" :fit="false">
|
|
50
|
+
<template #default="scope">
|
|
51
|
+
<span :title="dateFormat(scope?.row?.created_at)">
|
|
52
|
+
{{ calendarFormat(scope?.row?.created_at) }}
|
|
53
|
+
</span>
|
|
54
|
+
</template>
|
|
55
|
+
</el-table-column>
|
|
56
|
+
</el-table>
|
|
39
57
|
|
|
40
|
-
<el-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
<el-pagination
|
|
59
|
+
v-if="meta.last_page > 1"
|
|
60
|
+
v-model:current-page="page"
|
|
61
|
+
layout="prev, pager, next"
|
|
62
|
+
:total="meta.total"
|
|
63
|
+
:page-size="meta.per_page"
|
|
64
|
+
class="mt-3 justify-center"
|
|
65
|
+
@update:current-page="fetchAudits"
|
|
66
|
+
/>
|
|
67
|
+
</div>
|
|
46
68
|
</template>
|
|
47
69
|
|
|
48
70
|
<script>
|
|
49
|
-
import { ElTable, ElTableColumn } from "element-plus";
|
|
71
|
+
import { ElTable, ElTableColumn, ElPagination } from "element-plus";
|
|
72
|
+
import {
|
|
73
|
+
ucfirst,
|
|
74
|
+
calendarFormat,
|
|
75
|
+
dateFormat,
|
|
76
|
+
} from "../../../js/libs/filters.js";
|
|
77
|
+
import axios from "axios";
|
|
50
78
|
|
|
51
79
|
export default {
|
|
52
80
|
components: {
|
|
53
81
|
ElTable,
|
|
54
82
|
ElTableColumn,
|
|
83
|
+
ElPagination,
|
|
55
84
|
},
|
|
56
85
|
|
|
57
|
-
props:
|
|
86
|
+
props: {
|
|
87
|
+
auditableType: {
|
|
88
|
+
type: String,
|
|
89
|
+
required: true,
|
|
90
|
+
},
|
|
91
|
+
auditableId: {
|
|
92
|
+
type: [Number, String],
|
|
93
|
+
required: true,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
data() {
|
|
98
|
+
return {
|
|
99
|
+
audits: [],
|
|
100
|
+
meta: {},
|
|
101
|
+
loading: false,
|
|
102
|
+
page: 1,
|
|
103
|
+
};
|
|
104
|
+
},
|
|
58
105
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.
|
|
106
|
+
mounted() {
|
|
107
|
+
this.fetchAudits();
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
methods: {
|
|
111
|
+
ucfirst,
|
|
112
|
+
calendarFormat,
|
|
113
|
+
dateFormat,
|
|
114
|
+
|
|
115
|
+
formatValues(values) {
|
|
116
|
+
if (!values) return [];
|
|
117
|
+
return Object.entries(values)
|
|
118
|
+
.filter(([key, value]) => value)
|
|
119
|
+
.map(([key, value]) => ({ key, value }));
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
async fetchAudits() {
|
|
123
|
+
this.loading = true;
|
|
124
|
+
try {
|
|
125
|
+
const res = await axios.get("/api/audits", {
|
|
126
|
+
params: {
|
|
127
|
+
"filter[auditable_type]": this.auditableType,
|
|
128
|
+
"filter[auditable_id]": this.auditableId,
|
|
129
|
+
include: "user",
|
|
130
|
+
page: this.page,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
this.audits = res.data.data;
|
|
134
|
+
this.meta = res.data.meta;
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Failed to load audits", err);
|
|
137
|
+
} finally {
|
|
138
|
+
this.loading = false;
|
|
139
|
+
}
|
|
72
140
|
},
|
|
73
141
|
},
|
|
74
142
|
};
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
/>
|
|
12
12
|
</router-link>
|
|
13
13
|
<template #links>
|
|
14
|
-
<div
|
|
14
|
+
<div
|
|
15
|
+
v-if="$store.getters.authenticated"
|
|
16
|
+
class="flex items-center pr"
|
|
17
|
+
>
|
|
15
18
|
<GIcon
|
|
16
19
|
class="icon fill-1 icon--0.5 mr-0.5"
|
|
17
20
|
name="icon-account-circle"
|
|
@@ -20,7 +23,22 @@
|
|
|
20
23
|
/>
|
|
21
24
|
<span>{{ $store?.state?.auth?.user?.name }}</span>
|
|
22
25
|
</div>
|
|
26
|
+
<div class="flex items-center px">
|
|
27
|
+
<router-link
|
|
28
|
+
v-if="$store.getters.authenticated"
|
|
29
|
+
:to="{ name: 'auth.logout' }"
|
|
30
|
+
class="vel-logout"
|
|
31
|
+
>Logout</router-link
|
|
32
|
+
>
|
|
33
|
+
<router-link
|
|
34
|
+
v-else
|
|
35
|
+
:to="{ name: 'auth.login' }"
|
|
36
|
+
class="vel-logout"
|
|
37
|
+
>Login</router-link
|
|
38
|
+
>
|
|
39
|
+
</div>
|
|
23
40
|
<VelButton
|
|
41
|
+
v-if="$root.spaUrl"
|
|
24
42
|
class="ml"
|
|
25
43
|
type="primary"
|
|
26
44
|
tag="a"
|