19 Commits

Author SHA1 Message Date
Manuel Romero
4c53026e02 Build prod 2025-07-24 13:10:35 +02:00
Manuel Romero
69dffe0710 fix redshift 2025-07-24 12:56:23 +02:00
Manuel Romero
97b9f1831e Start confirm 2025-07-24 12:55:18 +02:00
Manuel Romero
abb8205004 Fixes 2025-07-24 12:43:27 +02:00
Manuel Romero
8e72203c73 New common version 2025-07-24 12:24:51 +02:00
Manuel Romero
ea0747a722 Fe build 2025-07-24 12:19:23 +02:00
Manuel Romero
38cc793016 Adding redshift start / stop 2025-07-24 12:18:29 +02:00
Manuel Romero
272415faf0 Merge branch 'dev' 2025-06-18 13:32:42 +02:00
Manuel Romero
191ab040f1 version app 6.0.0 2025-06-18 13:24:36 +02:00
Manuel Romero
101a6980a2 build staging 2025-06-18 13:22:07 +02:00
Manuel Romero
7389960a80 new version 2025-06-18 13:08:17 +02:00
Manuel Romero
511e5e16d8 new common 2025-05-12 00:49:20 +02:00
Manuel Romero
5a5d97dcaa fix 2025-05-12 00:39:30 +02:00
Manuel Romero
e891854efb using qaa for email 2025-05-12 00:25:41 +02:00
Manuel Romero
f01eee5d9e add provision status 2025-05-11 23:25:43 +02:00
Manuel Romero
3b95e35173 fix fix fix 2025-05-09 15:19:43 +02:00
Manuel Romero
f3c6bfbba5 fix 2025-05-09 14:31:23 +02:00
Manuel Romero
267ee5f93e only one snowflake onelabs 2025-05-09 14:23:03 +02:00
Manuel Romero
f47e84aab0 Do not duplicate databricks 2025-05-05 12:41:41 +02:00
68 changed files with 910 additions and 206000 deletions

View File

