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.
Files changed (39) hide show
  1. package/README.md +59 -22
  2. package/app.js +9 -5
  3. package/bin/agendash-standalone-fastify.js +61 -0
  4. package/bin/agendash-standalone-hapi.js +36 -18
  5. package/bin/agendash-standalone-koa.js +30 -14
  6. package/bin/agendash-standalone.js +44 -19
  7. package/lib/controllers/agendash.js +228 -110
  8. package/lib/csp.js +28 -0
  9. package/lib/middlewares/README.md +3 -1
  10. package/lib/middlewares/express.js +43 -17
  11. package/lib/middlewares/fastify.js +77 -0
  12. package/lib/middlewares/hapi.js +58 -33
  13. package/lib/middlewares/koa.js +29 -20
  14. package/package.json +37 -35
  15. package/public/app/js/confirmDelete.js +14 -13
  16. package/public/app/js/confirmDeleteMulti.js +14 -13
  17. package/public/app/js/confirmRequeue.js +14 -13
  18. package/public/app/js/confirmRequeueMulti.js +15 -14
  19. package/public/app/js/confirms.js +4 -4
  20. package/public/app/js/jobdetail.js +9 -9
  21. package/public/app/js/joblist.js +50 -43
  22. package/public/app/js/main.js +109 -72
  23. package/public/app/js/newJob.js +37 -23
  24. package/public/app/js/sidebar.js +51 -26
  25. package/public/app/js/topbar.js +15 -5
  26. package/.editorconfig +0 -7
  27. package/.idea/agendash.iml +0 -12
  28. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  29. package/.idea/jsLibraryMappings.xml +0 -6
  30. package/.idea/misc.xml +0 -92
  31. package/.idea/modules.xml +0 -8
  32. package/.idea/vcs.xml +0 -6
  33. package/.travis.yml +0 -27
  34. package/.vscode/launch.json +0 -15
  35. package/History.md +0 -106
  36. package/renovate.json +0 -5
  37. package/test/test-express.js +0 -82
  38. package/test/test-hapi.js +0 -106
  39. package/test/test-koa.js +0 -85
@@ -1,76 +1,101 @@
1
- const path = require('path');
2
- const pack = require('../../package.json');
1
+ const path = require("path");
2
+ const pack = require("../../package.json");
3
+ const csp = require("../csp");
3
4
 
