mirror of
https://github.com/jpros/tacticalrmm-web.git
synced 2026-01-20 03:50:21 +00:00
scripts rework
This commit is contained in:
275
package-lock.json
generated
275
package-lock.json
generated
@@ -3572,9 +3572,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@quasar/app": {
|
||||
"version": "2.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/app/-/app-2.1.9.tgz",
|
||||
"integrity": "sha512-KhO78w0BBRVGkH5OQhr6IuP9pg26c8DeI/E26TMekjD9DVHgWV8jtxIC6kBseo0NiC6noYHf632aNjXklruwnQ==",
|
||||
"version": "2.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/app/-/app-2.1.11.tgz",
|
||||
"integrity": "sha512-MX01izfk1cAFcRVj4IpU6fneQW14oeq4oAPdCqJDjYY1I1M3kYBFG+WvgfvZJxfTGiaVNP6xKWKkU1wIUNgbIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@quasar/babel-preset-app": "2.0.1",
|
||||
@@ -3603,7 +3603,6 @@
|
||||
"express": "4.17.1",
|
||||
"fast-glob": "3.2.4",
|
||||
"file-loader": "6.2.0",
|
||||
"flat": "^5.0.2",
|
||||
"fork-ts-checker-webpack-plugin": "4.1.6",
|
||||
"friendly-errors-webpack-plugin": "1.7.0",
|
||||
"fs-extra": "9.0.1",
|
||||
@@ -4071,9 +4070,9 @@
|
||||
}
|
||||
},
|
||||
"@quasar/extras": {
|
||||
"version": "1.9.10",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.9.10.tgz",
|
||||
"integrity": "sha512-pVM2lLiX2vHhibL4VUCjAfYhhYtQLDLYccq/ee6PdpyJ394lJQSkFnnGntcmpQk4QPcgIQ8GZSVpsUd1qgabaw=="
|
||||
"version": "1.9.11",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/extras/-/extras-1.9.11.tgz",
|
||||
"integrity": "sha512-HI50hWZVfdcdg1TKldQxgZRr05tEX4sSJQ5TAx8no5RghjrHpSuVuwDstIFmsUM0WgTGzE89S3Aqgvr7tS4dIg=="
|
||||
},
|
||||
"@quasar/fastclick": {
|
||||
"version": "1.1.4",
|
||||
@@ -4082,23 +4081,145 @@
|
||||
"dev": true
|
||||
},
|
||||
"@quasar/quasar-app-extension-testing": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/quasar-app-extension-testing/-/quasar-app-extension-testing-1.0.0.tgz",
|
||||
"integrity": "sha512-IuHseh5YIaf4JPlsjehkB2pLUaWuFMsAxFq83+06btO9dMSQpvBXrGhA6O0N1rXUM/EXBI8Mi7pwJWi+78i4LA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@quasar/quasar-app-extension-testing/-/quasar-app-extension-testing-1.0.3.tgz",
|
||||
"integrity": "sha512-x3uQpsshEfSyDW/mnQeS5nUOsr3thHQn74qdlXRr7NlxzlsiV+vHSZiGlCj5Q+WNdEecWsjjqAVrwlb7FkP1CQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"execa": "^1.0.0",
|
||||
"strip-ansi": "^5.0.0"
|
||||
"chalk": "^4.1.0",
|
||||
"execa": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
|
||||
"integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"human-signals": "^1.1.1",
|
||||
"is-stream": "^2.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^4.0.0",
|
||||
"onetime": "^5.1.0",
|
||||
"signal-exit": "^3.0.2",
|
||||
"strip-final-newline": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"dev": true
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4206,9 +4327,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
|
||||
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
|
||||
"version": "3.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
||||
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
@@ -4255,9 +4376,9 @@
|
||||
}
|
||||
},
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.14.tgz",
|
||||
"integrity": "sha512-uFTLwu94TfUFMToXNgRZikwPuZdOtDgs3syBtAIr/OXorL1kJqUJT9qCLnRZ5KBOWfZQikQ2xKgR2tnDj1OgDA==",
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.15.tgz",
|
||||
"integrity": "sha512-pb71P0BrBAx7cQE+/7QnA1HTQUkdBKMlkPY7lHUMn0YvPJkL2UA+KW3BdWQ309IT+i9En/qm45ZxpjIcpgEhNQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
@@ -6524,6 +6645,18 @@
|
||||
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
|
||||
"dev": true
|
||||
},
|
||||
"clipboard": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
|
||||
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"good-listener": "^1.2.2",
|
||||
"select": "^1.1.2",
|
||||
"tiny-emitter": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
@@ -7287,9 +7420,9 @@
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
|
||||
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
|
||||
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==",
|
||||
"dev": true
|
||||
},
|
||||
"core-js-compat": {
|
||||
@@ -8126,6 +8259,13 @@
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"delegate": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
|
||||
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -8671,9 +8811,9 @@
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.616",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.616.tgz",
|
||||
"integrity": "sha512-CI8L38UN2BEnqXw3/oRIQTmde0LiSeqWSRlPA42ZTYgJQ8fYenzAM2Z3ni+jtILTcrs5aiXZCGJ96Pm+3/yGyQ==",
|
||||
"version": "1.3.620",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.620.tgz",
|
||||
"integrity": "sha512-YbgWXUR2Mu+Fp6rm3GZ5YJdNo8SgZKLUTNSl2PNvdOcM8OIz07jRJnRkIaV9vdszFv9UUuGChh19w9qSuoLJgw==",
|
||||
"dev": true
|
||||
},
|
||||
"elementtree": {
|
||||
@@ -9618,12 +9758,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"flat": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
|
||||
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
|
||||
"dev": true
|
||||
},
|
||||
"flush-promises": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz",
|
||||
@@ -10053,6 +10187,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"good-listener": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
|
||||
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delegate": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"got": {
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
|
||||
@@ -10583,6 +10727,12 @@
|
||||
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
|
||||
"dev": true
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
|
||||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
|
||||
"dev": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@@ -14183,9 +14333,9 @@
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -14882,6 +15032,15 @@
|
||||
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"prismjs": {
|
||||
"version": "1.22.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz",
|
||||
"integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clipboard": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
@@ -15047,9 +15206,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"quasar": {
|
||||
"version": "1.14.6",
|
||||
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.14.6.tgz",
|
||||
"integrity": "sha512-EuVld48G2UiIOU3t2xRfLqYEj0choawWFd4cWs5Ea2TaDF+BR+JTTXovUI1kar8QBKMhU6i6ChTt8fyNATdbfQ=="
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/quasar/-/quasar-1.14.7.tgz",
|
||||
"integrity": "sha512-AP++F9xNEmzdK4zEjYBgEF0lifg3LBIrE24weUyQqS/jNQ22YT1cGyqDzWrfScaGLmRdm27R6eWLsbT4Qnh3Pg=="
|
||||
},
|
||||
"query-string": {
|
||||
"version": "4.3.4",
|
||||
@@ -15915,6 +16074,13 @@
|
||||
"commander": "^2.8.1"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@@ -16415,9 +16581,9 @@
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -16881,6 +17047,12 @@
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-final-newline": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
@@ -17333,6 +17505,13 @@
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
|
||||
"dev": true
|
||||
},
|
||||
"tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
@@ -18157,6 +18336,12 @@
|
||||
"vue-style-loader": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"vue-prism-editor": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-1.2.2.tgz",
|
||||
"integrity": "sha512-Lq2VgVygTx3Whn/tC8gD4m1ajA4lzSyCTqPLZA1Dq/ErbBaZA93FWRblwCoDR7AD2nXhGWuiTzb5ih3guzB7DA==",
|
||||
"dev": true
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.2.0.tgz",
|
||||
|
||||
14
package.json
14
package.json
@@ -9,20 +9,22 @@
|
||||
"test:unit": "quasar test --unit jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/extras": "^1.9.10",
|
||||
"@quasar/extras": "^1.9.11",
|
||||
"axios": "^0.21.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"qrcode.vue": "^1.7.0",
|
||||
"quasar": "^1.14.6"
|
||||
"quasar": "^1.14.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/app": "^2.1.9",
|
||||
"@quasar/app": "^2.1.11",
|
||||
"@quasar/cli": "^1.1.2",
|
||||
"@quasar/quasar-app-extension-testing": "^1.0.0",
|
||||
"@quasar/quasar-app-extension-testing": "^1.0.3",
|
||||
"@quasar/quasar-app-extension-testing-unit-jest": "^1.0.1",
|
||||
"core-js": "^3.6.5",
|
||||
"core-js": "^3.8.1",
|
||||
"flush-promises": "^1.0.2",
|
||||
"fs-extra": "^9.0.1"
|
||||
"fs-extra": "^9.0.1",
|
||||
"prismjs": "^1.22.0",
|
||||
"vue-prism-editor": "^1.2.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 4 Chrome versions",
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
<q-menu auto-close>
|
||||
<q-list dense style="min-width: 100px">
|
||||
<!-- script manager -->
|
||||
<q-item clickable v-close-popup @click="showScriptManager">
|
||||
<q-item clickable v-close-popup @click="showScriptManager = true">
|
||||
<q-item-section>Script Manager</q-item-section>
|
||||
</q-item>
|
||||
<!-- automation manager -->
|
||||
@@ -182,8 +182,11 @@
|
||||
</q-dialog>
|
||||
</div>
|
||||
<!-- Script Manager -->
|
||||
<ScriptManager />
|
||||
|
||||
<div class="q-pa-md q-gutter-sm">
|
||||
<q-dialog v-model="showScriptManager">
|
||||
<ScriptManager @close="showScriptManager = false" />
|
||||
</q-dialog>
|
||||
</div>
|
||||
<!-- Automation Manager -->
|
||||
<div class="q-pa-md q-gutter-sm">
|
||||
<q-dialog v-model="showAutomationManager">
|
||||
@@ -271,6 +274,7 @@ export default {
|
||||
bulkMode: null,
|
||||
showDeployment: false,
|
||||
showDebugLog: false,
|
||||
showScriptManager: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -296,9 +300,6 @@ export default {
|
||||
this.bulkMode = null;
|
||||
this.showBulkAction = false;
|
||||
},
|
||||
showScriptManager() {
|
||||
this.$store.commit("TOGGLE_SCRIPT_MANAGER", true);
|
||||
},
|
||||
edited() {
|
||||
this.$emit("edited");
|
||||
},
|
||||
|
||||
@@ -1,150 +1,250 @@
|
||||
<template>
|
||||
<div class="q-pa-md q-gutter-sm">
|
||||
<q-dialog :value="toggleScriptManager" @hide="hideScriptManager" @show="getScripts">
|
||||
<q-card style="min-width: 70vw">
|
||||
<q-bar>
|
||||
<q-btn @click="getScripts" class="q-mr-sm" dense flat push icon="refresh" />Script Manager
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<div class="q-pa-md">
|
||||
<div class="q-gutter-sm row">
|
||||
<div style="width: 60vw; max-width: 90vw">
|
||||
<q-card>
|
||||
<q-bar>
|
||||
<q-btn @click="getScripts" class="q-mr-sm" dense flat push icon="refresh" />Script Manager
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<div class="q-pa-md">
|
||||
<div class="q-gutter-sm row">
|
||||
<q-btn-dropdown icon="add" label="New" no-caps dense flat>
|
||||
<q-list dense>
|
||||
<q-item clickable v-close-popup @click="newScript">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="add" />
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label>New Script</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showScriptUploadModal = true">
|
||||
<q-item-section side>
|
||||
<q-icon size="xs" name="cloud_upload" />
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label>Upload Script</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
<q-btn
|
||||
label="Edit"
|
||||
:disable="!isRowSelected || isBuiltInScript(selectedScript.id)"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="edit"
|
||||
@click="editScript(selectedScript)"
|
||||
/>
|
||||
<q-btn
|
||||
label="Delete"
|
||||
:disable="!isRowSelected || isBuiltInScript(selectedScript.id)"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="delete"
|
||||
@click="deleteScript(selectedScript.id)"
|
||||
/>
|
||||
<q-btn
|
||||
label="View Code"
|
||||
:disable="!isRowSelected"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="remove_red_eye"
|
||||
@click="viewCode(selectedScript)"
|
||||
/>
|
||||
<q-btn
|
||||
label="Download Script"
|
||||
:disable="!isRowSelected"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="cloud_download"
|
||||
@click="downloadScript(selectedScript)"
|
||||
/>
|
||||
</div>
|
||||
<q-table
|
||||
style="min-height: 30vw; max-height: 30vw"
|
||||
dense
|
||||
:table-class="{ 'table-bgcolor': !$q.dark.isActive, 'table-bgcolor-dark': $q.dark.isActive }"
|
||||
class="settings-tbl-sticky scroll"
|
||||
:data="visibleScripts"
|
||||
:columns="columns"
|
||||
:visible-columns="visibleColumns"
|
||||
:pagination.sync="pagination"
|
||||
:filter="search"
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-bottom
|
||||
virtual-scroll
|
||||
flat
|
||||
:rows-per-page-options="[0]"
|
||||
>
|
||||
<template v-slot:header-cell-favorite="props">
|
||||
<q-th :props="props" auto-width>
|
||||
<q-icon name="star" color="yellow-8" size="sm" />
|
||||
</q-th>
|
||||
</template>
|
||||
<template v-slot:top>
|
||||
<q-btn
|
||||
label="New"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="add"
|
||||
@click="
|
||||
showScript('add');
|
||||
clearRow();
|
||||
"
|
||||
/>
|
||||
<q-btn
|
||||
label="Edit"
|
||||
:disable="scriptpk === null"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="edit"
|
||||
@click="showScript('edit')"
|
||||
/>
|
||||
<q-btn
|
||||
label="Delete"
|
||||
:disable="scriptpk === null || isBuiltInScript(scriptpk)"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="delete"
|
||||
@click="deleteScript"
|
||||
/>
|
||||
<q-btn
|
||||
label="View Code"
|
||||
:disable="scriptpk === null"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="remove_red_eye"
|
||||
@click="viewCode"
|
||||
/>
|
||||
<q-btn
|
||||
label="Download Script"
|
||||
:disable="scriptpk === null"
|
||||
dense
|
||||
flat
|
||||
push
|
||||
unelevated
|
||||
no-caps
|
||||
icon="cloud_download"
|
||||
@click="downloadScript"
|
||||
class="q-ml-sm"
|
||||
:label="showCommunityScripts ? 'Hide Community Scripts' : 'Show Community Scripts'"
|
||||
@click="setShowCommunityScripts(!showCommunityScripts)"
|
||||
/>
|
||||
<q-space />
|
||||
<q-toggle :value="showBuiltIn" label="Show Community Scripts" @input="showBuiltIn = !showBuiltIn" />
|
||||
</div>
|
||||
<q-table
|
||||
dense
|
||||
:table-class="{ 'table-bgcolor': !$q.dark.isActive, 'table-bgcolor-dark': $q.dark.isActive }"
|
||||
class="settings-tbl-sticky"
|
||||
:data="visibleScripts"
|
||||
:columns="columns"
|
||||
:visible-columns="visibleColumns"
|
||||
:pagination.sync="pagination"
|
||||
row-key="id"
|
||||
binary-state-sort
|
||||
hide-bottom
|
||||
virtual-scroll
|
||||
flat
|
||||
:rows-per-page-options="[0]"
|
||||
>
|
||||
<template slot="body" slot-scope="props" :props="props">
|
||||
<q-tr
|
||||
:class="rowSelectedClass(props.row.id)"
|
||||
@click="
|
||||
scriptpk = props.row.id;
|
||||
filename = props.row.filename;
|
||||
code = props.row.code;
|
||||
"
|
||||
>
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<q-td>
|
||||
{{ truncateText(props.row.description) }}
|
||||
<q-tooltip v-if="props.row.description.length >= 60" content-style="font-size: 12px">{{
|
||||
props.row.description
|
||||
}}</q-tooltip>
|
||||
</q-td>
|
||||
<q-td>{{ props.row.filename }}</q-td>
|
||||
<q-td>{{ props.row.shell }}</q-td>
|
||||
<q-td v-show="props.row.script_type === 'userdefined'">User Defined</q-td>
|
||||
<q-td v-show="props.row.script_type === 'builtin'">Community Uploaded</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
<q-card-section></q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section></q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="showScriptModal">
|
||||
<ScriptModal :mode="mode" :scriptpk="scriptpk" @close="showScriptModal = false" @uploaded="getScripts" />
|
||||
<q-input
|
||||
v-model="search"
|
||||
style="width: 300px"
|
||||
label="Search"
|
||||
dense
|
||||
outlined
|
||||
clearable
|
||||
class="q-pr-md q-pb-xs"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="search" color="primary" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
<template slot="body" slot-scope="props" :props="props">
|
||||
<q-tr
|
||||
:class="`${rowSelectedClass(props.row.id)} cursor-pointer`"
|
||||
@click="selectedScript = props.row"
|
||||
@contextmenu="selectedScript = props.row"
|
||||
>
|
||||
<!-- Context Menu -->
|
||||
<q-menu context-menu>
|
||||
<q-list dense style="min-width: 200px">
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="editScript(props.row)"
|
||||
id="context-edit"
|
||||
v-if="props.row.script_type !== 'builtin'"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="edit" />
|
||||
</q-item-section>
|
||||
<q-item-section>Edit</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="deleteScript(props.row.id)"
|
||||
id="context-delete"
|
||||
v-if="props.row.script_type !== 'builtin'"
|
||||
>
|
||||
<q-item-section side>
|
||||
<q-icon name="delete" />
|
||||
</q-item-section>
|
||||
<q-item-section>Delete</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-close-popup @click="favoriteScript(props.row)">
|
||||
<q-item-section side>
|
||||
<q-icon name="star" />
|
||||
</q-item-section>
|
||||
<q-item-section>{{ favoriteText(props.row.favorite) }}</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup @click="viewCode(props.row)" id="context-view">
|
||||
<q-item-section side>
|
||||
<q-icon name="remove_red_eye" />
|
||||
</q-item-section>
|
||||
<q-item-section>View Code</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item clickable v-close-popup @click="downloadScript(props.row)" id="context-download">
|
||||
<q-item-section side>
|
||||
<q-icon name="cloud_download" />
|
||||
</q-item-section>
|
||||
<q-item-section>Download Script</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<q-item clickable v-close-popup>
|
||||
<q-item-section>Close</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
<q-td>
|
||||
<q-icon v-if="props.row.favorite" color="yellow-8" name="star" size="sm" />
|
||||
</q-td>
|
||||
<q-td>{{ props.row.name }}</q-td>
|
||||
<q-td>{{ props.row.category }}</q-td>
|
||||
<q-td>{{ props.row.shell }}</q-td>
|
||||
<q-td>
|
||||
{{ truncateText(props.row.description) }}
|
||||
<q-tooltip v-if="props.row.description.length >= 60" content-style="font-size: 12px">{{
|
||||
props.row.description
|
||||
}}</q-tooltip>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
<q-separator />
|
||||
<q-card-section></q-card-section>
|
||||
</q-card>
|
||||
<q-dialog v-model="showScriptUploadModal">
|
||||
<ScriptUploadModal
|
||||
:script="selectedScript"
|
||||
:categories="categories"
|
||||
@close="showScriptUploadModal = false"
|
||||
@added="getScripts"
|
||||
/>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import { mapState } from "vuex";
|
||||
import ScriptModal from "@/components/modals/scripts/ScriptModal";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import ScriptUploadModal from "@/components/modals/scripts/ScriptUploadModal";
|
||||
import ScriptFormModal from "@/components/modals/scripts/ScriptFormModal";
|
||||
|
||||
export default {
|
||||
name: "ScriptManager",
|
||||
components: { ScriptModal },
|
||||
components: { ScriptUploadModal },
|
||||
mixins: [mixins],
|
||||
data() {
|
||||
return {
|
||||
mode: "add",
|
||||
scriptpk: null,
|
||||
showScriptModal: false,
|
||||
filename: null,
|
||||
code: null,
|
||||
showBuiltIn: true,
|
||||
scripts: [],
|
||||
selectedScript: {},
|
||||
showScriptUploadModal: false,
|
||||
search: "",
|
||||
pagination: {
|
||||
rowsPerPage: 0,
|
||||
sortBy: "script_type",
|
||||
sortBy: "favorite",
|
||||
descending: true,
|
||||
},
|
||||
columns: [
|
||||
{ name: "id", label: "ID", field: "id" },
|
||||
{
|
||||
name: "favorite",
|
||||
label: "",
|
||||
field: "favorite",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
label: "Name",
|
||||
@@ -153,16 +253,9 @@ export default {
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "desc",
|
||||
label: "Description",
|
||||
field: "description",
|
||||
align: "left",
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
name: "file",
|
||||
label: "File",
|
||||
field: "filename",
|
||||
name: "category",
|
||||
label: "Category",
|
||||
field: "category",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
},
|
||||
@@ -174,37 +267,57 @@ export default {
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: "script_type",
|
||||
label: "Type",
|
||||
field: "script_type",
|
||||
name: "desc",
|
||||
label: "Description",
|
||||
field: "description",
|
||||
align: "left",
|
||||
sortable: true,
|
||||
sortable: false,
|
||||
},
|
||||
],
|
||||
visibleColumns: ["name", "desc", "file", "shell", "script_type"],
|
||||
visibleColumns: ["favorite", "name", "category", "desc", "shell"],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getScripts() {
|
||||
this.clearRow();
|
||||
this.$store.dispatch("getScripts");
|
||||
},
|
||||
hideScriptManager() {
|
||||
this.$store.commit("TOGGLE_SCRIPT_MANAGER", false);
|
||||
},
|
||||
clearRow() {
|
||||
this.scriptpk = null;
|
||||
this.filename = null;
|
||||
},
|
||||
viewCode() {
|
||||
this.$q.dialog({
|
||||
title: this.filename,
|
||||
message: `<pre>${this.code}</pre>`,
|
||||
html: true,
|
||||
style: "width: 70vw; max-width: 80vw;",
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scripts = r.data;
|
||||
});
|
||||
},
|
||||
deleteScript() {
|
||||
setShowCommunityScripts(show) {
|
||||
this.$store.dispatch("setShowCommunityScripts", show);
|
||||
},
|
||||
clearRow() {
|
||||
this.selectedScript = {};
|
||||
},
|
||||
viewCode(script) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: ScriptFormModal,
|
||||
parent: this,
|
||||
script: script,
|
||||
readonly: true,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
},
|
||||
favoriteScript(script) {
|
||||
this.$q.loading.show();
|
||||
const notifyText = !script.favorite ? "Script was favorited!" : "Script was removed as a favorite!";
|
||||
this.$axios
|
||||
.put(`/scripts/${script.id}/script/`, { favorite: !script.favorite })
|
||||
.then(() => {
|
||||
this.getScripts();
|
||||
this.$q.loading.hide();
|
||||
this.notifySuccess(notifyText);
|
||||
})
|
||||
.catch(() => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError("Something went wrong");
|
||||
});
|
||||
},
|
||||
deleteScript(scriptpk) {
|
||||
this.$q
|
||||
.dialog({
|
||||
title: "Delete script?",
|
||||
@@ -212,8 +325,8 @@ export default {
|
||||
ok: { label: "Delete", color: "negative" },
|
||||
})
|
||||
.onOk(() => {
|
||||
axios
|
||||
.delete(`/scripts/${this.scriptpk}/script/`)
|
||||
this.$axios
|
||||
.delete(`/scripts/${scriptpk}/script/`)
|
||||
.then(r => {
|
||||
this.getScripts();
|
||||
this.notifySuccess(r.data);
|
||||
@@ -221,29 +334,18 @@ export default {
|
||||
.catch(() => this.notifySuccess("Something went wrong"));
|
||||
});
|
||||
},
|
||||
downloadScript() {
|
||||
axios
|
||||
.get(`/scripts/${this.scriptpk}/download/`, { responseType: "blob" })
|
||||
downloadScript(script) {
|
||||
this.$axios
|
||||
.get(`/scripts/${script.id}/download/`)
|
||||
.then(({ data }) => {
|
||||
const blob = new Blob([data], { type: "text/plain" });
|
||||
const blob = new Blob([data.code], { type: "text/plain;charset=utf-8" });
|
||||
let link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = this.filename;
|
||||
link.download = data.filename;
|
||||
link.click();
|
||||
})
|
||||
.catch(() => this.notifyError("Something went wrong"));
|
||||
},
|
||||
showScript(mode) {
|
||||
switch (mode) {
|
||||
case "add":
|
||||
this.mode = "add";
|
||||
break;
|
||||
case "edit":
|
||||
this.mode = "edit";
|
||||
break;
|
||||
}
|
||||
this.showScriptModal = true;
|
||||
},
|
||||
truncateText(txt) {
|
||||
return txt.length >= 60 ? txt.substring(0, 60) + "..." : txt;
|
||||
},
|
||||
@@ -255,16 +357,55 @@ export default {
|
||||
}
|
||||
},
|
||||
rowSelectedClass(id) {
|
||||
if (this.scriptpk === id) return this.$q.dark.isActive ? "highlight-dark" : "highlight";
|
||||
if (this.selectedScript.id === id) return this.$q.dark.isActive ? "highlight-dark" : "highlight";
|
||||
},
|
||||
favoriteText(isFavorite) {
|
||||
return isFavorite ? "Remove as Favorite" : "Add as Favorite";
|
||||
},
|
||||
newScript() {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: ScriptFormModal,
|
||||
parent: this,
|
||||
categories: this.categories,
|
||||
readonly: false,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
},
|
||||
editScript(script) {
|
||||
this.$q
|
||||
.dialog({
|
||||
component: ScriptFormModal,
|
||||
parent: this,
|
||||
script: script,
|
||||
categories: this.categories,
|
||||
readonly: false,
|
||||
})
|
||||
.onDismiss(() => {
|
||||
this.getScripts();
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
toggleScriptManager: state => state.toggleScriptManager,
|
||||
scripts: state => state.scripts,
|
||||
}),
|
||||
...mapState(["showCommunityScripts"]),
|
||||
visibleScripts() {
|
||||
return this.showBuiltIn ? this.scripts : this.scripts.filter(i => i.script_type !== "builtin");
|
||||
return this.showCommunityScripts ? this.scripts : this.scripts.filter(i => i.script_type !== "builtin");
|
||||
},
|
||||
categories() {
|
||||
let list = [];
|
||||
this.scripts.forEach(script => {
|
||||
if (!!script.category && !list.includes(script.category)) {
|
||||
if (script.category !== "Community") {
|
||||
list.push(script.category);
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
},
|
||||
isRowSelected() {
|
||||
return this.selectedScript.id !== null && this.selectedScript.id !== undefined;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -155,7 +155,6 @@
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
import { mapGetters } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "BulkAction",
|
||||
@@ -167,6 +166,7 @@ export default {
|
||||
return {
|
||||
target: "client",
|
||||
selected_mode: null,
|
||||
scriptOptions: [],
|
||||
scriptPK: null,
|
||||
timeout: 900,
|
||||
client: null,
|
||||
@@ -182,16 +182,18 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["scripts"]),
|
||||
sites() {
|
||||
return !!this.client ? this.formatSiteOptions(this.client.sites) : [];
|
||||
},
|
||||
scriptOptions() {
|
||||
const ret = this.scripts.map(script => ({ label: script.name, value: script.id }));
|
||||
return ret.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getScripts() {
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scriptOptions = r.data.map(
|
||||
script => ({ label: script.name, value: script.id })).sort((a, b) => a.label.localeCompare(b.label)
|
||||
);
|
||||
});
|
||||
},
|
||||
send() {
|
||||
this.$q.loading.show();
|
||||
const data = {
|
||||
@@ -253,6 +255,7 @@ export default {
|
||||
this.setTitles();
|
||||
this.getClients();
|
||||
this.getAgents();
|
||||
this.getScripts()
|
||||
|
||||
this.selected_mode = this.mode;
|
||||
},
|
||||
|
||||
@@ -76,6 +76,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scriptOptions: [],
|
||||
loading: false,
|
||||
scriptPK: null,
|
||||
timeout: 30,
|
||||
@@ -85,22 +86,21 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["scripts"]),
|
||||
hostname() {
|
||||
return this.$store.state.agentSummary.hostname;
|
||||
},
|
||||
width() {
|
||||
return this.ret === null ? "40vw" : "70vw";
|
||||
},
|
||||
scriptOptions() {
|
||||
const ret = [];
|
||||
this.scripts.forEach(i => {
|
||||
ret.push({ label: i.name, value: i.id });
|
||||
});
|
||||
return ret.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getScripts() {
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scriptOptions = r.data.map(
|
||||
script => ({ label: script.name, value: script.id })).sort((a, b) => a.label.localeCompare(b.label)
|
||||
);
|
||||
});
|
||||
},
|
||||
send() {
|
||||
this.ret = null;
|
||||
this.loading = true;
|
||||
@@ -129,5 +129,8 @@ export default {
|
||||
});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getScripts()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<q-card v-if="scripts.length === 0" style="min-width: 400px">
|
||||
<q-card v-if="scriptOptions.length === 0" style="min-width: 400px">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Add Script Check</div>
|
||||
<q-space />
|
||||
@@ -80,9 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import mixins from "@/mixins/mixins";
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
export default {
|
||||
name: "ScriptCheck",
|
||||
props: {
|
||||
@@ -101,22 +99,20 @@ export default {
|
||||
timeout: 120,
|
||||
fails_b4_alert: 1,
|
||||
},
|
||||
scriptOptions: [],
|
||||
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["scripts"]),
|
||||
scriptOptions() {
|
||||
const ret = [];
|
||||
this.scripts.forEach(i => {
|
||||
ret.push({ label: i.name, value: i.id });
|
||||
});
|
||||
return ret.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getScripts() {
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scriptOptions = r.data.map(
|
||||
script => ({ label: script.name, value: script.id })).sort((a, b) => a.label.localeCompare(b.label)
|
||||
);
|
||||
});
|
||||
},
|
||||
getCheck() {
|
||||
axios.get(`/checks/${this.checkpk}/check/`).then(r => {
|
||||
this.$axios.get(`/checks/${this.checkpk}/check/`).then(r => {
|
||||
this.scriptcheck = r.data;
|
||||
this.scriptcheck.script = r.data.script.id;
|
||||
});
|
||||
@@ -127,7 +123,7 @@ export default {
|
||||
...pk,
|
||||
check: this.scriptcheck,
|
||||
};
|
||||
axios
|
||||
this.$axios
|
||||
.post("/checks/checks/", data)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
@@ -137,7 +133,7 @@ export default {
|
||||
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
||||
},
|
||||
editCheck() {
|
||||
axios
|
||||
this.$axios
|
||||
.patch(`/checks/${this.checkpk}/check/`, this.scriptcheck)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
@@ -158,6 +154,8 @@ export default {
|
||||
if (this.mode === "edit") {
|
||||
this.getCheck();
|
||||
}
|
||||
|
||||
this.getScripts()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
270
src/components/modals/scripts/ScriptFormModal.vue
Normal file
270
src/components/modals/scripts/ScriptFormModal.vue
Normal file
@@ -0,0 +1,270 @@
|
||||
<template>
|
||||
<q-dialog ref="dialog" @hide="onHide" persistent :maximized="maximized">
|
||||
<q-card class="q-dialog-plugin" :style="getMaxWidth">
|
||||
<q-bar>
|
||||
{{ title }}
|
||||
<q-space />
|
||||
<q-btn dense flat icon="minimize" @click="maximized = false" :disable="!maximized">
|
||||
<q-tooltip v-if="maximized" content-class="bg-white text-primary">Minimize</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn dense flat icon="crop_square" @click="maximized = true" :disable="maximized">
|
||||
<q-tooltip v-if="!maximized" content-class="bg-white text-primary">Maximize</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form @submit="submit">
|
||||
<q-card-section class="row">
|
||||
<div class="q-pa-sm col-1" style="width: auto">
|
||||
<q-icon
|
||||
class="cursor-pointer"
|
||||
:name="favoriteIcon"
|
||||
size="md"
|
||||
color="yellow-8"
|
||||
@[clickEvent]="localScript.favorite = !localScript.favorite"
|
||||
/>
|
||||
</div>
|
||||
<div class="q-pa-sm col-2">
|
||||
<q-input filled dense :readonly="readonly" v-model="localScript.name" label="Name" />
|
||||
</div>
|
||||
<div class="q-pa-sm col-2">
|
||||
<q-select
|
||||
:readonly="readonly"
|
||||
options-dense
|
||||
filled
|
||||
dense
|
||||
v-model="localScript.shell"
|
||||
:options="shellOptions"
|
||||
emit-value
|
||||
map-options
|
||||
label="Shell Type"
|
||||
/>
|
||||
</div>
|
||||
<div class="q-pa-sm col-3">
|
||||
<q-select
|
||||
hint="Press Enter or Tab when adding a new value"
|
||||
dense
|
||||
options-dense
|
||||
filled
|
||||
v-model="localScript.category"
|
||||
:options="filterOptions"
|
||||
use-input
|
||||
clearable
|
||||
new-value-mode="add-unique"
|
||||
debounce="0"
|
||||
@filter="filterFn"
|
||||
label="Category"
|
||||
:readonly="readonly"
|
||||
/>
|
||||
</div>
|
||||
<div class="q-pa-sm col-4">
|
||||
<q-input filled dense :readonly="readonly" v-model="localScript.description" label="Description" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<prism-editor
|
||||
class="editor"
|
||||
:readonly="readonly"
|
||||
v-model="localScript.code"
|
||||
:highlight="highlighter"
|
||||
:style="heightVar"
|
||||
lineNumbers
|
||||
></prism-editor>
|
||||
<q-card-actions v-if="!readonly">
|
||||
<q-space />
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn dense flat label="Save" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
import { PrismEditor } from "vue-prism-editor";
|
||||
import "vue-prism-editor/dist/prismeditor.min.css";
|
||||
|
||||
import { highlight, languages } from "prismjs/components/prism-core";
|
||||
import "prismjs/components/prism-batch";
|
||||
import "prismjs/components/prism-python";
|
||||
import "prismjs/components/prism-powershell";
|
||||
import "prismjs/themes/prism-tomorrow.css";
|
||||
|
||||
export default {
|
||||
name: "ScriptFormModal",
|
||||
mixins: [mixins],
|
||||
components: {
|
||||
PrismEditor,
|
||||
},
|
||||
props: {
|
||||
script: Object,
|
||||
categories: !Array,
|
||||
readonly: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localScript: {
|
||||
name: "",
|
||||
code: "",
|
||||
shell: "powershell",
|
||||
description: "",
|
||||
category: "",
|
||||
favorite: false,
|
||||
script_type: "userdefined",
|
||||
},
|
||||
maximized: false,
|
||||
filterOptions: [],
|
||||
shellOptions: [
|
||||
{ label: "Powershell", value: "powershell" },
|
||||
{ label: "Batch", value: "cmd" },
|
||||
{ label: "Python", value: "python" },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$q.loading.show();
|
||||
|
||||
if (!!this.script) {
|
||||
this.$axios
|
||||
.put(`/scripts/${this.script.id}/script/`, this.localScript)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("hide");
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data.non_field_errors, 4000);
|
||||
});
|
||||
} else {
|
||||
this.$axios
|
||||
.post(`/scripts/scripts/`, this.localScript)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("hide");
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data.non_field_errors, 4000);
|
||||
});
|
||||
}
|
||||
},
|
||||
getCode() {
|
||||
this.$q.loading.show();
|
||||
this.$axios
|
||||
.get(`/scripts/${this.script.id}/download/`)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.localScript.code = r.data.code;
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data.non_field_errors, 4000);
|
||||
});
|
||||
},
|
||||
highlighter(code) {
|
||||
let lang = this.localScript.shell === "cmd" ? "batch" : this.localScript.shell;
|
||||
return highlight(code, languages[lang]);
|
||||
},
|
||||
show() {
|
||||
this.$refs.dialog.show();
|
||||
},
|
||||
hide() {
|
||||
this.$refs.dialog.hide();
|
||||
},
|
||||
onHide() {
|
||||
this.$emit("hide");
|
||||
},
|
||||
filterFn(val, update) {
|
||||
update(() => {
|
||||
if (val === "") {
|
||||
this.filterOptions = this.categories;
|
||||
} else {
|
||||
const needle = val.toLowerCase();
|
||||
this.filterOptions = this.categories.filter(v => v.toLowerCase().indexOf(needle) > -1);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
favoriteIcon() {
|
||||
return this.localScript.favorite ? "star" : "star_outline";
|
||||
},
|
||||
title() {
|
||||
if (!!this.script) {
|
||||
return this.readonly ? `Viewing ${this.script.name}` : `Editing ${this.script.name}`;
|
||||
} else {
|
||||
return "Adding new script";
|
||||
}
|
||||
},
|
||||
clickEvent() {
|
||||
return !this.readonly ? "click" : null;
|
||||
},
|
||||
getMaxWidth() {
|
||||
return this.maximized ? "" : "width: 60vw; max-width: 90vw";
|
||||
},
|
||||
heightVar() {
|
||||
return this.maximized ? "--prism-height: 80vh" : "--prism-height: 70vh";
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (!!this.script) {
|
||||
this.localScript.id = this.script.id;
|
||||
this.localScript.name = this.script.name;
|
||||
this.localScript.description = this.script.description;
|
||||
this.localScript.favorite = this.script.favorite;
|
||||
this.localScript.shell = this.script.shell;
|
||||
this.localScript.category = this.script.category;
|
||||
this.localScript.script_type = this.script.script_type;
|
||||
this.getCode();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* required class */
|
||||
.editor {
|
||||
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
|
||||
background: #2d2d2d;
|
||||
color: #ccc;
|
||||
|
||||
/* you must provide font-family font-size line-height. Example: */
|
||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
padding: 5px;
|
||||
height: var(--prism-height);
|
||||
}
|
||||
|
||||
.prism-editor__container {
|
||||
height: 60000em;
|
||||
}
|
||||
|
||||
/* optional class for removing the outline */
|
||||
.prism-editor__textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.prism-editor__textarea,
|
||||
.prism-editor__container {
|
||||
width: 10000em !important;
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.prism-editor__container::-webkit-scrollbar,
|
||||
.prism-editor__textarea::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.prism-editor__editor {
|
||||
white-space: pre !important;
|
||||
}
|
||||
.prism-editor__container {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,180 +0,0 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-form @submit.prevent="handleScript">
|
||||
<q-card-section class="row items-center">
|
||||
<div v-if="mode === 'add'" class="text-h6">Add Script</div>
|
||||
<div v-else-if="mode === 'edit'" class="text-h6">Edit Script</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense v-close-popup />
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input
|
||||
:disable="isBuiltInScript"
|
||||
outlined
|
||||
dense
|
||||
v-model="script.name"
|
||||
:rules="[val => !!val || '*Required']"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input :disable="isBuiltInScript" outlined dense v-model="script.description" type="textarea" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">File Upload:</div>
|
||||
<div v-if="mode === 'add'" class="col-10">
|
||||
<q-file
|
||||
v-model="script.filename"
|
||||
label="Supported file types: .ps1, .bat, .py"
|
||||
stack-label
|
||||
filled
|
||||
counter
|
||||
accept=".ps1, .bat, .py"
|
||||
:rules="[val => !!val || '*Required']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="attach_file" />
|
||||
</template>
|
||||
</q-file>
|
||||
</div>
|
||||
<!-- don't enforce rules if edit mode -->
|
||||
<div v-if="mode === 'edit'" class="col-10">
|
||||
<q-file
|
||||
v-model="script.filename"
|
||||
:disable="isBuiltInScript"
|
||||
label="Upload new script version"
|
||||
stack-label
|
||||
filled
|
||||
counter
|
||||
accept=".ps1, .bat, .py"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="attach_file" />
|
||||
</template>
|
||||
</q-file>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Type:</div>
|
||||
<q-select
|
||||
:disable="isBuiltInScript"
|
||||
dense
|
||||
options-dense
|
||||
class="col-10"
|
||||
outlined
|
||||
v-model="script.shell"
|
||||
:options="shellOptions"
|
||||
emit-value
|
||||
map-options
|
||||
:rules="[val => !!val || '*Required']"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="row items-center">
|
||||
<q-btn v-if="mode === 'add'" label="Upload" color="primary" type="submit" />
|
||||
<q-btn v-else-if="mode === 'edit'" :disable="isBuiltInScript" label="Edit" color="primary" type="submit" />
|
||||
</q-card-section>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import { mapState } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "ScriptModal",
|
||||
mixins: [mixins],
|
||||
props: {
|
||||
scriptpk: Number,
|
||||
mode: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
script: {},
|
||||
originalFile: null,
|
||||
shellOptions: [
|
||||
{ label: "Powershell", value: "powershell" },
|
||||
{ label: "Batch (CMD)", value: "cmd" },
|
||||
{ label: "Python", value: "python" },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getScript() {
|
||||
axios.get(`/scripts/${this.scriptpk}/script/`).then(r => {
|
||||
this.originalFile = r.data.filename;
|
||||
delete r.data.filename;
|
||||
this.script = r.data;
|
||||
});
|
||||
},
|
||||
handleScript() {
|
||||
let formData = new FormData();
|
||||
|
||||
if (this.mode === "add") {
|
||||
formData.append("filename", this.script.filename);
|
||||
}
|
||||
// only append file if uploading a new file
|
||||
else if (this.mode === "edit" && this.script.filename) {
|
||||
formData.append("filename", this.script.filename);
|
||||
|
||||
// filename needs to be the same if editing so we don't have a ghost file on server
|
||||
if (this.script.filename.name !== this.originalFile) {
|
||||
this.notifyError("Script filename must be the same if editing.", 4000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let url;
|
||||
switch (this.mode) {
|
||||
case "add":
|
||||
url = "/scripts/scripts/";
|
||||
break;
|
||||
case "edit":
|
||||
url = `/scripts/${this.scriptpk}/script/`;
|
||||
break;
|
||||
}
|
||||
|
||||
formData.append("name", this.script.name);
|
||||
formData.append("shell", this.script.shell);
|
||||
formData.append("description", this.script.description);
|
||||
|
||||
this.$q.loading.show();
|
||||
axios
|
||||
.put(url, formData)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$emit("uploaded");
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data.non_field_errors, 4000);
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
scripts: state => state.scripts,
|
||||
}),
|
||||
isBuiltInScript() {
|
||||
if (this.mode === "edit") {
|
||||
return this.scripts.find(i => i.id === this.scriptpk).script_type === "builtin" ? true : false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.mode === "edit") {
|
||||
this.getScript();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
149
src/components/modals/scripts/ScriptUploadModal.vue
Normal file
149
src/components/modals/scripts/ScriptUploadModal.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<q-card style="width: 40vw">
|
||||
<q-bar>
|
||||
Add Script
|
||||
<q-space />
|
||||
<q-btn dense flat icon="close" v-close-popup>
|
||||
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||
</q-btn>
|
||||
</q-bar>
|
||||
<q-form @submit.prevent="submit">
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Name:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="script.name" :rules="[val => !!val || '*Required']" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Description:</div>
|
||||
<div class="col-10">
|
||||
<q-input outlined dense v-model="script.description" type="textarea" />
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Category:</div>
|
||||
<q-select
|
||||
hint="Press Enter or Tab when adding a new value"
|
||||
dense
|
||||
options-dense
|
||||
class="col-10"
|
||||
outlined
|
||||
v-model="script.category"
|
||||
:options="filterOptions"
|
||||
use-input
|
||||
clearable
|
||||
new-value-mode="add-unique"
|
||||
debounce="0"
|
||||
@filter="filterFn"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">File Upload:</div>
|
||||
<div class="col-10">
|
||||
<q-file
|
||||
v-model="script.filename"
|
||||
label="Supported file types: .ps1, .bat, .py"
|
||||
stack-label
|
||||
filled
|
||||
counter
|
||||
accept=".ps1, .bat, .py"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="attach_file" />
|
||||
</template>
|
||||
</q-file>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="row">
|
||||
<div class="col-2">Type:</div>
|
||||
<q-select
|
||||
dense
|
||||
options-dense
|
||||
class="col-10"
|
||||
outlined
|
||||
v-model="script.shell"
|
||||
:options="shellOptions"
|
||||
emit-value
|
||||
map-options
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions>
|
||||
<q-space />
|
||||
<q-btn dense flat label="Cancel" v-close-popup />
|
||||
<q-btn dense flat label="Add" color="primary" type="submit" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
name: "ScriptModal",
|
||||
mixins: [mixins],
|
||||
props: {
|
||||
categories: !Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
script: {
|
||||
name: "",
|
||||
description: "",
|
||||
shell: "powershell",
|
||||
category: null,
|
||||
},
|
||||
shellOptions: [
|
||||
{ label: "Powershell", value: "powershell" },
|
||||
{ label: "Batch (CMD)", value: "cmd" },
|
||||
{ label: "Python", value: "python" },
|
||||
],
|
||||
filterOptions: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$q.loading.show();
|
||||
|
||||
let formData = new FormData();
|
||||
|
||||
if (!!this.script.filename) {
|
||||
formData.append("filename", this.script.filename);
|
||||
}
|
||||
|
||||
if (!!this.script.category) {
|
||||
formData.append("category", this.script.category);
|
||||
} else {
|
||||
formData.append("category", "");
|
||||
}
|
||||
|
||||
formData.append("name", this.script.name);
|
||||
formData.append("shell", this.script.shell);
|
||||
formData.append("description", this.script.description);
|
||||
|
||||
this.$axios
|
||||
.post("/scripts/scripts/", formData)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
this.$emit("close");
|
||||
this.$emit("added");
|
||||
this.notifySuccess(r.data);
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(e.response.data.non_field_errors, 4000);
|
||||
});
|
||||
},
|
||||
filterFn(val, update) {
|
||||
update(() => {
|
||||
if (val === "") {
|
||||
this.filterOptions = this.categories;
|
||||
} else {
|
||||
const needle = val.toLowerCase();
|
||||
this.filterOptions = this.categories.filter(v => v.toLowerCase().indexOf(needle) > -1);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<q-card v-if="scripts.length === 0" class="q-pa-xs" style="min-width: 400px">
|
||||
<q-card v-if="scriptOptions.length === 0" class="q-pa-xs" style="min-width: 400px">
|
||||
<q-card-section class="row items-center">
|
||||
<div class="text-h6">Add Automated Task</div>
|
||||
<q-space />
|
||||
@@ -26,7 +26,7 @@
|
||||
outlined
|
||||
v-model="autotask.script"
|
||||
:options="scriptOptions"
|
||||
label="Select task"
|
||||
label="Select script"
|
||||
map-options
|
||||
emit-value
|
||||
/>
|
||||
@@ -147,8 +147,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import { mapState, mapGetters } from "vuex";
|
||||
import { mapGetters } from "vuex";
|
||||
import mixins from "@/mixins/mixins";
|
||||
|
||||
export default {
|
||||
@@ -160,6 +159,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
step: 1,
|
||||
scriptOptions: [],
|
||||
autotask: {
|
||||
script: null,
|
||||
script_args: [],
|
||||
@@ -202,7 +202,7 @@ export default {
|
||||
autotask: this.autotask,
|
||||
};
|
||||
|
||||
axios
|
||||
this.$axios
|
||||
.post("tasks/automatedtasks/", data)
|
||||
.then(r => {
|
||||
this.$emit("close");
|
||||
@@ -220,11 +220,15 @@ export default {
|
||||
}
|
||||
},
|
||||
getScripts() {
|
||||
this.$store.dispatch("getScripts");
|
||||
},
|
||||
this.$axios.get("/scripts/scripts/").then(r => {
|
||||
this.scriptOptions = r.data.map(
|
||||
script => ({ label: script.name, value: script.id })).sort((a, b) => a.label.localeCompare(b.label)
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["selectedAgentPk", "scripts"]),
|
||||
...mapGetters(["selectedAgentPk"]),
|
||||
checks() {
|
||||
return this.policypk
|
||||
? this.$store.state.automation.checks
|
||||
@@ -237,13 +241,6 @@ export default {
|
||||
});
|
||||
return r.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
scriptOptions() {
|
||||
const r = [];
|
||||
this.scripts.forEach(i => {
|
||||
r.push({ label: i.name, value: i.id });
|
||||
});
|
||||
return r.sort((a, b) => a.label.localeCompare(b.label));
|
||||
},
|
||||
step1Done() {
|
||||
return this.step > 1 && this.autotask.script !== null && this.autotask.name && this.autotask.timeout
|
||||
? true
|
||||
@@ -264,7 +261,7 @@ export default {
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getScripts();
|
||||
},
|
||||
this.getScripts()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -29,12 +29,11 @@ export default function () {
|
||||
agentTableLoading: false,
|
||||
treeLoading: false,
|
||||
installedSoftware: [],
|
||||
scripts: [],
|
||||
notes: [],
|
||||
toggleScriptManager: false,
|
||||
needrefresh: false,
|
||||
tableHeight: "35vh",
|
||||
tabHeight: "35vh",
|
||||
showCommunityScripts: false
|
||||
},
|
||||
getters: {
|
||||
loggedIn(state) {
|
||||
@@ -68,9 +67,6 @@ export default function () {
|
||||
agentHostname(state) {
|
||||
return state.agentSummary.hostname;
|
||||
},
|
||||
scripts(state) {
|
||||
return state.scripts;
|
||||
},
|
||||
needRefresh(state) {
|
||||
return state.needrefresh;
|
||||
},
|
||||
@@ -82,9 +78,6 @@ export default function () {
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
TOGGLE_SCRIPT_MANAGER(state, action) {
|
||||
state.toggleScriptManager = action;
|
||||
},
|
||||
AGENT_TABLE_LOADING(state, visible) {
|
||||
state.agentTableLoading = visible;
|
||||
},
|
||||
@@ -128,9 +121,6 @@ export default function () {
|
||||
(state.installedSoftware = []);
|
||||
state.selectedRow = "";
|
||||
},
|
||||
SET_SCRIPTS(state, scripts) {
|
||||
state.scripts = scripts;
|
||||
},
|
||||
SET_REFRESH_NEEDED(state, action) {
|
||||
state.needrefresh = action;
|
||||
},
|
||||
@@ -142,9 +132,17 @@ export default function () {
|
||||
},
|
||||
SET_NOTES(state, notes) {
|
||||
state.notes = notes;
|
||||
},
|
||||
setShowCommunityScripts(state, show) {
|
||||
state.showCommunityScripts = show
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setShowCommunityScripts(context, data) {
|
||||
axios.patch("/accounts/users/ui/", { show_community_scripts: data }).then(r => {
|
||||
context.commit("setShowCommunityScripts", data)
|
||||
})
|
||||
},
|
||||
toggleMaintenanceMode(context, data) {
|
||||
return axios.post("/agents/maintenance/", data)
|
||||
},
|
||||
@@ -159,11 +157,6 @@ export default function () {
|
||||
context.commit("SET_AUTOMATED_TASKS", r.data);
|
||||
})
|
||||
},
|
||||
getScripts(context) {
|
||||
axios.get("/scripts/scripts/").then(r => {
|
||||
context.commit("SET_SCRIPTS", r.data);
|
||||
});
|
||||
},
|
||||
loadInstalledSoftware(context, pk) {
|
||||
axios.get(`/software/installed/${pk}`).then(r => {
|
||||
context.commit("SET_INSTALLED_SOFTWARE", r.data.software);
|
||||
|
||||
@@ -673,6 +673,8 @@ export default {
|
||||
this.darkMode = r.data.dark_mode;
|
||||
this.$q.dark.set(this.darkMode);
|
||||
this.currentTRMMVersion = r.data.trmm_version;
|
||||
|
||||
this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts);
|
||||
});
|
||||
},
|
||||
showToggleMaintenance(node) {
|
||||
|
||||
Reference in New Issue
Block a user