@@ -39,10 +39,6 @@
"src/styles.scss" "src/styles.scss"
], ],
"scripts": [ "scripts": [
"node_modules/chart.js/dist/Chart.js",
"node_modules/hammerjs/hammer.min.js",
"src/assets/js/qlikMashupQCS.js"
], ],
"aot": false, "aot": false,
"vendorChunk": true, "vendorChunk": true,
@@ -77,6 +73,14 @@
] ]
}, },
"staging": { "staging": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"outputPath": "diststaging/qmi-cloud", "outputPath": "diststaging/qmi-cloud",
"index": { "index": {
"input": "src/index-dev.html", "input": "src/index-dev.html",

View File

@@ -19,6 +19,6 @@
<style>:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}body{font-family:Roboto,sans-serif;font-weight:300}@charset "UTF-8";@font-face{font-family:Inter;src:url(Inter-Regular.1282ebc61b96a9d9.ttf);font-weight:400;font-style:normal}*{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:Inter!important;color:#444!important;font-size:inherit!important;background:#fafafa!important}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}</style><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css"></noscript></head> <style>:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}body{font-family:Roboto,sans-serif;font-weight:300}@charset "UTF-8";@font-face{font-family:Inter;src:url(Inter-Regular.1282ebc61b96a9d9.ttf);font-weight:400;font-style:normal}*{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:Inter!important;color:#444!important;font-size:inherit!important;background:#fafafa!important}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}</style><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css"></noscript></head>
<body> <body>
<app-root></app-root> <app-root></app-root>
<script src="runtime.accab2fb1ba76796.js" type="module"></script><script src="polyfills.7a6afdeb00d3088f.js" type="module"></script><script src="scripts.1be12de92f863a8e.js" defer></script><script src="main.d6cb332f7f6fa16d.js" type="module"></script> <script src="runtime.accab2fb1ba76796.js" type="module"></script><script src="polyfills.7a6afdeb00d3088f.js" type="module"></script><script src="main.467b269255a61ad3.js" type="module"></script>
</body></html> </body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

View File

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 213 B

View File

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 215 B

View File

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 146 B

View File

Before

Width:  |  Height:  |  Size: 137 B

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 215 B

View File

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 214 B

View File

Before

Width:  |  Height:  |  Size: 730 KiB

After

Width:  |  Height:  |  Size: 730 KiB

View File

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View File

Before

Width:  |  Height:  |  Size: 898 KiB

After

Width:  |  Height:  |  Size: 898 KiB

View File

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 434 KiB

View File

@@ -1,6 +1,4 @@
<!doctype html> <!DOCTYPE html><html lang="en"><head>
<html lang="en">
<head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>QMI Cloud</title> <title>QMI Cloud</title>
<base href="/"> <base href="/">
@@ -18,8 +16,9 @@
<script crossorigin="anonymous" type="application/javascript" src="https://cdn.jsdelivr.net/npm/@qlik/embed-web-components" data-host="https://innovation.us.qlikcloud.com" data-auth-type="Oauth2" data-client-id="21be5044bba1072c16a803a3e6e4dca0" data-redirect-uri="https://qmicloud-dev.qliktech.com/oauth-callback.html" data-access-token-storage="session" data-auto-redirect="true"></script> <script crossorigin="anonymous" type="application/javascript" src="https://cdn.jsdelivr.net/npm/@qlik/embed-web-components" data-host="https://innovation.us.qlikcloud.com" data-auth-type="Oauth2" data-client-id="21be5044bba1072c16a803a3e6e4dca0" data-redirect-uri="https://qmicloud-dev.qliktech.com/oauth-callback.html" data-access-token-storage="session" data-auto-redirect="true"></script>
<link rel="stylesheet" href="styles.css"></head> <style>:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}body{font-family:Roboto,sans-serif;font-weight:300}@charset "UTF-8";@font-face{font-family:Inter;src:url(Inter-Regular.1282ebc61b96a9d9.ttf);font-weight:400;font-style:normal}*{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:Inter!important;color:#444!important;font-size:inherit!important;background:#fafafa!important}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}@media print{*,*:before,*:after{text-shadow:none!important;box-shadow:none!important}@page{size:a3}body{min-width:992px!important}}</style><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.369b9a2a6e9a8394.css"></noscript></head>
<body> <body>
<app-root></app-root> <app-root></app-root>
<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="scripts.js" defer></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script></body> <script src="runtime.accab2fb1ba76796.js" type="module"></script><script src="polyfills.7a6afdeb00d3088f.js" type="module"></script><script src="main.467b269255a61ad3.js" type="module"></script>
</html>
</body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
(()=>{"use strict";var e,d={},v={};function n(e){var f=v[e];if(void 0!==f)return f.exports;var r=v[e]={id:e,loaded:!1,exports:{}};return d[e].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}n.m=d,e=[],n.O=(f,r,s,l)=>{if(!r){var o=1/0;for(a=0;a<e.length;a++){for(var[r,s,l]=e[a],t=!0,c=0;c<r.length;c++)(!1&l||o>=l)&&Object.keys(n.O).every(p=>n.O[p](r[c]))?r.splice(c--,1):(t=!1,l<o&&(o=l));if(t){e.splice(a--,1);var i=s();void 0!==i&&(f=i)}}return f}l=l||0;for(var a=e.length;a>0&&e[a-1][2]>l;a--)e[a]=e[a-1];e[a]=[r,s,l]},n.o=(e,f)=>Object.prototype.hasOwnProperty.call(e,f),n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={666:0};n.O.j=s=>0===e[s];var f=(s,l)=>{var c,i,[a,o,t]=l,u=0;if(a.some(_=>0!==e[_])){for(c in o)n.o(o,c)&&(n.m[c]=o[c]);if(t)var h=t(n)}for(s&&s(l);u<a.length;u++)n.o(e,i=a[u])&&e[i]&&e[i][0](),e[i]=0;return n.O(h)},r=self.webpackChunkqmi_cloud=self.webpackChunkqmi_cloud||[];r.forEach(f.bind(null,0)),r.push=f.bind(null,r.push.bind(r))})()})();

View File

@@ -1,175 +0,0 @@
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({});
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ loaded: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/chunk loaded */
/******/ (() => {
/******/ var deferred = [];
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var [chunkIds, fn, priority] = deferred[i];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ var r = fn();
/******/ if (r !== undefined) result = r;
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/node module decorator */
/******/ (() => {
/******/ __webpack_require__.nmd = (module) => {
/******/ module.paths = [];
/******/ if (!module.children) module.children = [];
/******/ return module;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ "runtime": 0
/******/ };
/******/
/******/ // no chunk on demand loading
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ return __webpack_require__.O(result);
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunkqmi_cloud"] = self["webpackChunkqmi_cloud"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
/******/
/******/
/******/ })()
;
//# sourceMappingURL=runtime.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{ {
"name": "qmi-cloud-app", "name": "qmi-cloud-app",
"version": "5.0.7", "version": "6.0.0",
"scripts": { "scripts": {
"start": "node server/server.js", "start": "node server/server.js",
"start:dev": "nodemon server/server.js", "start:dev": "nodemon server/server.js",
@@ -8,7 +8,7 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@QMI/qmi-cloud-common": "2.0.22", "@QMI/qmi-cloud-common": "2.0.24",
"@angular-devkit/build-angular": "^15.2.10", "@angular-devkit/build-angular": "^15.2.10",
"@angular/animations": "^15.2.10", "@angular/animations": "^15.2.10",
"@angular/common": "^15.2.10", "@angular/common": "^15.2.10",
@@ -30,7 +30,6 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
"bull-arena": "^2.6.4", "bull-arena": "^2.6.4",
"chart.js": "^2.9.3",
"connect-mongo": "^3.0.0", "connect-mongo": "^3.0.0",
"cookie": "^0.6.0", "cookie": "^0.6.0",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.4",
@@ -40,7 +39,6 @@
"express-session": "^1.17.0", "express-session": "^1.17.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"hammerjs": "^2.0.8",
"http-proxy-middleware": "^3.0.3", "http-proxy-middleware": "^3.0.3",
"ip-range-check": "^0.2.0", "ip-range-check": "^0.2.0",
"js-sha1": "^0.6.0", "js-sha1": "^0.6.0",

View File

@@ -1,6 +1,7 @@
const { RDSClient, StartDBClusterCommand, StartDBInstanceCommand, StopDBInstanceCommand, StopDBClusterCommand } = require("@aws-sdk/client-rds"); const { RDSClient, StartDBClusterCommand, StartDBInstanceCommand, StopDBInstanceCommand, StopDBClusterCommand } = require("@aws-sdk/client-rds");
const { EC2Client, DescribeInstancesCommand, StopInstancesCommand, StartInstancesCommand } = require("@aws-sdk/client-ec2"); const { EC2Client, DescribeInstancesCommand, StopInstancesCommand, StartInstancesCommand } = require("@aws-sdk/client-ec2");
const { IAMClient, CreateAccessKeyCommand, ListAccessKeysCommand, DeleteAccessKeyCommand } = require("@aws-sdk/client-iam"); const { IAMClient, CreateAccessKeyCommand, ListAccessKeysCommand, DeleteAccessKeyCommand } = require("@aws-sdk/client-iam");
const { RedshiftClient, PauseClusterCommand, ResumeClusterCommand } = require("@aws-sdk/client-redshift");
const db = require("./mongo"); const db = require("./mongo");
const utils = require("./utils"); const utils = require("./utils");
@@ -334,9 +335,54 @@ async function start(provision, triggerUserId) {
} }
// Stop Redshift cluster
async function stopRedshiftCluster(provision, triggerUserId) {
/*if (!provision || !provision.outputs || !provision.outputs['redshift_cluster_id']) {
console.log('AWSCLI# stopRedshiftCluster - Missing Redshift cluster ID in provision');
return null;
}*/
const clusterId = "qmi-"+provision._id.toString();
const region = _getRegion(provision);
try {
const client = new RedshiftClient({ region });
const command = new PauseClusterCommand({ ClusterIdentifier: clusterId });
const response = await client.send(command);
console.log(`AWSCLI# Redshift cluster (${clusterId}) paused.`);
await utils.afterStopVms( provision, triggerUserId, false, "redshift-cluster" );
return response;
} catch (error) {
console.log(`AWSCLI# ERROR pausing Redshift cluster: ${clusterId}`, error);
return null;
}
}
// Start Redshift cluster
async function startRedshiftCluster(provision, triggerUserId) {
/*if (!provision || !provision.outputs || !provision.outputs['redshift_cluster_id']) {
console.log('AWSCLI# startRedshiftCluster - Missing Redshift cluster ID in provision');
return null;
}*/
const clusterId = "qmi-"+provision._id.toString();
const region = _getRegion(provision);
try {
const client = new RedshiftClient({ region });
const command = new ResumeClusterCommand({ ClusterIdentifier: clusterId });
const response = await client.send(command);
console.log(`AWSCLI# Redshift cluster (${clusterId}) resumed.`);
await utils.afterStartVms( provision, triggerUserId, "redshift-cluster" );
return response;
} catch (error) {
console.log(`AWSCLI# ERROR resuming Redshift cluster: ${clusterId}`, error);
return null;
}
}
module.exports.deallocate = deallocate; module.exports.deallocate = deallocate;
module.exports.start = start; module.exports.start = start;
module.exports.stopDbInstance = stopDbInstance; module.exports.stopDbInstance = stopDbInstance;
module.exports.startDbInstance = startDbInstance; module.exports.startDbInstance = startDbInstance;
module.exports.rotateAccessKey = rotateAccessKey; module.exports.rotateAccessKey = rotateAccessKey;
module.exports.checkAccessKeys = checkAccessKeys; module.exports.checkAccessKeys = checkAccessKeys;
module.exports.stopRedshiftCluster = stopRedshiftCluster;
module.exports.startRedshiftCluster = startRedshiftCluster;

View File

@@ -100,6 +100,27 @@ async function checkIAMUserAccessKey(provision) {
} }
} }
async function startRedshiftCluster(provId, userId) {
try {
let provision = await db.provision.getById(provId);
if ( !provision ) return;
return await awscli.startRedshiftCluster(provision, userId);
} catch (err) {
console.log("CLI# ERROR startRedshiftCluster", err);
}
}
async function stopRedshiftCluster(provId, userId) {
try {
let provision = await db.provision.getById(provId);
if ( !provision ) return;
return await awscli.stopRedshiftCluster(provision, userId);
} catch (err) {
console.log("CLI# ERROR stopRedshiftCluster", err);
}
}
module.exports.deallocate = deallocate; module.exports.deallocate = deallocate;
module.exports.start = start; module.exports.start = start;
module.exports.updateVmsTags = updateVmsTags; module.exports.updateVmsTags = updateVmsTags;
@@ -109,3 +130,5 @@ module.exports.createSnapshots = createSnapshots;
module.exports.rotateStorageAccountKey = rotateStorageAccountKey; module.exports.rotateStorageAccountKey = rotateStorageAccountKey;
module.exports.rotateIAMUserAccessKey = rotateIAMUserAccessKey; module.exports.rotateIAMUserAccessKey = rotateIAMUserAccessKey;
module.exports.checkIAMUserAccessKey = checkIAMUserAccessKey; module.exports.checkIAMUserAccessKey = checkIAMUserAccessKey;
module.exports.startRedshiftCluster = startRedshiftCluster;
module.exports.stopRedshiftCluster = stopRedshiftCluster;

View File

@@ -1,10 +1,11 @@
{ {
"name": "@QMI/qmi-cloud-common", "name": "@QMI/qmi-cloud-common",
"version": "2.0.22", "version": "2.0.24",
"dependencies": { "dependencies": {
"@aws-sdk/client-ec2": "^3.590.0", "@aws-sdk/client-ec2": "^3.590.0",
"@aws-sdk/client-iam": "^3.758.0", "@aws-sdk/client-iam": "^3.758.0",
"@aws-sdk/client-rds": "^3.590.0", "@aws-sdk/client-rds": "^3.590.0",
"@aws-sdk/client-redshift": "^3.848.0",
"@azure/arm-compute": "^22.3.0", "@azure/arm-compute": "^22.3.0",
"@azure/arm-dns": "^5.1.0", "@azure/arm-dns": "^5.1.0",
"@azure/arm-storage": "^18.3.0", "@azure/arm-storage": "^18.3.0",

View File

@@ -2,6 +2,7 @@
const axios = require('axios'); const axios = require('axios');
const https = require("https"); const https = require("https");
const SMTP_EMAIL_SENDER = process.env.SMTP_EMAIL_SENDER; const SMTP_EMAIL_SENDER = process.env.SMTP_EMAIL_SENDER;
const SMTP_EXECUTION_TOKEN = process.env.SMTP_EXECUTION_TOKEN;
const HOSTNAME_URL = process.env.HOSTNAME_URL || "https://qmicloud.qliktech.com"; const HOSTNAME_URL = process.env.HOSTNAME_URL || "https://qmicloud.qliktech.com";
const FOOTER = `<div style="color:#404040;font-size:16px;padding:30px 0px 50px 0px"> const FOOTER = `<div style="color:#404040;font-size:16px;padding:30px 0px 50px 0px">
@@ -18,24 +19,34 @@ const getFooter = function(provision) {
async function _doSend(to, subject, htmlText) { async function _doSend(to, subject, htmlText) {
try { try {
console.log(`SendEmail (Qlik SMTP)# sending via : ` + SMTP_EMAIL_SENDER);
var body = { var body = {
"to": to, "to": to,
"subject": subject, "subject": subject,
"html": htmlText "html": htmlText
}; };
var headers = {};
if ( SMTP_EXECUTION_TOKEN ) {
headers = {
'X-Execution-Token': SMTP_EXECUTION_TOKEN,
'Content-Type': 'application/json'
};
console.log(`SendEmail (Qlik SMTP)# sending with X-Execution-Token: ` + SMTP_EXECUTION_TOKEN);
}
await axios({ await axios({
url: SMTP_EMAIL_SENDER, url: SMTP_EMAIL_SENDER,
method: "post", method: "POST",
data: body, data: body,
headers: headers,
httpsAgent: new https.Agent({ httpsAgent: new https.Agent({
rejectUnauthorized: false rejectUnauthorized: false
}) })
}); });
console.log('SendEmail (Qlik SMTP)# message sent to: ' + to); console.log(`SendEmail (Qlik SMTP)# message sent to:` + to);
} catch (err) { } catch (err) {
// Handle Error Here // Handle Error Here
console.log("SendEmail (Qlik SMTP) _doSend error: could not send the email to: " +to); console.log("SendEmail (Qlik SMTP) _doSend error: could not send the email to: " +to, err);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@ const TF_APPLY_QSEOK_QUEUE = MYQUEUES.TF_APPLY_QSEOK_QUEUE;
const TF_DESTROY_QUEUE = MYQUEUES.TF_DESTROY_QUEUE; const TF_DESTROY_QUEUE = MYQUEUES.TF_DESTROY_QUEUE;
const STOP_CONTAINER_QUEUE = MYQUEUES.STOP_CONTAINER_QUEUE; const STOP_CONTAINER_QUEUE = MYQUEUES.STOP_CONTAINER_QUEUE;
const SYNAPSE_QUEUE = MYQUEUES.SYNAPSE_QUEUE; const SYNAPSE_QUEUE = MYQUEUES.SYNAPSE_QUEUE;
const WEBHOOK_QUEUE = MYQUEUES.WEBHOOK_QUEUE;
/** /**
* @swagger * @swagger
@@ -210,6 +211,38 @@ router.post('/:userId/provisions', passport.ensureAuthenticatedAndIsMe, async (r
return res.status(400).json({"msg": "Number of simultaneous provisions reached for this scenario: " + scenarioSource.numSimultaneousProvisions}); return res.status(400).json({"msg": "Number of simultaneous provisions reached for this scenario: " + scenarioSource.numSimultaneousProvisions});
} }
if ( scenarioSource.name.includes('onelabs-databricks') && req.body.options && req.body.options.catalog_name && req.body.options.catalog_name.selected){
const thingName = req.body.options.catalog_name.selected.value;
const onelabProv = await db.provision.getOne({"user": userId, "status":"provisioned", "scenario": scenarioSource.name, "description": thingName, "isDestroyed": false});
if ( onelabProv ) {
queues[WEBHOOK_QUEUE].add("webhook_job", {
provId: onelabProv._id,
scenario: onelabProv.scenario,
user: userId,
eventType: 'provision.finished'
});
return res.status(200).json(onelabProv);
}
}
if ( scenarioSource.name.includes('onelabs-snowflake') && req.body.options && req.body.options.user_name && req.body.options.user_name.selected){
const thingName = req.body.options.user_name.selected.value;
const onelabProv = await db.provision.getOne({"user": userId, "status":"provisioned", "scenario": scenarioSource.name, "description": thingName, "isDestroyed": false});
if ( onelabProv ) {
queues[WEBHOOK_QUEUE].add("webhook_job", {
provId: onelabProv._id,
scenario: onelabProv.scenario,
user: userId,
eventType: 'provision.finished'
});
return res.status(200).json(onelabProv);
}
}
//if (!req.body.options || !req.body.options.vm1 || !req.body.options.vm1.vmType ) { //if (!req.body.options || !req.body.options.vm1 || !req.body.options.vm1.vmType ) {
// return res.status(400).json({"msg": "Invalid options"}); // return res.status(400).json({"msg": "Invalid options"});
//} //}
@@ -739,6 +772,8 @@ router.post('/:userId/provisions/:id/deallocatevms', passport.ensureAuthenticate
}); });
} else if(provision.scenario === 'awsqmi-rds') { } else if(provision.scenario === 'awsqmi-rds') {
cli.stopDb(provision._id, triggerUser._id); cli.stopDb(provision._id, triggerUser._id);
} else if(provision.scenario === 'awsqmi-redshift') {
cli.stopRedshiftCluster(provision._id, triggerUser._id);
} else { } else {
cli.deallocate(provision._id, triggerUser._id); cli.deallocate(provision._id, triggerUser._id);
} }
@@ -807,6 +842,8 @@ router.post('/:userId/provisions/:id/startvms', passport.ensureAuthenticatedAndI
}); });
} else if(provision.scenario === 'awsqmi-rds') { } else if(provision.scenario === 'awsqmi-rds') {
cli.startDb(provision._id, triggerUser._id); cli.startDb(provision._id, triggerUser._id);
} else if(provision.scenario === 'awsqmi-redshift') {
cli.startRedshiftCluster(provision._id, triggerUser._id);
} else { } else {
cli.start(provision._id, triggerUser._id); cli.start(provision._id, triggerUser._id);
} }

View File

@@ -12,7 +12,7 @@
<div *ngIf="provision && provision.statusVms === 'Running'"> <div *ngIf="provision && provision.statusVms === 'Running'">
<div *ngIf="provision.scenario !== 'awsqmi-rds' && provision.scenario !== 'azqmi-synapse'"> <div *ngIf="provision.scenario !== 'awsqmi-rds' && provision.scenario !== 'azqmi-synapse' && provision.scenario !== 'awsqmi-redshift'">
<p *ngIf="!provision.schedule || provision.schedule.is24x7"> <p *ngIf="!provision.schedule || provision.schedule.is24x7">
<br> <br>
<i><mdb-icon fas icon="info-circle"></mdb-icon> You'll have a period of <b>{{provision.isExternalAccess? '10' : '20'}} days</b> to startup VMs before scenario is destroyed</i> <i><mdb-icon fas icon="info-circle"></mdb-icon> You'll have a period of <b>{{provision.isExternalAccess? '10' : '20'}} days</b> to startup VMs before scenario is destroyed</i>
@@ -33,7 +33,7 @@
<i><mdb-icon fas icon="info-circle"></mdb-icon> This will just <b>temporary stop</b> this database instance <b>only for 7 days</b>, then it will auto restart. You can restart at any point.</i> <i><mdb-icon fas icon="info-circle"></mdb-icon> This will just <b>temporary stop</b> this database instance <b>only for 7 days</b>, then it will auto restart. You can restart at any point.</i>
</p> </p>
</div> </div>
<div *ngIf="provision.scenario === 'azqmi-synapse'"> <div *ngIf="provision.scenario === 'awsqmi-redshift' || provision.scenario === 'azqmi-synapse'">
<p> <p>
<br> <br>
<i><mdb-icon fas icon="info-circle"></mdb-icon> This will stop this database instance. You can restart it at any point though. </i> <i><mdb-icon fas icon="info-circle"></mdb-icon> This will stop this database instance. You can restart it at any point though. </i>
@@ -42,7 +42,7 @@
</div> </div>
<div *ngIf="provision && provision.statusVms === 'Stopped'"> <div *ngIf="provision && provision.statusVms === 'Stopped'">
<div *ngIf="provision.scenario !== 'awsqmi-rds' && provision.scenario !== 'azqmi-synapse'"> <div *ngIf="provision.scenario !== 'awsqmi-redshift' && provision.scenario !== 'awsqmi-rds' && provision.scenario !== 'azqmi-synapse'">
<p *ngIf="!provision.schedule || provision.schedule.is24x7"> <p *ngIf="!provision.schedule || provision.schedule.is24x7">
<br> <br>
<i><mdb-icon fas icon="info-circle"></mdb-icon>VMs will run nonstop during the next 7 days. Then, they'll auto-shutdown if you don't renew 24x7 period</i> <i><mdb-icon fas icon="info-circle"></mdb-icon>VMs will run nonstop during the next 7 days. Then, they'll auto-shutdown if you don't renew 24x7 period</i>
@@ -52,7 +52,7 @@
<i><mdb-icon fas icon="info-circle"></mdb-icon> As scheduled, next shutdown will be at <b>{{provision.schedule.localeShutdownTime}}h</b> ({{provision.schedule.localTimezone}})</i> <i><mdb-icon fas icon="info-circle"></mdb-icon> As scheduled, next shutdown will be at <b>{{provision.schedule.localeShutdownTime}}h</b> ({{provision.schedule.localTimezone}})</i>
</p> </p>
</div> </div>
<div *ngIf="provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse'"> <div *ngIf="provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse'">
<p> <p>
<br> <br>
<i><mdb-icon fas icon="info-circle"></mdb-icon> Be cost-conscious and stop this intance when you are done using it. </i> <i><mdb-icon fas icon="info-circle"></mdb-icon> Be cost-conscious and stop this intance when you are done using it. </i>

View File

@@ -89,10 +89,10 @@
<button style="margin-right: 2px;" mdbTooltip="Configure provision" *ngIf="provision.canManage && provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Configure provision" *ngIf="provision.canManage && provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button">
<mdb-icon fas icon="cog"></mdb-icon> <mdb-icon fas icon="cog"></mdb-icon>
</button> </button>
<button style="margin-right: 2px;" mdbTooltip="Stop" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmStopModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Stop" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmStopModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--stop" aria-hidden="true"></span> <span class="lui-icon lui-icon--stop" aria-hidden="true"></span>
</button> </button>
<button style="margin-right: 2px;" mdbTooltip="Start" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Start" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--run" aria-hidden="true"></span> <span class="lui-icon lui-icon--run" aria-hidden="true"></span>
</button> </button>
<!--<button style="margin-right: 5px;" mdbTooltip="Renew 24x7 period" *ngIf="(!provision.schedule || provision.schedule.is24x7) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmExtendModal(provision)" class="lui-button"> <!--<button style="margin-right: 5px;" mdbTooltip="Renew 24x7 period" *ngIf="(!provision.schedule || provision.schedule.is24x7) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmExtendModal(provision)" class="lui-button">

View File

@@ -101,10 +101,10 @@
<button style="margin-right: 2px;" mdbTooltip="Configure provision" *ngIf="provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Configure provision" *ngIf="provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button">
<mdb-icon fas icon="cog"></mdb-icon> <mdb-icon fas icon="cog"></mdb-icon>
</button> </button>
<button style="margin-right: 2px;" mdbTooltip="Stop" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmStopModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Stop" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Running'" (click)="openConfirmStopModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--stop" aria-hidden="true"></span> <span class="lui-icon lui-icon--stop" aria-hidden="true"></span>
</button> </button>
<button style="margin-right: 2px;" mdbTooltip="Start" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Start" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--run" aria-hidden="true"></span> <span class="lui-icon lui-icon--run" aria-hidden="true"></span>
</button> </button>
<button style="margin-right: 2px;" mdbTooltip="Open Remote Access (VPN needed)" *ngIf="(provision.outputs && (provision.outputs.WEB_SSH_ACCESS_WITH_GUACAMOLE || provision.outputs.WEB_RDP_ACCESS_WITH_GUACAMOLE) && provision.status === 'provisioned')" (click)="openRemoteAccess(provision)" class="lui-button"> <button style="margin-right: 2px;" mdbTooltip="Open Remote Access (VPN needed)" *ngIf="(provision.outputs && (provision.outputs.WEB_SSH_ACCESS_WITH_GUACAMOLE || provision.outputs.WEB_RDP_ACCESS_WITH_GUACAMOLE) && provision.status === 'provisioned')" (click)="openRemoteAccess(provision)" class="lui-button">

View File

@@ -104,10 +104,10 @@
<button style="margin-right: 3px;" title="Abort provision" *ngIf="!provision.isDestroyed && provision.status === 'provisioning'" (click)="openConfirmAbortModal(provision)" class="lui-button lui-text-danger"> <button style="margin-right: 3px;" title="Abort provision" *ngIf="!provision.isDestroyed && provision.status === 'provisioning'" (click)="openConfirmAbortModal(provision)" class="lui-button lui-text-danger">
Abort Abort
</button> </button>
<button style="margin-right: 3px;" title="Stop" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && !provision.isDestroyed && provision.status === 'provisioned' && (provision.statusVms === 'Running' || provision.statusVms === 'N/A') " (click)="openConfirmStopModal(provision)" class="lui-button"> <button style="margin-right: 3px;" title="Stop" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && !provision.isDestroyed && provision.status === 'provisioned' && (provision.statusVms === 'Running' || provision.statusVms === 'N/A') " (click)="openConfirmStopModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--stop" aria-hidden="true"></span> <span class="lui-icon lui-icon--stop" aria-hidden="true"></span>
</button> </button>
<button style="margin-right: 3px;" title="Start" *ngIf="(provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && !provision.isDestroyed && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button"> <button style="margin-right: 3px;" title="Start" *ngIf="(provision.scenario === 'awsqmi-redshift' || provision.scenario === 'awsqmi-rds' || provision.scenario === 'azqmi-synapse' || provision.vmImage && provision.vmImage.vm1 || provision.options && provision.options.vm1) && !provision.isDestroyed && provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button">
<span class="lui-icon lui-icon--run" aria-hidden="true"></span> <span class="lui-icon lui-icon--run" aria-hidden="true"></span>
</button> </button>
<button style="margin-right: 3px;" title="Destroy provision" *ngIf="!provision.isDestroyed && (!provision.destroy || provision.destroy.status !== 'destroying') && (provision.status === 'provisioned' || provision.status === 'error' || provision.status === 'aborted' )" (click)="openConfirmDestroyModal(provision)" class="lui-button lui-text-danger"> <button style="margin-right: 3px;" title="Destroy provision" *ngIf="!provision.isDestroyed && (!provision.destroy || provision.destroy.status !== 'destroying') && (provision.status === 'provisioned' || provision.status === 'error' || provision.status === 'aborted' )" (click)="openConfirmDestroyModal(provision)" class="lui-button lui-text-danger">

View File

@@ -5299,29 +5299,6 @@ chardet@^0.7.0:
resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chart.js@^2.9.3:
version "2.9.4"
resolved "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz"
integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==
dependencies:
chartjs-color "^2.1.0"
moment "^2.10.2"
chartjs-color-string@^0.6.0:
version "0.6.0"
resolved "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz"
integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
dependencies:
color-name "^1.0.0"
chartjs-color@^2.1.0:
version "2.4.1"
resolved "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz"
integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
dependencies:
chartjs-color-string "^0.6.0"
color-convert "^1.9.3"
chokidar@3.5.3: chokidar@3.5.3:
version "3.5.3" version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
@@ -5504,7 +5481,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0" map-visit "^1.0.0"
object-visit "^1.0.0" object-visit "^1.0.0"
color-convert@^1.9.0, color-convert@^1.9.3: color-convert@^1.9.0:
version "1.9.3" version "1.9.3"
resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -5523,7 +5500,7 @@ color-name@1.1.3:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.0.0, color-name@~1.1.4: color-name@~1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
@@ -12388,16 +12365,7 @@ streamroller@^3.1.5:
debug "^4.3.4" debug "^4.3.4"
fs-extra "^8.1.0" fs-extra "^8.1.0"
"string-width-cjs@npm:string-width@^4.2.0": "string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -12458,7 +12426,7 @@ string_decoder@^1.1.1, string_decoder@~1.1.1:
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1": "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -12479,13 +12447,6 @@ strip-ansi@^4.0.0:
dependencies: dependencies:
ansi-regex "^3.0.0" ansi-regex "^3.0.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1: strip-ansi@^7.0.1:
version "7.1.0" version "7.1.0"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz"
@@ -13563,7 +13524,7 @@ worker-farm@^1.7.0:
dependencies: dependencies:
errno "~0.1.7" errno "~0.1.7"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -13581,15 +13542,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0" string-width "^4.1.0"
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0: wrap-ansi@^8.1.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"