4
- module.exports = agendash => {
5
- const {api, requeueJobs, deleteJobs, createJob} = agendash;
5
+ module.exports = (agendash) => {
6
+ const { api, requeueJobs, deleteJobs, createJob } = agendash;
6
7
  return {
7
8
  pkg: pack,
8
9
  register: (server, options) => {
10
+ server.ext("onPreResponse", (req, h) => {
11
+ req.response.header("Content-Security-Policy", csp);
12
+ return h.continue;
13
+ });
14
+
9
15
  server.route([
10
16
  {
11
- method: 'GET',
12
- path: '/{param*}',
17
+ method: "GET",
18
+ path: "/{param*}",
13
19
  handler: {
14
20
  directory: {
15
- path: path.join(__dirname, '../../public')
16
- }
21
+ path: path.join(__dirname, "../../public"),
22
+ },
17
23
  },
18
24
  config: {
19
- auth: options.auth || false
20
- }
25
+ auth: options.auth || false,
26
+ },
21
27
  },
22
28
  {
23
- method: 'GET',
24
- path: '/api',
29
+ method: "GET",
30
+ path: "/api",
25
31
  handler(request) {
26
- const {job, state, limit, skip, q, property, isObjectId} = request.query;
27
- return api(job, state, {query: q, property, isObjectId, skip, limit});
32
+ const {
33
+ job,
34
+ state,
35
+ limit,
36
+ skip,
37
+ q,
38
+ property,
39
+ isObjectId,
40
+ } = request.query;
41
+ return api(job, state, {
42
+ query: q,
43
+ property,
44
+ isObjectId,
45
+ skip,
46
+ limit,
47
+ });
28
48
  },
29
49
  config: {
30
- auth: options.auth || false
31
- }
50
+ auth: options.auth || false,
51
+ },
32
52
  },
33
53
  {
34
- method: 'POST',
35
- path: '/api/jobs/requeue',
54
+ method: "POST",
55
+ path: "/api/jobs/requeue",
36
56
  handler(request) {
37
57
  return requeueJobs(request.payload.jobIds);
38
58
  },
39
59
  config: {
40
- auth: options.auth || false
41
- }
60
+ auth: options.auth || false,
61
+ },
42
62
  },
43
63
  {
44
- method: 'POST',
45
- path: '/api/jobs/delete',
64
+ method: "POST",
65
+ path: "/api/jobs/delete",
46
66
  async handler(request, h) {
47
67
  const deleted = await deleteJobs(request.payload.jobIds);
48
68
  if (deleted) {
49
- return h.response({deleted: true});
69
+ return h.response({ deleted: true });
50
70
  }
51
71
 
52
72
  return h.code(404);
53
73
  },
54
74
  config: {
55
- auth: options.auth || false
56
- }
75
+ auth: options.auth || false,
76
+ },
57
77
  },
58
78
  {
59
- method: 'POST',
60
- path: '/api/jobs/create',
79
+ method: "POST",
80
+ path: "/api/jobs/create",
61
81
  async handler(request, h) {
62
- const created = await createJob(request.payload.jobName, request.payload.jobSchedule, request.payload.jobRepeatEvery, request.payload.jobData);
82
+ const created = await createJob(
83
+ request.payload.jobName,
84
+ request.payload.jobSchedule,
85
+ request.payload.jobRepeatEvery,
86
+ request.payload.jobData
87
+ );
63
88
  if (created) {
64
- return h.response({created: true});
89
+ return h.response({ created: true });
65
90
  }
66
91
 
67
92
  return h.code(404);
68
93
  },
69
94
  config: {
70
- auth: options.auth || false
71
- }
72
- }
95
+ auth: options.auth || false,
96
+ },
97
+ },
73
98
  ]);
74
- }
99
+ },
75
100
  };
76
101
  };
@@ -1,28 +1,42 @@
1
- const path = require('path');
2
- const bodyParser = require('koa-bodyparser');
3
- const Router = require('koa-router');
4
- const koaStatic = require('koa-static');
1
+ const path = require("path");
2
+ const bodyParser = require("koa-bodyparser");
3
+ const Router = require("koa-router");
4
+ const koaStatic = require("koa-static");
5
+ const csp = require("../csp");
5
6
 
