expressa 1.2.5 → 1.3.0
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/.circleci/config.yml +2 -2
- package/controllers/users.js +43 -43
- package/index.js +1 -6
- package/middleware/permissions.js +53 -53
- package/modules/admin/dist/index.html +1 -1
- package/modules/admin/dist/index.html.gz +0 -0
- package/modules/admin/dist/static/css/{chunk-5cee.9685afb8.css → chunk-5061.ce0e4bdb.css} +0 -0
- package/modules/admin/dist/static/css/{chunk-5cee.9685afb8.css.gz → chunk-5061.ce0e4bdb.css.gz} +0 -0
- package/modules/admin/dist/static/css/chunk-5e50.f67eeaed.css +1 -0
- package/modules/admin/dist/static/css/chunk-5e50.f67eeaed.css.gz +0 -0
- package/modules/admin/dist/static/css/{chunk-621e.f3d0eab6.css → chunk-621e.b826be8d.css} +0 -0
- package/modules/admin/dist/static/css/{chunk-621e.f3d0eab6.css.gz → chunk-621e.b826be8d.css.gz} +0 -0
- package/modules/admin/dist/static/css/chunk-7109.2bd6f37e.css +1 -0
- package/modules/admin/dist/static/css/chunk-7109.2bd6f37e.css.gz +0 -0
- package/modules/admin/dist/static/css/chunk-7f4f.f67eeaed.css +1 -0
- package/modules/admin/dist/static/css/chunk-7f4f.f67eeaed.css.gz +0 -0
- package/modules/admin/dist/static/css/{chunk-bd5f.6ab011ba.css → chunk-bd5f.aefa49d7.css} +0 -0
- package/modules/admin/dist/static/css/{chunk-bd5f.6ab011ba.css.gz → chunk-bd5f.aefa49d7.css.gz} +0 -0
- package/modules/admin/dist/static/css/{chunk-e375.1d849865.css → chunk-e374.025d58bb.css} +0 -0
- package/modules/admin/dist/static/css/{chunk-e375.1d849865.css.gz → chunk-e374.025d58bb.css.gz} +0 -0
- package/modules/admin/dist/static/js/{app.ebe90d64.js → app.cdc00d38.js} +1 -1
- package/modules/admin/dist/static/js/app.cdc00d38.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js +1 -0
- package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js +1 -0
- package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-5e50.6820e69c.js +1 -0
- package/modules/admin/dist/static/js/chunk-5e50.6820e69c.js.gz +0 -0
- package/modules/admin/dist/static/js/{chunk-621e.6fe293e9.js → chunk-621e.ccf42393.js} +0 -0
- package/modules/admin/dist/static/js/{chunk-621e.6fe293e9.js.gz → chunk-621e.ccf42393.js.gz} +0 -0
- package/modules/admin/dist/static/js/chunk-7109.10cb4860.js +1 -0
- package/modules/admin/dist/static/js/chunk-7109.10cb4860.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-7f4f.ae4400a8.js +1 -0
- package/modules/admin/dist/static/js/chunk-7f4f.ae4400a8.js.gz +0 -0
- package/modules/admin/dist/static/js/{chunk-bd5f.af5f2197.js → chunk-bd5f.e9509f10.js} +0 -0
- package/modules/admin/dist/static/js/{chunk-bd5f.af5f2197.js.gz → chunk-bd5f.e9509f10.js.gz} +0 -0
- package/modules/admin/dist/static/js/{chunk-e375.089d85cd.js → chunk-e374.7c87a0dd.js} +1 -1
- package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js.gz +0 -0
- package/modules/admin/package.json +1 -0
- package/modules/admin/src/router/index.js +200 -185
- package/modules/admin/src/views/Endpoints.vue +250 -0
- package/modules/admin/src/views/ListDocuments2.vue +465 -407
- package/package.json +1 -1
- package/modules/admin/dist/static/css/chunk-1dff.39c7634b.css +0 -1
- package/modules/admin/dist/static/css/chunk-1dff.39c7634b.css.gz +0 -0
- package/modules/admin/dist/static/css/chunk-f691.4817ca73.css +0 -1
- package/modules/admin/dist/static/css/chunk-f691.4817ca73.css.gz +0 -0
- package/modules/admin/dist/static/js/app.ebe90d64.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-1dff.1f1c0999.js +0 -1
- package/modules/admin/dist/static/js/chunk-1dff.1f1c0999.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-5cee.a6f0e769.js +0 -1
- package/modules/admin/dist/static/js/chunk-5cee.a6f0e769.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-e375.089d85cd.js.gz +0 -0
- package/modules/admin/dist/static/js/chunk-f691.c0cbf5c1.js +0 -1
- package/modules/admin/dist/static/js/chunk-f691.c0cbf5c1.js.gz +0 -0
|
@@ -1,185 +1,200 @@
|
|
|
1
|
-
import Vue from 'vue'
|
|
2
|
-
import Router from 'vue-router'
|
|
3
|
-
|
|
4
|
-
// in development-env not use lazy-loading, because lazy-loading too many pages will cause webpack hot update too slow. so only in production use lazy-loading;
|
|
5
|
-
// detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
|
|
6
|
-
|
|
7
|
-
Vue.use(Router)
|
|
8
|
-
|
|
9
|
-
/* Layout */
|
|
10
|
-
import Layout from '../views/layout/Layout'
|
|
11
|
-
|
|
12
|
-
const capitalize = (s) => {
|
|
13
|
-
if (typeof s !== 'string') return ''
|
|
14
|
-
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* hidden: true if `hidden:true` will not show in the sidebar(default is false)
|
|
19
|
-
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
|
|
20
|
-
* if not set alwaysShow, only more than one route under the children
|
|
21
|
-
* it will becomes nested mode, otherwise not show the root menu
|
|
22
|
-
* redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
|
|
23
|
-
* name:'router-name' the name is used by <keep-alive> (must set!!!)
|
|
24
|
-
* meta : {
|
|
25
|
-
title: 'title' the name show in submenu and breadcrumb (recommend set)
|
|
26
|
-
icon: 'svg-name' the icon show in the sidebar,
|
|
27
|
-
}
|
|
28
|
-
**/
|
|
29
|
-
|
|
30
|
-
export const constantRouterMap = [
|
|
31
|
-
{ path: '/login', component: () => import('@/views/login/index'), hidden: true },
|
|
32
|
-
{ path: '/install', component: () => import('@/views/Install'), hidden: true },
|
|
33
|
-
{ path: '/404', component: () => import('@/views/404'), hidden: true },
|
|
34
|
-
|
|
35
|
-
{
|
|
36
|
-
path: '/',
|
|
37
|
-
component: Layout,
|
|
38
|
-
redirect: '/home',
|
|
39
|
-
name: 'Home',
|
|
40
|
-
meta: { title: 'Home', icon: 'home' },
|
|
41
|
-
children: [{
|
|
42
|
-
path: 'home',
|
|
43
|
-
meta: { title: 'Home', icon: 'home' },
|
|
44
|
-
component: () => import('@/views/Home')
|
|
45
|
-
}, {
|
|
46
|
-
path: '/edit/:collectionName/:id',
|
|
47
|
-
component: () => import('@/views/EditDocument'),
|
|
48
|
-
hidden: true
|
|
49
|
-
}]
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
path: '/users',
|
|
54
|
-
redirect: '/users/list',
|
|
55
|
-
component: Layout,
|
|
56
|
-
name: 'Users',
|
|
57
|
-
meta: { title: 'People', icon: 'users-alt' },
|
|
58
|
-
children: [{
|
|
59
|
-
path: 'list',
|
|
60
|
-
meta: { title: 'Users', icon: 'users-alt' },
|
|
61
|
-
name: 'users2',
|
|
62
|
-
component: () => import('@/views/ListDocuments2'),
|
|
63
|
-
props: { collectionName: 'users' },
|
|
64
|
-
}, {
|
|
65
|
-
path: 'add',
|
|
66
|
-
meta: { title: 'Add User', icon: 'plus' },
|
|
67
|
-
name: 'newuser',
|
|
68
|
-
component: () => import('@/views/EditDocument'),
|
|
69
|
-
props: { collectionName: 'users', id: 'create' },
|
|
70
|
-
}, {
|
|
71
|
-
path: 'role',
|
|
72
|
-
meta: { title: 'Roles', icon: 'shield-check' },
|
|
73
|
-
name: 'role',
|
|
74
|
-
component: () => import('@/views/ListDocuments2'),
|
|
75
|
-
props: { collectionName: 'role' },
|
|
76
|
-
}, {
|
|
77
|
-
path: 'addrole',
|
|
78
|
-
meta: { title: 'Add Role', icon: 'plus' },
|
|
79
|
-
name: 'newrole',
|
|
80
|
-
component: () => import('@/views/EditDocument'),
|
|
81
|
-
props: { collectionName: 'role', id: 'create' },
|
|
82
|
-
}],
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
path: '/list/:collectionName',
|
|
87
|
-
component: Layout,
|
|
88
|
-
hidden: true,
|
|
89
|
-
name: 'Data',
|
|
90
|
-
meta: { title: 'Data', icon: 'database' },
|
|
91
|
-
children: [{
|
|
92
|
-
path: '',
|
|
93
|
-
name: ':collectionName',
|
|
94
|
-
component: () => import('@/views/ListDocuments2'),
|
|
95
|
-
props: route => ({ collectionName: route.params.collectionName }),
|
|
96
|
-
meta: { title: capitalize(name) }
|
|
97
|
-
}]
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
{
|
|
101
|
-
path: '/manage/permissions',
|
|
102
|
-
component: Layout,
|
|
103
|
-
name: 'permissions',
|
|
104
|
-
meta: { title: 'Manage', icon: 'shield-check' },
|
|
105
|
-
children: [
|
|
106
|
-
{
|
|
107
|
-
path: '',
|
|
108
|
-
name: 'permissions',
|
|
109
|
-
component: () => import('@/views/ManagePermissions'),
|
|
110
|
-
meta: { title: 'Permissions' }
|
|
111
|
-
}
|
|
112
|
-
]
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
{
|
|
116
|
-
path: '/
|
|
117
|
-
component: Layout,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
children: [
|
|
121
|
-
{
|
|
122
|
-
path: '',
|
|
123
|
-
name: '',
|
|
124
|
-
component: () => import('@/views/
|
|
125
|
-
meta: { title: '' }
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
meta: { title: '
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
]
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import Router from 'vue-router'
|
|
3
|
+
|
|
4
|
+
// in development-env not use lazy-loading, because lazy-loading too many pages will cause webpack hot update too slow. so only in production use lazy-loading;
|
|
5
|
+
// detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
|
|
6
|
+
|
|
7
|
+
Vue.use(Router)
|
|
8
|
+
|
|
9
|
+
/* Layout */
|
|
10
|
+
import Layout from '../views/layout/Layout'
|
|
11
|
+
|
|
12
|
+
const capitalize = (s) => {
|
|
13
|
+
if (typeof s !== 'string') return ''
|
|
14
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* hidden: true if `hidden:true` will not show in the sidebar(default is false)
|
|
19
|
+
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
|
|
20
|
+
* if not set alwaysShow, only more than one route under the children
|
|
21
|
+
* it will becomes nested mode, otherwise not show the root menu
|
|
22
|
+
* redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
|
|
23
|
+
* name:'router-name' the name is used by <keep-alive> (must set!!!)
|
|
24
|
+
* meta : {
|
|
25
|
+
title: 'title' the name show in submenu and breadcrumb (recommend set)
|
|
26
|
+
icon: 'svg-name' the icon show in the sidebar,
|
|
27
|
+
}
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
export const constantRouterMap = [
|
|
31
|
+
{ path: '/login', component: () => import('@/views/login/index'), hidden: true },
|
|
32
|
+
{ path: '/install', component: () => import('@/views/Install'), hidden: true },
|
|
33
|
+
{ path: '/404', component: () => import('@/views/404'), hidden: true },
|
|
34
|
+
|
|
35
|
+
{
|
|
36
|
+
path: '/',
|
|
37
|
+
component: Layout,
|
|
38
|
+
redirect: '/home',
|
|
39
|
+
name: 'Home',
|
|
40
|
+
meta: { title: 'Home', icon: 'home' },
|
|
41
|
+
children: [{
|
|
42
|
+
path: 'home',
|
|
43
|
+
meta: { title: 'Home', icon: 'home' },
|
|
44
|
+
component: () => import('@/views/Home')
|
|
45
|
+
}, {
|
|
46
|
+
path: '/edit/:collectionName/:id',
|
|
47
|
+
component: () => import('@/views/EditDocument'),
|
|
48
|
+
hidden: true
|
|
49
|
+
}]
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
path: '/users',
|
|
54
|
+
redirect: '/users/list',
|
|
55
|
+
component: Layout,
|
|
56
|
+
name: 'Users',
|
|
57
|
+
meta: { title: 'People', icon: 'users-alt' },
|
|
58
|
+
children: [{
|
|
59
|
+
path: 'list',
|
|
60
|
+
meta: { title: 'Users', icon: 'users-alt' },
|
|
61
|
+
name: 'users2',
|
|
62
|
+
component: () => import('@/views/ListDocuments2'),
|
|
63
|
+
props: { collectionName: 'users' },
|
|
64
|
+
}, {
|
|
65
|
+
path: 'add',
|
|
66
|
+
meta: { title: 'Add User', icon: 'plus' },
|
|
67
|
+
name: 'newuser',
|
|
68
|
+
component: () => import('@/views/EditDocument'),
|
|
69
|
+
props: { collectionName: 'users', id: 'create' },
|
|
70
|
+
}, {
|
|
71
|
+
path: 'role',
|
|
72
|
+
meta: { title: 'Roles', icon: 'shield-check' },
|
|
73
|
+
name: 'role',
|
|
74
|
+
component: () => import('@/views/ListDocuments2'),
|
|
75
|
+
props: { collectionName: 'role' },
|
|
76
|
+
}, {
|
|
77
|
+
path: 'addrole',
|
|
78
|
+
meta: { title: 'Add Role', icon: 'plus' },
|
|
79
|
+
name: 'newrole',
|
|
80
|
+
component: () => import('@/views/EditDocument'),
|
|
81
|
+
props: { collectionName: 'role', id: 'create' },
|
|
82
|
+
}],
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
path: '/list/:collectionName',
|
|
87
|
+
component: Layout,
|
|
88
|
+
hidden: true,
|
|
89
|
+
name: 'Data',
|
|
90
|
+
meta: { title: 'Data', icon: 'database' },
|
|
91
|
+
children: [{
|
|
92
|
+
path: '',
|
|
93
|
+
name: ':collectionName',
|
|
94
|
+
component: () => import('@/views/ListDocuments2'),
|
|
95
|
+
props: route => ({ collectionName: route.params.collectionName }),
|
|
96
|
+
meta: { title: capitalize(name) }
|
|
97
|
+
}]
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
{
|
|
101
|
+
path: '/manage/permissions',
|
|
102
|
+
component: Layout,
|
|
103
|
+
name: 'permissions',
|
|
104
|
+
meta: { title: 'Manage', icon: 'shield-check' },
|
|
105
|
+
children: [
|
|
106
|
+
{
|
|
107
|
+
path: '',
|
|
108
|
+
name: 'permissions',
|
|
109
|
+
component: () => import('@/views/ManagePermissions'),
|
|
110
|
+
meta: { title: 'Permissions' }
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
{
|
|
116
|
+
path: '/endpoints',
|
|
117
|
+
component: Layout,
|
|
118
|
+
name: 'endpoints',
|
|
119
|
+
meta: { title: 'Search', icon: 'link' },
|
|
120
|
+
children: [
|
|
121
|
+
{
|
|
122
|
+
path: '',
|
|
123
|
+
name: 'endpoints',
|
|
124
|
+
component: () => import('@/views/Endpoints'),
|
|
125
|
+
meta: { title: 'Endpoints' }
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
{
|
|
131
|
+
path: '/dev',
|
|
132
|
+
component: Layout,
|
|
133
|
+
meta: { title: 'Dev', icon: 'flask' },
|
|
134
|
+
name: 'Dev',
|
|
135
|
+
children: [
|
|
136
|
+
{
|
|
137
|
+
path: '',
|
|
138
|
+
name: '',
|
|
139
|
+
component: () => import('@/views/Dev'),
|
|
140
|
+
meta: { title: '' },
|
|
141
|
+
hidden: true,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
path: 'listeners',
|
|
145
|
+
name: 'listeners',
|
|
146
|
+
component: () => import('@/views/ManageListeners'),
|
|
147
|
+
meta: { title: 'Listeners' }
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
path: 'middleware',
|
|
151
|
+
name: 'middleware',
|
|
152
|
+
component: () => import('@/views/ManageMiddleware'),
|
|
153
|
+
meta: { title: 'Middleware' }
|
|
154
|
+
}, {
|
|
155
|
+
path: 'requestlogs',
|
|
156
|
+
meta: { title: 'Request Logs', icon: 'diary' },
|
|
157
|
+
name: 'requestlogs',
|
|
158
|
+
component: () => import('@/views/ListDocuments2'),
|
|
159
|
+
props: { collectionName: 'requestlog', columns: ['method', 'url', 'req.ip', 'user', 'res.message', 'res.statusCode', 'res.headers.content-length'] },
|
|
160
|
+
}, {
|
|
161
|
+
path: 'viewrequest/:requestId',
|
|
162
|
+
hidden: true,
|
|
163
|
+
meta: { title: 'View Request', icon: 'diary' },
|
|
164
|
+
name: 'viewrequest',
|
|
165
|
+
component: () => import('@/views/ViewRequest'),
|
|
166
|
+
}, {
|
|
167
|
+
path: '/edit/collection',
|
|
168
|
+
component: Layout,
|
|
169
|
+
name: 'Schema',
|
|
170
|
+
hidden: true,
|
|
171
|
+
meta: { title: 'Schemas', icon: 'cog' },
|
|
172
|
+
children: [{
|
|
173
|
+
hidden: true,
|
|
174
|
+
path: '/:collectionName',
|
|
175
|
+
name: name,
|
|
176
|
+
meta: { title: capitalize(name) }
|
|
177
|
+
}]
|
|
178
|
+
},
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
{
|
|
183
|
+
path: 'external-link',
|
|
184
|
+
component: Layout,
|
|
185
|
+
children: [
|
|
186
|
+
{
|
|
187
|
+
path: 'https://github.com/thomas4019/expressa',
|
|
188
|
+
meta: { title: 'Expressa Docs', icon: 'link' }
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
{ path: '*', redirect: '/404', hidden: true }
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
export default new Router({
|
|
197
|
+
// mode: 'history',
|
|
198
|
+
scrollBehavior: () => ({ y: 0 }),
|
|
199
|
+
routes: constantRouterMap
|
|
200
|
+
})
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="px-3">
|
|
3
|
+
<div class="d-flex align-items-start py-2">
|
|
4
|
+
<div>
|
|
5
|
+
Endpoint
|
|
6
|
+
|
|
7
|
+
<div class="d-flex align-items-center mb-2">
|
|
8
|
+
<el-input v-model="apiBaseUrl" placeholder="key" />
|
|
9
|
+
<el-input v-model="apiSuffix" placeholder="races" />
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
Params
|
|
13
|
+
<div v-for="(parameter, index) in params" :key="index" class="d-flex align-items-center mb-1">
|
|
14
|
+
<el-checkbox v-model="parameter.isEnabled" class="mr-2" />
|
|
15
|
+
|
|
16
|
+
<el-input v-model="parameter.key" placeholder="key" @input="handleParamKeyChange(index)" />
|
|
17
|
+
|
|
18
|
+
<el-input v-model="parameter.value" placeholder="value" class="ml-1" />
|
|
19
|
+
|
|
20
|
+
<el-button
|
|
21
|
+
v-if="params.length > 1"
|
|
22
|
+
icon="el-icon-close"
|
|
23
|
+
circle
|
|
24
|
+
type="text"
|
|
25
|
+
@click="removeParam(index)"
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<span class="mx-auto" />
|
|
31
|
+
|
|
32
|
+
<div class="d-flex align-items-center">
|
|
33
|
+
<el-dropdown
|
|
34
|
+
multiple
|
|
35
|
+
class="mr-4"
|
|
36
|
+
:hide-on-click="false"
|
|
37
|
+
>
|
|
38
|
+
<span class="el-dropdown-link">
|
|
39
|
+
Select columns
|
|
40
|
+
<i class="el-icon-arrow-down el-icon--right" />
|
|
41
|
+
</span>
|
|
42
|
+
|
|
43
|
+
<el-dropdown-menu slot="dropdown" style="max-height: 300px; overflow: auto">
|
|
44
|
+
<el-checkbox-group v-model="selectedColumns" @input="update">
|
|
45
|
+
<el-dropdown-item
|
|
46
|
+
v-for="column in allPossibleColumns"
|
|
47
|
+
:key="column"
|
|
48
|
+
:label="column"
|
|
49
|
+
:value="column"
|
|
50
|
+
>
|
|
51
|
+
<el-checkbox
|
|
52
|
+
class="mb-0 mr-4"
|
|
53
|
+
:label="column"
|
|
54
|
+
:disabled="selectedColumns.length === 1 && selectedColumns[0] === column"
|
|
55
|
+
/>
|
|
56
|
+
</el-dropdown-item>
|
|
57
|
+
</el-checkbox-group>
|
|
58
|
+
</el-dropdown-menu>
|
|
59
|
+
</el-dropdown>
|
|
60
|
+
|
|
61
|
+
<el-checkbox
|
|
62
|
+
v-model="isFiltersVisible"
|
|
63
|
+
class="mb-0 mr-4"
|
|
64
|
+
>
|
|
65
|
+
Show Filters
|
|
66
|
+
</el-checkbox>
|
|
67
|
+
|
|
68
|
+
<el-pagination
|
|
69
|
+
:page-size="pageSize"
|
|
70
|
+
:total="count"
|
|
71
|
+
:page-sizes="pageSizes"
|
|
72
|
+
:current-page.sync="page"
|
|
73
|
+
layout="sizes, prev, pager, next"
|
|
74
|
+
@current-change="update()"
|
|
75
|
+
@size-change="pageSize = $event, update()"
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<el-button class="btn btn-primary mb-3" @click="update">
|
|
81
|
+
Search
|
|
82
|
+
</el-button>
|
|
83
|
+
|
|
84
|
+
<el-table
|
|
85
|
+
:data="tableRows"
|
|
86
|
+
element-loading-text="Loading"
|
|
87
|
+
border
|
|
88
|
+
fit
|
|
89
|
+
highlight-current-row
|
|
90
|
+
@sort-change="handleSortChange"
|
|
91
|
+
>
|
|
92
|
+
<el-table-column
|
|
93
|
+
v-for="(name, i) in selectedColumns"
|
|
94
|
+
:key="name"
|
|
95
|
+
:label="name"
|
|
96
|
+
:prop="name"
|
|
97
|
+
align="center"
|
|
98
|
+
:sortable="true"
|
|
99
|
+
>
|
|
100
|
+
<template slot-scope="scope">
|
|
101
|
+
<div class="text-left">
|
|
102
|
+
<div v-if="scope.$index === 0 && isFiltersVisible">
|
|
103
|
+
<el-input
|
|
104
|
+
v-model="searchFilters[name]"
|
|
105
|
+
:placeholder="`Search by ${name}`"
|
|
106
|
+
:type="getFieldType(name) === 'number' ? 'number' : 'text'"
|
|
107
|
+
@change="update()"
|
|
108
|
+
/>
|
|
109
|
+
|
|
110
|
+
<el-checkbox
|
|
111
|
+
v-model="exactSearches[name]"
|
|
112
|
+
:disabled="getFieldType(name) === 'number'"
|
|
113
|
+
class="mt-3"
|
|
114
|
+
@change="update()"
|
|
115
|
+
>
|
|
116
|
+
Exact match
|
|
117
|
+
</el-checkbox>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<template>
|
|
121
|
+
<router-link v-if="i === 0 && collectionName !== 'requestlog'" :to="'/edit/'+collectionName+'/'+scope.row._id">
|
|
122
|
+
{{ getPath(scope.row, name) }}
|
|
123
|
+
</router-link>
|
|
124
|
+
<router-link v-if="i === 0 && collectionName === 'requestlog'" :to="'/dev/viewrequest/'+scope.row._id">
|
|
125
|
+
{{ getPath(scope.row, name) }}
|
|
126
|
+
</router-link>
|
|
127
|
+
<span v-if="i !== 0">{{ getPath(scope.row, name) }}</span>
|
|
128
|
+
</template>
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
131
|
+
</el-table-column>
|
|
132
|
+
</el-table>
|
|
133
|
+
|
|
134
|
+
<div v-if="data.length" class="d-flex align-items-center my-3">
|
|
135
|
+
<button class="btn btn-secondary download-button mr-2" @click="downloadCSV()">
|
|
136
|
+
Download
|
|
137
|
+
</button>
|
|
138
|
+
|
|
139
|
+
<button class="btn btn-secondary download-button" @click="downloadAllCSV()">
|
|
140
|
+
Download All
|
|
141
|
+
</button>
|
|
142
|
+
|
|
143
|
+
<span class="mx-auto" />
|
|
144
|
+
|
|
145
|
+
<el-pagination
|
|
146
|
+
:page-size="pageSize"
|
|
147
|
+
:total="count"
|
|
148
|
+
:page-sizes="pageSizes"
|
|
149
|
+
:current-page.sync="page"
|
|
150
|
+
layout="sizes, prev, pager, next"
|
|
151
|
+
@current-change="update()"
|
|
152
|
+
@size-change="pageSize = $event, update()"
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</template>
|
|
157
|
+
|
|
158
|
+
<script>
|
|
159
|
+
import ListDocuments2 from '@/views/ListDocuments2.vue'
|
|
160
|
+
import request from '@/utils/request'
|
|
161
|
+
var dot = require('dot-object')
|
|
162
|
+
dot.keepArray = true
|
|
163
|
+
|
|
164
|
+
export default {
|
|
165
|
+
name: 'Endpoints',
|
|
166
|
+
mixins: [ListDocuments2],
|
|
167
|
+
data() {
|
|
168
|
+
return {
|
|
169
|
+
apiBaseUrl: request.defaults.baseURL,
|
|
170
|
+
apiSuffix: '',
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
methods: {
|
|
174
|
+
async update() {
|
|
175
|
+
if (!this.apiSuffix) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Fetch and Set table data
|
|
180
|
+
const params = {
|
|
181
|
+
page: this.page,
|
|
182
|
+
limit: this.pageSize,
|
|
183
|
+
...this.allFilters,
|
|
184
|
+
query: undefined
|
|
185
|
+
}
|
|
186
|
+
const info = (await request({ url: `/${this.apiSuffix}?${this.customParams}`, params })).data
|
|
187
|
+
this.count = info.itemsTotal
|
|
188
|
+
this.data = this.applyCustomColumnFilter(info.data)
|
|
189
|
+
|
|
190
|
+
// Set columns data if not set.
|
|
191
|
+
if (!this.selectedColumns.length) {
|
|
192
|
+
const columns = Array.from(this.data.reduce((acc, row) => {
|
|
193
|
+
const rowWithDottedKeys = dot.dot(row)
|
|
194
|
+
|
|
195
|
+
return new Set([
|
|
196
|
+
...Object.keys(rowWithDottedKeys),
|
|
197
|
+
...acc
|
|
198
|
+
])
|
|
199
|
+
}, []))
|
|
200
|
+
|
|
201
|
+
this.selectedColumns = ['_id']
|
|
202
|
+
this.allPossibleColumns = columns
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
applyCustomColumnFilter(tableData) {
|
|
206
|
+
const customColumnSearches = Object.keys(this.searchFilters)
|
|
207
|
+
|
|
208
|
+
return tableData.filter((row) => {
|
|
209
|
+
return customColumnSearches.every(fieldName => {
|
|
210
|
+
const searchKeyword = this.searchFilters[fieldName]
|
|
211
|
+
|
|
212
|
+
if (!searchKeyword) {
|
|
213
|
+
return true
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const rowWithDottedKeys = dot.dot(row)
|
|
217
|
+
const stringified = rowWithDottedKeys[fieldName].toString()
|
|
218
|
+
|
|
219
|
+
if (this.exactSearches[fieldName]) {
|
|
220
|
+
return stringified.trim() === searchKeyword.trim()
|
|
221
|
+
} else {
|
|
222
|
+
return stringified.toLowerCase().includes(searchKeyword.toLowerCase())
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
},
|
|
227
|
+
async downloadAllCSV() {
|
|
228
|
+
let rows = []
|
|
229
|
+
let page = 1
|
|
230
|
+
|
|
231
|
+
while (this.count > rows.length) {
|
|
232
|
+
const params = {
|
|
233
|
+
...this.allFilters,
|
|
234
|
+
page: page,
|
|
235
|
+
limit: 500,
|
|
236
|
+
query: undefined
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const url = `/${this.apiSuffix}?${this.customParams}`
|
|
240
|
+
const response = (await request({ url, params })).data
|
|
241
|
+
rows = [...response.data, ...rows]
|
|
242
|
+
page += 1
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
this.downloadCSV(this.applyCustomColumnFilter(rows))
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
</script>
|
|
250
|
+
|