agendash 2.0.0 → 3.1.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/README.md +59 -22
- package/app.js +9 -5
- package/bin/agendash-standalone-fastify.js +61 -0
- package/bin/agendash-standalone-hapi.js +36 -18
- package/bin/agendash-standalone-koa.js +30 -14
- package/bin/agendash-standalone.js +44 -19
- package/lib/controllers/agendash.js +228 -110
- package/lib/csp.js +28 -0
- package/lib/middlewares/README.md +3 -1
- package/lib/middlewares/express.js +43 -17
- package/lib/middlewares/fastify.js +77 -0
- package/lib/middlewares/hapi.js +58 -33
- package/lib/middlewares/koa.js +29 -20
- package/package.json +37 -35
- package/public/app/js/confirmDelete.js +14 -13
- package/public/app/js/confirmDeleteMulti.js +14 -13
- package/public/app/js/confirmRequeue.js +14 -13
- package/public/app/js/confirmRequeueMulti.js +15 -14
- package/public/app/js/confirms.js +4 -4
- package/public/app/js/jobdetail.js +9 -9
- package/public/app/js/joblist.js +50 -43
- package/public/app/js/main.js +109 -72
- package/public/app/js/newJob.js +37 -23
- package/public/app/js/sidebar.js +51 -26
- package/public/app/js/topbar.js +15 -5
- package/.editorconfig +0 -7
- package/.idea/agendash.iml +0 -12
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/jsLibraryMappings.xml +0 -6
- package/.idea/misc.xml +0 -92
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.travis.yml +0 -27
- package/.vscode/launch.json +0 -15
- package/History.md +0 -106
- package/renovate.json +0 -5
- package/test/test-express.js +0 -82
- package/test/test-hapi.js +0 -106
- package/test/test-koa.js +0 -85
package/public/app/js/joblist.js
CHANGED
|
@@ -1,72 +1,79 @@
|
|
|
1
|
-
const jobList = Vue.component(
|
|
1
|
+
const jobList = Vue.component("job-list", {
|
|
2
2
|
data: () => ({
|
|
3
3
|
multijobs: [],
|
|
4
|
-
currentSort:
|
|
5
|
-
currentSortDir:
|
|
4
|
+
currentSort: "name",
|
|
5
|
+
currentSortDir: "asc",
|
|
6
6
|
}),
|
|
7
|
-
props: [
|
|
8
|
-
computed:{
|
|
9
|
-
sortedJobs:function() {
|
|
10
|
-
return this.jobs.sort((a,b) => {
|
|
11
|
-
let displayA, displayB
|
|
12
|
-
if(this.currentSort === "name") {
|
|
13
|
-
displayA = a.job[this.currentSort]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
props: ["jobs", "pagesize", "pagenumber", "sendClean", "loading"],
|
|
8
|
+
computed: {
|
|
9
|
+
sortedJobs: function () {
|
|
10
|
+
return this.jobs.sort((a, b) => {
|
|
11
|
+
let displayA, displayB;
|
|
12
|
+
if (this.currentSort === "name") {
|
|
13
|
+
displayA = a.job[this.currentSort]
|
|
14
|
+
? a.job[this.currentSort].toLowerCase()
|
|
15
|
+
: "";
|
|
16
|
+
displayB = a.job[this.currentSort]
|
|
17
|
+
? b.job[this.currentSort].toLowerCase()
|
|
18
|
+
: "";
|
|
19
|
+
} else {
|
|
20
|
+
displayA = moment(a.job[this.currentSort]);
|
|
21
|
+
displayB = moment(b.job[this.currentSort]);
|
|
19
22
|
}
|
|
20
23
|
let modifier = 1;
|
|
21
|
-
if(this.currentSortDir ===
|
|
22
|
-
if(displayA < displayB) return -1 * modifier;
|
|
23
|
-
if(displayA > displayB) return 1 * modifier;
|
|
24
|
+
if (this.currentSortDir === "desc") modifier = -1;
|
|
25
|
+
if (displayA < displayB) return -1 * modifier;
|
|
26
|
+
if (displayA > displayB) return 1 * modifier;
|
|
24
27
|
return 0;
|
|
25
28
|
});
|
|
26
|
-
}
|
|
29
|
+
},
|
|
27
30
|
},
|
|
28
31
|
watch: {
|
|
29
32
|
jobs() {
|
|
30
33
|
// reset multijobs when jobs have changed
|
|
31
34
|
this.multijobs = [];
|
|
32
|
-
}
|
|
35
|
+
},
|
|
33
36
|
},
|
|
34
37
|
methods: {
|
|
35
38
|
sort(s) {
|
|
36
39
|
//if s == current sort, reverse
|
|
37
|
-
if(s === this.currentSort) {
|
|
38
|
-
this.currentSortDir = this.currentSortDir ===
|
|
40
|
+
if (s === this.currentSort) {
|
|
41
|
+
this.currentSortDir = this.currentSortDir === "asc" ? "desc" : "asc";
|
|
39
42
|
}
|
|
40
43
|
this.currentSort = s;
|
|
41
44
|
},
|
|
42
|
-
sendQueued(){
|
|
43
|
-
this.$emit(
|
|
45
|
+
sendQueued() {
|
|
46
|
+
this.$emit("confirm-multi-requeue", this.multijobs);
|
|
44
47
|
// this.multijobs = []
|
|
45
48
|
},
|
|
46
|
-
sendDelete(){
|
|
47
|
-
this.$emit(
|
|
49
|
+
sendDelete() {
|
|
50
|
+
this.$emit("confirm-multi-delete", this.multijobs);
|
|
48
51
|
// this.multijobs = []
|
|
49
52
|
},
|
|
50
53
|
cleanMulti() {
|
|
51
|
-
return console.log("received Clean Multi")
|
|
54
|
+
return console.log("received Clean Multi");
|
|
55
|
+
},
|
|
56
|
+
formatTitle(date) {
|
|
57
|
+
if (!date) return;
|
|
58
|
+
return moment(date).format();
|
|
52
59
|
},
|
|
53
60
|
formatDate(date) {
|
|
61
|
+
if (!date) return;
|
|
54
62
|
return moment(date).fromNow();
|
|
55
|
-
// return new Date(date).toLocaleDateString('en-US', { day: 'numeric', month: 'numeric', year: '2-digit', hour: "numeric", minute: "numeric", second: "numeric" })
|
|
56
63
|
},
|
|
57
|
-
checkAllCheckboxes(){
|
|
58
|
-
const checkboxes = document.querySelectorAll(
|
|
64
|
+
checkAllCheckboxes() {
|
|
65
|
+
const checkboxes = document.querySelectorAll(".checkbox-triggerable");
|
|
59
66
|
for (const checkbox of checkboxes) {
|
|
60
67
|
checkbox.click();
|
|
61
68
|
}
|
|
62
69
|
},
|
|
63
70
|
toggleList(job) {
|
|
64
|
-
if(this.multijobs.includes(job.job._id)) {
|
|
71
|
+
if (this.multijobs.includes(job.job._id)) {
|
|
65
72
|
this.multijobs.splice(this.multijobs.indexOf(job.job._id), 1);
|
|
66
73
|
} else {
|
|
67
74
|
this.multijobs.push(job.job._id);
|
|
68
75
|
}
|
|
69
|
-
}
|
|
76
|
+
},
|
|
70
77
|
},
|
|
71
78
|
template: `
|
|
72
79
|
<div v-on:sendClean="cleanMulti">
|
|
@@ -136,10 +143,10 @@ const jobList = Vue.component('job-list', {
|
|
|
136
143
|
<i v-if="job.running" class="pill-own bg-warning pill-withoutIcon"><span>Running</span></i>
|
|
137
144
|
</td>
|
|
138
145
|
<td class="job-name" @click="toggleList(job)"> {{job.job.name}} </td>
|
|
139
|
-
<td class="job-lastRunAt"
|
|
140
|
-
<td class="job-nextRunAt"
|
|
141
|
-
<td class="job-finishedAt"
|
|
142
|
-
<td class="job-lockedAt"
|
|
146
|
+
<td class="job-lastRunAt" :title="formatTitle(job.job.lastRunAt)" @click="toggleList(job)"> {{ formatDate(job.job.lastRunAt) }} </td>
|
|
147
|
+
<td class="job-nextRunAt" :title="formatTitle(job.job.nextRunAt)" @click="toggleList(job)"> {{ formatDate(job.job.nextRunAt) }} </td>
|
|
148
|
+
<td class="job-finishedAt" :title="formatTitle(job.job.lastFinishedAt)" @click="toggleList(job)"> {{ formatDate(job.job.lastFinishedAt) }} </td>
|
|
149
|
+
<td class="job-lockedAt" :title="formatTitle(job.job.lockedAt)" @click="toggleList(job)"> {{ formatDate(job.job.lockedAt) }} </td>
|
|
143
150
|
<td class="job-actions">
|
|
144
151
|
<i class="material-icons md-dark md-custom action-btn viewData text-primary" data-toggle="modal" data-target="#modalRequeueSure" @click="$emit('confirm-requeue', job)" data-placement="left" title="Requeue">update</i>
|
|
145
152
|
<i class="material-icons md-dark md-custom action-btn viewData text-success" data-toggle="modal" data-target="#modalData" @click="$emit('show-job-detail', job)" data-placement="top" title="Job Data">visibility</i>
|
|
@@ -181,13 +188,13 @@ const jobList = Vue.component('job-list', {
|
|
|
181
188
|
<div class="card-responsive-status-title">
|
|
182
189
|
Last run started
|
|
183
190
|
</div>
|
|
184
|
-
<div class="mb-3">
|
|
191
|
+
<div class="mb-3" :title="formatTitle(job.job.lastRunAt)">
|
|
185
192
|
{{ formatDate(job.job.lastRunAt) }}
|
|
186
193
|
</div>
|
|
187
194
|
<div class="card-responsive-status-title">
|
|
188
195
|
Last finished
|
|
189
196
|
</div>
|
|
190
|
-
<div>
|
|
197
|
+
<div :title="formatTitle(job.job.lastFinishedAt)">
|
|
191
198
|
{{ formatDate(job.job.lastFinishedAt) }}
|
|
192
199
|
</div>
|
|
193
200
|
</div>
|
|
@@ -195,14 +202,14 @@ const jobList = Vue.component('job-list', {
|
|
|
195
202
|
<div class="card-responsive-status-title">
|
|
196
203
|
Next run starts
|
|
197
204
|
</div>
|
|
198
|
-
<div class="mb-3">
|
|
205
|
+
<div class="mb-3" :title="formatTitle(job.job.nextRunAt)">
|
|
199
206
|
{{ formatDate(job.job.nextRunAt) }}
|
|
200
207
|
</div>
|
|
201
208
|
<div class="card-responsive-status-title">
|
|
202
209
|
Locked
|
|
203
210
|
</div>
|
|
204
|
-
<div>
|
|
205
|
-
{{
|
|
211
|
+
<div :title="formatTitle(job.job.lockedAt)">
|
|
212
|
+
{{ formatDate(job.job.lockedAt) || "-" }}
|
|
206
213
|
</div>
|
|
207
214
|
</div>
|
|
208
215
|
</div>
|
|
@@ -228,5 +235,5 @@ const jobList = Vue.component('job-list', {
|
|
|
228
235
|
</div>
|
|
229
236
|
</div>
|
|
230
237
|
</div>
|
|
231
|
-
|
|
232
|
-
})
|
|
238
|
+
`,
|
|
239
|
+
});
|
package/public/app/js/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const app = Vue.component(
|
|
1
|
+
const app = Vue.component("app", {
|
|
2
2
|
data: () => ({
|
|
3
3
|
jobs: [],
|
|
4
4
|
overview: [],
|
|
@@ -16,14 +16,14 @@ const app = Vue.component('app', {
|
|
|
16
16
|
pagesize: 15,
|
|
17
17
|
sendClean: false,
|
|
18
18
|
createc: false,
|
|
19
|
-
property:
|
|
20
|
-
search:
|
|
21
|
-
object:
|
|
19
|
+
property: "",
|
|
20
|
+
search: "",
|
|
21
|
+
object: "",
|
|
22
22
|
newLimit: null,
|
|
23
23
|
skip: 0,
|
|
24
|
-
name:
|
|
25
|
-
state:
|
|
26
|
-
nameprop:
|
|
24
|
+
name: "",
|
|
25
|
+
state: "",
|
|
26
|
+
nameprop: "",
|
|
27
27
|
loading: false,
|
|
28
28
|
hideSlide: true,
|
|
29
29
|
}),
|
|
@@ -31,123 +31,160 @@ const app = Vue.component('app', {
|
|
|
31
31
|
openNav() {
|
|
32
32
|
document.getElementById("mySidebar").style.width = "100%";
|
|
33
33
|
document.getElementById("main").style.marginLeft = "100%";
|
|
34
|
-
this.hideSlide = false
|
|
34
|
+
this.hideSlide = false;
|
|
35
35
|
},
|
|
36
36
|
closeNav() {
|
|
37
37
|
document.getElementById("mySidebar").style.width = "0";
|
|
38
38
|
document.getElementById("main").style.marginLeft = "0";
|
|
39
|
-
this.hideSlide = true
|
|
39
|
+
this.hideSlide = true;
|
|
40
40
|
},
|
|
41
|
-
showJobDetail(data){
|
|
41
|
+
showJobDetail(data) {
|
|
42
42
|
this.jobData = data;
|
|
43
43
|
this.showDetail = true;
|
|
44
44
|
},
|
|
45
|
-
readyClean(){
|
|
45
|
+
readyClean() {
|
|
46
46
|
this.sendClean = true;
|
|
47
47
|
},
|
|
48
|
-
confirmDelete(data){
|
|
48
|
+
confirmDelete(data) {
|
|
49
49
|
this.jobData = data;
|
|
50
50
|
this.showConfirm = true;
|
|
51
51
|
},
|
|
52
|
-
confirmDeleteMulti(data){
|
|
52
|
+
confirmDeleteMulti(data) {
|
|
53
53
|
this.jobData = data;
|
|
54
54
|
this.showConfirmMulti = true;
|
|
55
55
|
},
|
|
56
|
-
confirmRequeue(data){
|
|
56
|
+
confirmRequeue(data) {
|
|
57
57
|
this.jobData = data;
|
|
58
58
|
this.showConfirmRequeue = true;
|
|
59
59
|
},
|
|
60
|
-
confirmRequeueMulti(data){
|
|
60
|
+
confirmRequeueMulti(data) {
|
|
61
61
|
this.jobData = data;
|
|
62
62
|
this.showConfirmRequeueMulti = true;
|
|
63
63
|
},
|
|
64
|
-
newJob(data){
|
|
64
|
+
newJob(data) {
|
|
65
65
|
this.jobData = data;
|
|
66
66
|
this.showNewJob = true;
|
|
67
67
|
},
|
|
68
|
-
searchForm(name, search, property, limit, skip, refresh, state, object){
|
|
69
|
-
|
|
70
|
-
this.name = name,
|
|
71
|
-
this.search = search,
|
|
72
|
-
this.property = property,
|
|
73
|
-
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
76
|
-
this.
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
searchForm(name, search, property, limit, skip, refresh, state, object) {
|
|
69
|
+
(this.pagesize = limit ? limit : this.pagesize),
|
|
70
|
+
(this.name = name),
|
|
71
|
+
(this.search = search),
|
|
72
|
+
(this.property = property),
|
|
73
|
+
(this.skip = skip),
|
|
74
|
+
(this.refresh = refresh),
|
|
75
|
+
(this.state = state),
|
|
76
|
+
(this.object = object ? object : this.object),
|
|
77
|
+
this.fetchData(
|
|
78
|
+
this.name,
|
|
79
|
+
this.search,
|
|
80
|
+
this.property,
|
|
81
|
+
this.pagesize,
|
|
82
|
+
this.skip,
|
|
83
|
+
this.refresh,
|
|
84
|
+
this.state,
|
|
85
|
+
this.object
|
|
86
|
+
);
|
|
80
87
|
},
|
|
81
88
|
refreshData() {
|
|
82
|
-
this.fetchData(
|
|
89
|
+
this.fetchData(
|
|
90
|
+
this.name,
|
|
91
|
+
this.search,
|
|
92
|
+
this.property,
|
|
93
|
+
this.pagesize,
|
|
94
|
+
this.skip,
|
|
95
|
+
this.refresh,
|
|
96
|
+
this.state,
|
|
97
|
+
this.object
|
|
98
|
+
);
|
|
83
99
|
},
|
|
84
|
-
pagechange(action){
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
this.pagenumber++
|
|
100
|
+
pagechange(action) {
|
|
101
|
+
if (action === "next") {
|
|
102
|
+
this.pagenumber++;
|
|
88
103
|
}
|
|
89
|
-
if(action ===
|
|
90
|
-
this.pagenumber
|
|
104
|
+
if (action === "prev") {
|
|
105
|
+
this.pagenumber--;
|
|
91
106
|
}
|
|
92
|
-
this.skip = (this.pagenumber-1) * this.pagesize
|
|
93
|
-
this.fetchData(
|
|
107
|
+
this.skip = (this.pagenumber - 1) * this.pagesize;
|
|
108
|
+
this.fetchData(
|
|
109
|
+
this.name,
|
|
110
|
+
this.search,
|
|
111
|
+
this.property,
|
|
112
|
+
this.pagesize,
|
|
113
|
+
this.skip,
|
|
114
|
+
this.refresh,
|
|
115
|
+
this.state,
|
|
116
|
+
this.object
|
|
117
|
+
);
|
|
94
118
|
},
|
|
95
|
-
fetchData(
|
|
119
|
+
fetchData(
|
|
120
|
+
name = "",
|
|
121
|
+
search = "",
|
|
122
|
+
property = "",
|
|
123
|
+
limit = 15,
|
|
124
|
+
skip = 0,
|
|
125
|
+
refresh = 60,
|
|
126
|
+
state = "",
|
|
127
|
+
object
|
|
128
|
+
) {
|
|
96
129
|
this.loading = true;
|
|
97
130
|
this.pagesize = this.pagesize === 0 ? parseInt(limit) : this.pagesize;
|
|
98
131
|
this.refresh = parseFloat(refresh);
|
|
99
|
-
const url = `api?limit=${limit}&job=${name}&skip=${skip}&property=${property}${
|
|
100
|
-
|
|
101
|
-
|
|
132
|
+
const url = `api?limit=${limit}&job=${name}&skip=${skip}&property=${property}${
|
|
133
|
+
object ? "&isObjectId=true" : ""
|
|
134
|
+
}${state ? `&state=${state}` : ""}&q=${search}`;
|
|
135
|
+
return axios
|
|
136
|
+
.get(url)
|
|
137
|
+
.then((result) => result.data)
|
|
102
138
|
.then(
|
|
103
|
-
data => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
139
|
+
(data) => {
|
|
140
|
+
this.jobs = data.jobs;
|
|
141
|
+
this.search = search;
|
|
142
|
+
this.property = property;
|
|
143
|
+
this.object = object;
|
|
144
|
+
this.overview = data.overview;
|
|
145
|
+
this.loading = false;
|
|
146
|
+
},
|
|
147
|
+
() => {
|
|
148
|
+
this.loading = false;
|
|
149
|
+
this.jobs = [];
|
|
150
|
+
}
|
|
114
151
|
)
|
|
115
|
-
.catch(console.log)
|
|
152
|
+
.catch(console.log);
|
|
116
153
|
},
|
|
117
154
|
|
|
118
|
-
popupmessage(data){
|
|
119
|
-
if(data ===
|
|
120
|
-
this.deletec = true
|
|
155
|
+
popupmessage(data) {
|
|
156
|
+
if (data === "delete") {
|
|
157
|
+
this.deletec = true;
|
|
121
158
|
setTimeout(() => {
|
|
122
|
-
this.deletec = false
|
|
159
|
+
this.deletec = false;
|
|
123
160
|
}, 2000);
|
|
124
161
|
}
|
|
125
|
-
if(data ===
|
|
126
|
-
this.deletec = true
|
|
162
|
+
if (data === "multidelete") {
|
|
163
|
+
this.deletec = true;
|
|
127
164
|
setTimeout(() => {
|
|
128
|
-
this.deletec = false
|
|
165
|
+
this.deletec = false;
|
|
129
166
|
}, 2000);
|
|
130
167
|
}
|
|
131
|
-
if(data ===
|
|
132
|
-
this.requeuec = true
|
|
168
|
+
if (data === "requeue") {
|
|
169
|
+
this.requeuec = true;
|
|
133
170
|
setTimeout(() => {
|
|
134
|
-
this.requeuec = false
|
|
171
|
+
this.requeuec = false;
|
|
135
172
|
}, 2000);
|
|
136
173
|
}
|
|
137
|
-
if(data ===
|
|
138
|
-
this.requeuec = true
|
|
174
|
+
if (data === "multirequeue") {
|
|
175
|
+
this.requeuec = true;
|
|
139
176
|
setTimeout(() => {
|
|
140
|
-
this.requeuec = false
|
|
177
|
+
this.requeuec = false;
|
|
141
178
|
}, 2000);
|
|
142
179
|
}
|
|
143
|
-
if(data ===
|
|
144
|
-
this.createc = true
|
|
180
|
+
if (data === "create") {
|
|
181
|
+
this.createc = true;
|
|
145
182
|
setTimeout(() => {
|
|
146
|
-
this.createc = false
|
|
183
|
+
this.createc = false;
|
|
147
184
|
}, 2000);
|
|
148
185
|
}
|
|
149
|
-
}
|
|
150
186
|
},
|
|
187
|
+
},
|
|
151
188
|
created() {
|
|
152
189
|
return this.fetchData();
|
|
153
190
|
},
|
|
@@ -234,5 +271,5 @@ const app = Vue.component('app', {
|
|
|
234
271
|
<popup-message :deletec="deletec" :requeuec="requeuec" :createc="createc"></popup-message>
|
|
235
272
|
<new-job v-if="showNewJob" v-on:popup-message="popupmessage('create')" v-on:refresh-data="fetchData"></new-job>
|
|
236
273
|
</div>
|
|
237
|
-
|
|
238
|
-
})
|
|
274
|
+
`,
|
|
275
|
+
});
|
package/public/app/js/newJob.js
CHANGED
|
@@ -1,35 +1,48 @@
|
|
|
1
|
-
const newJob = Vue.component(
|
|
2
|
-
data: () =>({
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
const newJob = Vue.component("new-job", {
|
|
2
|
+
data: () => ({
|
|
3
|
+
jobDataParseError: "",
|
|
4
|
+
jobName: "",
|
|
5
|
+
jobSchedule: "",
|
|
6
|
+
jobRepeatEvery: "",
|
|
6
7
|
jobData: `{ "name": "Your medatada goes here..." }`,
|
|
7
8
|
}),
|
|
8
|
-
props: [
|
|
9
|
+
props: ["job"],
|
|
9
10
|
methods: {
|
|
10
|
-
clear(){
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
clear() {
|
|
12
|
+
(this.jobDataParseError = ""),
|
|
13
|
+
(this.jobName = ""),
|
|
14
|
+
(this.jobSchedule = ""),
|
|
15
|
+
(this.jobRepeatEvery = ""),
|
|
16
|
+
(this.jobData = `{ "name": "Your medatada goes here..." }`);
|
|
15
17
|
},
|
|
16
|
-
create(){
|
|
18
|
+
create() {
|
|
17
19
|
const url = `api/jobs/create`;
|
|
20
|
+
|
|
21
|
+
let jobData = "";
|
|
22
|
+
try {
|
|
23
|
+
jobData = JSON.parse(this.jobData);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
this.jobDataParseError = err.message;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
let body = {
|
|
19
30
|
jobName: this.jobName,
|
|
20
31
|
jobSchedule: this.jobSchedule,
|
|
21
32
|
jobRepeatEvery: this.jobRepeatEvery,
|
|
22
|
-
jobData:
|
|
33
|
+
jobData: jobData,
|
|
23
34
|
};
|
|
24
|
-
return axios
|
|
25
|
-
.
|
|
26
|
-
.then(
|
|
27
|
-
|
|
28
|
-
this.$emit(
|
|
35
|
+
return axios
|
|
36
|
+
.post(url, body)
|
|
37
|
+
.then((result) => result.data)
|
|
38
|
+
.then((data) => {
|
|
39
|
+
this.$emit("popup-message");
|
|
40
|
+
this.$emit("refresh-data");
|
|
41
|
+
this.$refs.Close.click();
|
|
29
42
|
this.clear();
|
|
30
43
|
})
|
|
31
|
-
.catch(console.log)
|
|
32
|
-
}
|
|
44
|
+
.catch(console.log);
|
|
45
|
+
},
|
|
33
46
|
},
|
|
34
47
|
template: `
|
|
35
48
|
<div class="modal fade" id="modalNewJob" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
|
@@ -61,15 +74,16 @@ const newJob = Vue.component('new-job', {
|
|
|
61
74
|
<div class="form-group">
|
|
62
75
|
<label for="jobData">Job Metadata</label>
|
|
63
76
|
<prism-editor class="json-editor" :lineNumbers="true" v-model="jobData" language="json"></prism-editor>
|
|
77
|
+
<small class="form-text text-muted">{{jobDataParseError}}</small>
|
|
64
78
|
</div>
|
|
65
79
|
</form>
|
|
66
80
|
</div>
|
|
67
81
|
<div class="modal-footer">
|
|
68
|
-
<button type="button" class="btn btn-info"
|
|
82
|
+
<button type="button" class="btn btn-info" @click="create()">Create Job</button>
|
|
69
83
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
|
70
84
|
</div>
|
|
71
85
|
</div>
|
|
72
86
|
</div>
|
|
73
87
|
</div>
|
|
74
|
-
|
|
75
|
-
})
|
|
88
|
+
`,
|
|
89
|
+
});
|
package/public/app/js/sidebar.js
CHANGED
|
@@ -1,41 +1,66 @@
|
|
|
1
|
-
const sidebar = Vue.component(
|
|
2
|
-
props: [
|
|
1
|
+
const sidebar = Vue.component("sidebar", {
|
|
2
|
+
props: ["overview", "pagesize", "loading"],
|
|
3
3
|
computed: {
|
|
4
4
|
sortedArray() {
|
|
5
|
-
function compare(a, b){
|
|
5
|
+
function compare(a, b) {
|
|
6
6
|
let displayNameA = a.displayName.toLowerCase();
|
|
7
7
|
let displayNameB = b.displayName.toLowerCase();
|
|
8
|
-
if (displayNameA ===
|
|
9
|
-
|
|
10
|
-
if (displayNameA
|
|
11
|
-
return -1;
|
|
12
|
-
if (displayNameA > displayNameB)
|
|
13
|
-
return 1;
|
|
8
|
+
if (displayNameA === "all jobs" || displayNameB === "all jobs") return;
|
|
9
|
+
if (displayNameA < displayNameB) return -1;
|
|
10
|
+
if (displayNameA > displayNameB) return 1;
|
|
14
11
|
return 0;
|
|
15
12
|
}
|
|
16
13
|
|
|
17
14
|
return this.overview.sort(compare);
|
|
18
|
-
}
|
|
15
|
+
},
|
|
19
16
|
},
|
|
20
17
|
methods: {
|
|
21
|
-
flexgrow(number){
|
|
22
|
-
return Math.log2(1 + number)
|
|
18
|
+
flexgrow(number) {
|
|
19
|
+
return Math.log2(1 + number);
|
|
23
20
|
},
|
|
24
|
-
searchSpecificJob(job, type){
|
|
25
|
-
if(job ===
|
|
26
|
-
if(type){
|
|
27
|
-
this.$emit(
|
|
21
|
+
searchSpecificJob(job, type) {
|
|
22
|
+
if (job === "All Jobs") {
|
|
23
|
+
if (type) {
|
|
24
|
+
this.$emit(
|
|
25
|
+
"search-sidebar",
|
|
26
|
+
"",
|
|
27
|
+
"",
|
|
28
|
+
"",
|
|
29
|
+
this.pagesize,
|
|
30
|
+
"",
|
|
31
|
+
"",
|
|
32
|
+
type,
|
|
33
|
+
""
|
|
34
|
+
);
|
|
28
35
|
} else {
|
|
29
|
-
this.$emit(
|
|
36
|
+
this.$emit(
|
|
37
|
+
"search-sidebar",
|
|
38
|
+
"",
|
|
39
|
+
"",
|
|
40
|
+
"",
|
|
41
|
+
this.pagesize,
|
|
42
|
+
"",
|
|
43
|
+
"",
|
|
44
|
+
"",
|
|
45
|
+
""
|
|
46
|
+
);
|
|
30
47
|
}
|
|
48
|
+
} else if (type) {
|
|
49
|
+
this.$emit(
|
|
50
|
+
"search-sidebar",
|
|
51
|
+
job,
|
|
52
|
+
"",
|
|
53
|
+
"",
|
|
54
|
+
this.pagesize,
|
|
55
|
+
"",
|
|
56
|
+
"",
|
|
57
|
+
type,
|
|
58
|
+
""
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
this.$emit("search-sidebar", job, "", "", this.pagesize, "", "", "");
|
|
31
62
|
}
|
|
32
|
-
|
|
33
|
-
this.$emit('search-sidebar',job,'','',this.pagesize,'','',type,'',)
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
this.$emit('search-sidebar', job, '','',this.pagesize,'','','',);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
63
|
+
},
|
|
39
64
|
},
|
|
40
65
|
template: `
|
|
41
66
|
<div class="col sidebar">
|
|
@@ -92,5 +117,5 @@ const sidebar = Vue.component('sidebar', {
|
|
|
92
117
|
</div>
|
|
93
118
|
</div> <!-- row -->
|
|
94
119
|
</div> <!-- div -->
|
|
95
|
-
|
|
96
|
-
})
|
|
120
|
+
`,
|
|
121
|
+
});
|
package/public/app/js/topbar.js
CHANGED
|
@@ -16,13 +16,23 @@ const topbar = Vue.component("topbar", {
|
|
|
16
16
|
{ text: "Running", value: "running", class: "text-warning" },
|
|
17
17
|
{ text: "Completed", value: "completed", class: "text-success" },
|
|
18
18
|
{ text: "Failed", value: "failed", class: "text-danger" },
|
|
19
|
-
{ text: "Repeating", value: "repeating", class: "text-info" }
|
|
20
|
-
]
|
|
19
|
+
{ text: "Repeating", value: "repeating", class: "text-info" },
|
|
20
|
+
],
|
|
21
21
|
}),
|
|
22
22
|
methods: {
|
|
23
23
|
submit() {
|
|
24
|
-
this.$emit(
|
|
25
|
-
|
|
24
|
+
this.$emit(
|
|
25
|
+
"search-form",
|
|
26
|
+
this.name,
|
|
27
|
+
this.search,
|
|
28
|
+
this.property,
|
|
29
|
+
this.limit,
|
|
30
|
+
this.skip,
|
|
31
|
+
this.refresh,
|
|
32
|
+
this.state,
|
|
33
|
+
this.object
|
|
34
|
+
);
|
|
35
|
+
},
|
|
26
36
|
},
|
|
27
37
|
template: `
|
|
28
38
|
<form @submit.prevent="submit">
|
|
@@ -81,5 +91,5 @@ const topbar = Vue.component("topbar", {
|
|
|
81
91
|
</div>
|
|
82
92
|
</div>
|
|
83
93
|
</form>
|
|
84
|
-
|
|
94
|
+
`,
|
|
85
95
|
});
|
package/.editorconfig
DELETED
package/.idea/agendash.iml
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="WEB_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager">
|
|
4
|
-
<content url="file://$MODULE_DIR$">
|
|
5
|
-
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
6
|
-
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
7
|
-
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
-
</content>
|
|
9
|
-
<orderEntry type="inheritedJdk" />
|
|
10
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
11
|
-
</component>
|
|
12
|
-
</module>
|