6
- module.exports = agendash => {
7
+ module.exports = (agendash) => {
7
8
  const middlewares = [];
8
9
 
9
- middlewares.push(koaStatic(path.resolve(__dirname, '../../public'), {defer: true}));
10
+ middlewares.push(async (ctx, next) => {
11
+ await next();
12
+ ctx.set("Content-Security-Policy", csp);
13
+ });
14
+
15
+ middlewares.push(
16
+ koaStatic(path.resolve(__dirname, "../../public"), { defer: true })
17
+ );
10
18
 
11
19
  middlewares.push(bodyParser());
12
20
 
13
21
  const routerApi = new Router();
14
22
 
15
- routerApi.get('/api', async({response, query}) => {
16
- const {job, state, skip, limit, q, property, isObjectId} = query;
23
+ routerApi.get("/api", async ({ response, query }) => {
24
+ const { job, state, skip, limit, q, property, isObjectId } = query;
17
25
  try {
18
- response.body = await agendash.api(job, state, {query: q, property, isObjectId, skip, limit});
26
+ response.body = await agendash.api(job, state, {
27
+ query: q,
28
+ property,
29
+ isObjectId,
30
+ skip,
31
+ limit,
32
+ });
19
33
  } catch (error) {
20
34
  response.status = 400;
21
35
  response.body = error;
22
36
  }
23
37
  });
24
38
 
25
- routerApi.post('/api/jobs/requeue', async({request, response}) => {
39
+ routerApi.post("/api/jobs/requeue", async ({ request, response }) => {
26
40
  try {
27
41
  response.body = await agendash.requeueJobs(request.body.jobIds);
28
42
  } catch (error) {
@@ -31,11 +45,11 @@ module.exports = agendash => {
31
45
  }
32
46
  });
33
47
 
34
- routerApi.post('/api/jobs/delete', async({request, response}) => {
48
+ routerApi.post("/api/jobs/delete", async ({ request, response }) => {
35
49
  try {
36
50
  await agendash.deleteJobs(request.body.jobIds);
37
51
  response.body = {
38
- deleted: true
52
+ deleted: true,
39
53
  };
40
54
  } catch (error) {
41
55
  response.status = 404;
@@ -43,18 +57,13 @@ module.exports = agendash => {
43
57
  }
44
58
  });
45
59
 
46
- routerApi.post('/api/jobs/create', async({request, response}) => {
47
- const {
48
- jobData,
49
- jobName,
50
- jobSchedule,
51
- jobRepeatEvery
52
- } = request.body;
60
+ routerApi.post("/api/jobs/create", async ({ request, response }) => {
61
+ const { jobData, jobName, jobSchedule, jobRepeatEvery } = request.body;
53
62
 
54
63
  try {
55
64
  await agendash.createJob(jobName, jobSchedule, jobRepeatEvery, jobData);
56
65
  response.body = {
57
- created: true
66
+ created: true,
58
67
  };
59
68
  } catch (error) {
60
69
  response.status = 404;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agendash",
3
- "version": "2.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "A modern dashboard for Agenda.js with Pagination and Search capabilities",
5
5
  "main": "app.js",
6
6
  "bin": "bin/agendash-standalone.js",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "run-p lint ava",
12
- "lint": "xo",
12
+ "lint": "eslint ./",
13
13
  "ava": "ava -v -c 1"
14
14
  },
15
15
  "keywords": [
@@ -27,8 +27,17 @@
27
27
  },
28
28
  "homepage": "https://github.com/agenda/agendash#readme",
29
29
  "license": "MIT",
30
+ "files": [
31
+ "bin",
32
+ "lib",
33
+ "public",
34
+ "app.js",
35
+ "*.png",
36
+ "Dockerfile",
37
+ "entrypoint.sh"
38
+ ],
30
39
  "dependencies": {
31
- "agenda": "^3.1.0 || ^4.0.0",
40
+ "agenda": "^4.2.1",
32
41
  "body-parser": "^1.15.0",
33
42
  "commander": "^2.9.0",
34
43
  "express": "^4.0.0",
@@ -36,38 +45,31 @@
36
45
  "semver": "^7.3.4"
37
46
  },
38
47
  "devDependencies": {
39
- "@hapi/hapi": "^19.1.1",
40
- "@hapi/inert": "^6.0.1",
41
- "ava": "^3.5.1",
42
- "koa": "^2.13.1",
43
- "koa-bodyparser": "^4.3.0",
44
- "koa-router": "^10.0.0",
45
- "koa-static": "^5.0.0",
46
- "npm-run-all": "^4.1.2",
47
- "supertest": "^6.1.1",
48
- "xo": "^0.37.1"
48
+ "@hapi/hapi": "^20.2.1",
49
+ "@hapi/inert": "^6.0.5",
50
+ "ava": "3.15.0",
51
+ "eslint": "7.19.0",
52
+ "fastify": "^3.24.0",
53
+ "fastify-static": "^4.5.0",
54
+ "koa": "2.13.1",
55
+ "koa-bodyparser": "4.3.0",
56
+ "koa-router": "10.0.0",
57
+ "koa-static": "5.0.0",
58
+ "npm-run-all": "4.1.5",
59
+ "prettier": "2.2.1",
60
+ "supertest": "^6.2.2"
49
61
  },
50
- "xo": {
51
- "space": 2,
52
- "rules": {
53
- "space-before-function-paren": [
54
- "error",
55
- "never"
56
- ],
57
- "max-params": [
58
- "error",
59
- 5
60
- ],
61
- "max-nested-callbacks": [
62
- "error",
63
- 5
64
- ]
62
+ "eslintConfig": {
63
+ "parserOptions": {
64
+ "ecmaVersion": 2019
65
+ },
66
+ "env": {
67
+ "es6": true,
68
+ "node": true
65
69
  },
66
- "envs": [
67
- "node"
68
- ],
69
- "ignores": [
70
- "public/**/*"
71
- ]
72
- }
70
+ "extends": "eslint:recommended"
71
+ },
72
+ "eslintIgnore": [
73
+ "public"
74
+ ]
73
75
  }
@@ -1,17 +1,18 @@
1
- const confirmDelete = Vue.component('confirm-delete', {
2
- props: ['job'],
1
+ const confirmDelete = Vue.component("confirm-delete", {
2
+ props: ["job"],
3
3
  methods: {
4
- deleteOne(id){
4
+ deleteOne(id) {
5
5
  const url = `api/jobs/delete`;
6
- let body = {jobIds: [id]};
7
- return axios.post(url, body)
8
- .then(result => result.data)
9
- .then(data => {
10
- this.$emit('popup-message', 'delete');
11
- this.$emit('refresh-data');
6
+ let body = { jobIds: [id] };
7
+ return axios
8
+ .post(url, body)
9
+ .then((result) => result.data)
10
+ .then((data) => {
11
+ this.$emit("popup-message", "delete");
12
+ this.$emit("refresh-data");
12
13
  })
13
- .catch(console.log)
14
- }
14
+ .catch(console.log);
15
+ },
15
16
  },
16
17
  template: `
17
18
  <div class="modal fade" id="modalDeleteSure" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
@@ -35,5 +36,5 @@ const confirmDelete = Vue.component('confirm-delete', {
35
36
  </div>
36
37
  </div>
37
38
  </div>
38
- `
39
- })
39
+ `,
40
+ });
@@ -1,17 +1,18 @@
1
- const confirmDeleteMulti = Vue.component('confirm-multi-delete', {
2
- props: ['jobs'],
1
+ const confirmDeleteMulti = Vue.component("confirm-multi-delete", {
2
+ props: ["jobs"],
3
3
  methods: {
4
- deleteMulti(ids){
4
+ deleteMulti(ids) {
5
5
  const url = `api/jobs/delete`;
6
- let body = {jobIds: ids};
7
- return axios.post(url, body)
8
- .then(result => result.data)
9
- .then(data => {
10
- this.$emit('popup-message', 'delete');
11
- this.$emit('refresh-data');
6
+ let body = { jobIds: ids };
7
+ return axios
8
+ .post(url, body)
9
+ .then((result) => result.data)
10
+ .then((data) => {
11
+ this.$emit("popup-message", "delete");
12
+ this.$emit("refresh-data");
12
13
  })
13
- .catch(console.log)
14
- }
14
+ .catch(console.log);
15
+ },
15
16
  },
16
17
  template: `
17
18
  <div class="modal fade" id="modalDeleteSureMulti" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
@@ -40,5 +41,5 @@ const confirmDeleteMulti = Vue.component('confirm-multi-delete', {
40
41
  </div>
41
42
  </div>
42
43
  </div>
43
- `
44
- })
44
+ `,
45
+ });
@@ -1,17 +1,18 @@
1
- const confirmRequeue = Vue.component('confirm-requeue', {
2
- props: ['job'],
1
+ const confirmRequeue = Vue.component("confirm-requeue", {
2
+ props: ["job"],
3
3
  methods: {
4
- RequeueOne(id){
4
+ RequeueOne(id) {
5
5
  const url = `api/jobs/requeue`;
6
- let body = {jobIds: [id]};
7
- return axios.post(url, body)
8
- .then(result => result.data)
9
- .then(data => {
10
- this.$emit('popup-message');
11
- this.$emit('refresh-data');
6
+ let body = { jobIds: [id] };
7
+ return axios
8
+ .post(url, body)
9
+ .then((result) => result.data)
10
+ .then((data) => {
11
+ this.$emit("popup-message");
12
+ this.$emit("refresh-data");
12
13
  })
13
- .catch(console.log)
14
- }
14
+ .catch(console.log);
15
+ },
15
16
  },
16
17
  template: `
17
18
  <div class="modal fade" id="modalRequeueSure" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
@@ -35,5 +36,5 @@ const confirmRequeue = Vue.component('confirm-requeue', {
35
36
  </div>
36
37
  </div>
37
38
  </div>
38
- `
39
- })
39
+ `,
40
+ });
@@ -1,18 +1,19 @@
1
- const confirmRequeueMulti = Vue.component('confirm-multi-requeue', {
2
- props: ['jobs'],
1
+ const confirmRequeueMulti = Vue.component("confirm-multi-requeue", {
2
+ props: ["jobs"],
3
3
  methods: {
4
- RequeueMulti(ids){
4
+ RequeueMulti(ids) {
5
5
  const url = `api/jobs/requeue`;
6
- let body = {jobIds: ids};
7
- return axios.post(url, body)
8
- .then(result => result.data)
9
- .then(data => {
10
- this.$emit('popup-message');
11
- this.$emit('refresh-data');
12
- this.$emit('ready-clean')
6
+ let body = { jobIds: ids };
7
+ return axios
8
+ .post(url, body)
9
+ .then((result) => result.data)
10
+ .then((data) => {
11
+ this.$emit("popup-message");
12
+ this.$emit("refresh-data");
13
+ this.$emit("ready-clean");
13
14
  })
14
- .catch(console.log)
15
- }
15
+ .catch(console.log);
16
+ },
16
17
  },
17
18
  template: `
18
19
  <div class="modal fade" id="modalRequeueSureMulti" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
@@ -40,5 +41,5 @@ const confirmRequeueMulti = Vue.component('confirm-multi-requeue', {
40
41
  </div>
41
42
  </div>
42
43
  </div>
43
- `
44
- })
44
+ `,
45
+ });
@@ -1,8 +1,8 @@
1
- const popupmessage = Vue.component('popup-message', {
2
- props: ['job','deletec','requeuec','createc'],
1
+ const popupmessage = Vue.component("popup-message", {
2
+ props: ["job", "deletec", "requeuec", "createc"],
3
3
  template: `
4
4
  <div v-if="deletec" class="alert alert-success popupmessage">Job Deleted successfull</div>
5
5
  <div v-else-if="requeuec" class="alert alert-success popupmessage">Job Requeue successfull</div>
6
6
  <div v-else-if="createc" class="alert alert-success popupmessage">Job Created successfull</div>
7
- `
8
- })
7
+ `,
8
+ });
@@ -1,14 +1,14 @@
1
- const jobDetail = Vue.component('job-detail', {
2
- props: ['job'],
1
+ const jobDetail = Vue.component("job-detail", {
2
+ props: ["job"],
3
3
  filters: {
4
- formatJSON(jsonstr){
4
+ formatJSON(jsonstr) {
5
5
  return JSON.stringify(jsonstr, null, 2);
6
6
  },
7
7
  },
8
8
  methods: {
9
- formatDate(date){
10
- return moment(date).format('DD-MM-YYYY HH:mm:ss')
11
- }
9
+ formatDate(date) {
10
+ return moment(date).format("DD-MM-YYYY HH:mm:ss");
11
+ },
12
12
  },
13
13
  template: `
14
14
  <div class="modal fade" id="modalData" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
@@ -24,7 +24,7 @@ const jobDetail = Vue.component('job-detail', {
24
24
  <div class="modal-body">
25
25
  <div class="row my-3">
26
26
  <div class="col">
27
- <p><strong>Next run starts: </strong>{{ formatDate(job.job.lastRunAt) }}</p>
27
+ <p><strong>Next run starts: </strong>{{ formatDate(job.job.nextRunAt) }}</p>
28
28
  <p><strong>Last run started: </strong>{{ formatDate(job.job.lastRunAt) }}</p>
29
29
  </div>
30
30
  </div>
@@ -44,5 +44,5 @@ const jobDetail = Vue.component('job-detail', {
44
44
  </div>
45
45
  </div>
46
46
  </div>
47
- `
48
- })
47
+ `,
48
+ });