You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by li...@apache.org on 2022/11/23 02:27:11 UTC
[incubator-devlake] branch main updated: feat(config-ui): encapsulate base layout component (#3770)
This is an automated email from the ASF dual-hosted git repository.
likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 31b457e30 feat(config-ui): encapsulate base layout component (#3770)
31b457e30 is described below
commit 31b457e30419da9297273364d86ced7f74bb885c
Author: 青湛 <0x...@gmail.com>
AuthorDate: Wed Nov 23 10:27:06 2022 +0800
feat(config-ui): encapsulate base layout component (#3770)
* feat(config-ui): encapsulate base layout component
* refactor(config-ui): adjust page routing to support the global layout
* refactor(config-ui): remove old content about nav and sidebar
* fix(config-ui): menu key duplicate
* refactor(config-ui): adjust some style
* fix(config-ui): miss header in index.d.ts file
* refactor(config-ui): modify plugin import method
---
config-ui/package-lock.json | 317 ++++++-
config-ui/package.json | 3 +-
config-ui/src/App.js | 166 ++--
config-ui/src/components/ErrorBoundary.jsx | 122 ++-
config-ui/src/components/Nav.jsx | 124 ---
config-ui/src/components/Sidebar.jsx | 117 ---
.../src/components/Sidebar/MenuConfiguration.jsx | 152 ----
config-ui/src/components/Sidebar/SidebarMenu.jsx | 86 --
.../src/{components/Content.jsx => index.d.ts} | 9 +-
config-ui/src/layouts/base/base.tsx | 150 ++++
.../Content.jsx => layouts/base/index.ts} | 8 +-
config-ui/src/layouts/base/styled.ts | 131 +++
config-ui/src/layouts/base/use-menu.ts | 85 ++
.../{components/Content.jsx => layouts/index.ts} | 8 +-
config-ui/src/models/MenuItem.js | 53 --
.../src/pages/blueprints/blueprint-detail.jsx | 917 ++++++++++-----------
.../src/pages/blueprints/blueprint-settings.jsx | 510 ++++++------
.../src/pages/blueprints/create-blueprint.jsx | 388 +++++----
config-ui/src/pages/blueprints/index.jsx | 243 +++---
.../pages/configure/connections/AddConnection.jsx | 188 ++---
.../configure/connections/ConfigureConnection.jsx | 370 ++++-----
.../src/pages/configure/integration/index.jsx | 193 ++---
.../src/pages/configure/integration/manage.jsx | 600 +++++++-------
.../pages/connections/incoming-webhook/index.jsx | 175 ++--
config-ui/src/registry/index.ts | 51 ++
config-ui/src/styles/app.scss | 2 +-
config-ui/src/styles/blueprints.scss | 8 +-
config-ui/src/styles/common.scss | 22 +-
config-ui/src/styles/integration.scss | 6 +-
config-ui/src/styles/nav.scss | 83 --
config-ui/src/styles/sidebar-menu.scss | 80 --
config-ui/src/styles/sidebar.scss | 82 --
32 files changed, 2554 insertions(+), 2895 deletions(-)
diff --git a/config-ui/package-lock.json b/config-ui/package-lock.json
index 73ddcbb82..04fdfbf2a 100644
--- a/config-ui/package-lock.json
+++ b/config-ui/package-lock.json
@@ -1520,27 +1520,101 @@
}
},
"@blueprintjs/popover2": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/@blueprintjs/popover2/-/popover2-0.11.4.tgz",
- "integrity": "sha512-KTietd+thBzeen9yP0WWzHJDAaqoey1H3AXvjaF94ypQQKdUaIzSmIop9Z3lJK44ynlYiI+dSzFYQbRdbpd0/w==",
- "requires": {
- "@blueprintjs/core": "^3.49.1",
- "@popperjs/core": "^2.5.4",
- "classnames": "^2.2",
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/popover2/-/popover2-1.10.1.tgz",
+ "integrity": "sha512-WWKCvwvPoDUeAXUfsWg5aqbSFI09H+EGbsKZ8CVyRLHC3K0j6k4ljI6ic9iTiDUXLD/0TKGFCd1mOy9GOGaONg==",
+ "requires": {
+ "@blueprintjs/core": "^4.12.0",
+ "@juggle/resize-observer": "^3.4.0",
+ "@popperjs/core": "^2.11.6",
+ "classnames": "^2.3.1",
"dom4": "^2.1.5",
- "react-popper": "^2.2.4",
- "resize-observer-polyfill": "^1.5.1",
- "tslib": "~1.13.0"
+ "react-popper": "^2.3.0",
+ "tslib": "~2.3.1"
},
"dependencies": {
+ "@blueprintjs/colors": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/colors/-/colors-4.1.9.tgz",
+ "integrity": "sha512-AxBKGwHS9Ojs7YPRMiwDlUEnSG36P/Hi0C3i4/smPmzUzqFGp1ZDqTmBBM15XoUKIuYfmpNATqIdKgNx2OzOkg=="
+ },
+ "@blueprintjs/core": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-4.12.0.tgz",
+ "integrity": "sha512-obbtEMzKOTwB56vlw4A8+9lvYwtB1mK4S8/b5Dy7WqdJ66L1WfcbIWcGxc2jWsGxanvMIzi6Pd+0XXuRRNkmhQ==",
+ "requires": {
+ "@blueprintjs/colors": "^4.1.9",
+ "@blueprintjs/icons": "^4.10.1",
+ "@juggle/resize-observer": "^3.4.0",
+ "@types/dom4": "^2.0.2",
+ "classnames": "^2.3.1",
+ "dom4": "^2.1.5",
+ "normalize.css": "^8.0.1",
+ "popper.js": "^1.16.1",
+ "react-popper": "^1.3.11",
+ "react-transition-group": "^4.4.5",
+ "tslib": "~2.3.1"
+ },
+ "dependencies": {
+ "react-popper": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz",
+ "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "@hypnosphi/create-react-context": "^0.3.1",
+ "deep-equal": "^1.1.1",
+ "popper.js": "^1.14.4",
+ "prop-types": "^15.6.1",
+ "typed-styles": "^0.0.7",
+ "warning": "^4.0.2"
+ }
+ }
+ }
+ },
+ "@blueprintjs/icons": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-4.10.1.tgz",
+ "integrity": "sha512-VkEa+tzi2wZF51D2PmuKVl3krEuAudvpR8ziDQiXBbq9DPlN3Y+HrCJQzZ8LX7HtSbDp7v8k6f5/1T1ubH96SQ==",
+ "requires": {
+ "change-case": "^4.1.2",
+ "classnames": "^2.3.1",
+ "tslib": "~2.3.1"
+ }
+ },
+ "dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "requires": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"react-popper": {
- "version": "2.2.5",
- "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz",
- "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
+ "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
"requires": {
"react-fast-compare": "^3.0.1",
"warning": "^4.0.2"
}
+ },
+ "react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ }
+ },
+ "tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -2500,6 +2574,11 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
+ "@juggle/resize-observer": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
+ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
+ },
"@mapbox/rehype-prism": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@mapbox/rehype-prism/-/rehype-prism-0.8.0.tgz",
@@ -2594,9 +2673,9 @@
}
},
"@popperjs/core": {
- "version": "2.10.2",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
- "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ=="
+ "version": "2.11.6",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
+ "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
},
"@sindresorhus/is": {
"version": "0.14.0",
@@ -3017,6 +3096,12 @@
"@types/unist": "*"
}
},
+ "@types/history": {
+ "version": "4.7.11",
+ "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
+ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
+ "dev": true
+ },
"@types/html-minifier-terser": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz",
@@ -3137,6 +3222,27 @@
"csstype": "^3.0.2"
}
},
+ "@types/react-router": {
+ "version": "5.1.19",
+ "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.19.tgz",
+ "integrity": "sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA==",
+ "dev": true,
+ "requires": {
+ "@types/history": "^4.7.11",
+ "@types/react": "*"
+ }
+ },
+ "@types/react-router-dom": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
+ "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
+ "dev": true,
+ "requires": {
+ "@types/history": "^4.7.11",
+ "@types/react": "*",
+ "@types/react-router": "*"
+ }
+ },
"@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
@@ -4868,7 +4974,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
- "dev": true,
"requires": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
@@ -4877,8 +4982,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -4925,6 +5029,23 @@
"integrity": "sha512-VfEHpzHEXj6/CxggTwSFoZBBYGQfQv9Cf42KPlO79sWXCD1QNKWKsKzFeWL7QpZHJQYAvocqV6Rty1yJMkqWLQ==",
"dev": true
},
+ "capital-case": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz",
+ "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
+ "requires": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3",
+ "upper-case-first": "^2.0.2"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"capture-stack-trace": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
@@ -4951,6 +5072,32 @@
"supports-color": "^5.3.0"
}
},
+ "change-case": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz",
+ "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
+ "requires": {
+ "camel-case": "^4.1.2",
+ "capital-case": "^1.0.4",
+ "constant-case": "^3.0.4",
+ "dot-case": "^3.0.4",
+ "header-case": "^2.0.4",
+ "no-case": "^3.0.4",
+ "param-case": "^3.0.4",
+ "pascal-case": "^3.1.2",
+ "path-case": "^3.0.4",
+ "sentence-case": "^3.0.4",
+ "snake-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"char-regex": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
@@ -5588,6 +5735,23 @@
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"dev": true
},
+ "constant-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
+ "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
+ "requires": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3",
+ "upper-case": "^2.0.2"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"constants-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@@ -7013,7 +7177,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
- "dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
@@ -7022,8 +7185,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -9537,6 +9699,22 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
+ "header-case": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz",
+ "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
+ "requires": {
+ "capital-case": "^1.0.4",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"hex-color-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
@@ -13139,7 +13317,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
- "dev": true,
"requires": {
"tslib": "^2.0.3"
},
@@ -13147,8 +13324,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -13891,7 +14067,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
- "dev": true,
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
@@ -13900,8 +14075,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -14566,7 +14740,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
"integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
- "dev": true,
"requires": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
@@ -14575,8 +14748,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -14676,7 +14848,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
- "dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
@@ -14685,8 +14856,7 @@
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
- "dev": true
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
@@ -14702,6 +14872,22 @@
"integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
"dev": true
},
+ "path-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz",
+ "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
+ "requires": {
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
@@ -16962,6 +17148,23 @@
}
}
},
+ "sentence-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
+ "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
+ "requires": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3",
+ "upper-case-first": "^2.0.2"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"serialize-javascript": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
@@ -17220,6 +17423,22 @@
"babel-code-frame": "^6.26.0"
}
},
+ "snake-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
+ "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
+ "requires": {
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -18932,6 +19151,36 @@
}
}
},
+ "upper-case": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz",
+ "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
+ "requires": {
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
+ "upper-case-first": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
+ "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
+ "requires": {
+ "tslib": "^2.0.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
+ }
+ }
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/config-ui/package.json b/config-ui/package.json
index f0425b405..73a2c98eb 100644
--- a/config-ui/package.json
+++ b/config-ui/package.json
@@ -14,7 +14,7 @@
"dependencies": {
"@babel/eslint-parser": "^7.18.2",
"@blueprintjs/core": "^3.49.1",
- "@blueprintjs/popover2": "^0.11.4",
+ "@blueprintjs/popover2": "^1.4.1",
"@blueprintjs/select": "^3.18.10",
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
@@ -50,6 +50,7 @@
"@testing-library/react": "^12.1.1",
"@testing-library/user-event": "^13.2.1",
"@types/react": "^18.0.24",
+ "@types/react-router-dom": "^5.3.3",
"autoprefixer": "^9.8.6",
"babel-jest": "^27.2.3",
"babel-loader": "^8.2.2",
diff --git a/config-ui/src/App.js b/config-ui/src/App.js
index 1fdf94476..71a87c93d 100644
--- a/config-ui/src/App.js
+++ b/config-ui/src/App.js
@@ -17,7 +17,12 @@
*/
import React from 'react'
-import { BrowserRouter as Router, Route } from 'react-router-dom'
+import {
+ BrowserRouter as Router,
+ Route,
+ Switch,
+ Redirect
+} from 'react-router-dom'
import 'normalize.css'
import '@/styles/app.scss'
@@ -30,6 +35,7 @@ import '@fontsource/inter/variable-full.css'
// import '@/styles/theme.scss'
import useDatabaseMigrations from '@/hooks/useDatabaseMigrations'
+import { BaseLayout } from '@/layouts'
import ErrorBoundary from '@/components/ErrorBoundary'
import Integration from '@/pages/configure/integration/index'
import ManageIntegration from '@/pages/configure/integration/manage'
@@ -57,66 +63,104 @@ function App(props) {
return (
<Router>
- <Route exact path='/'>
- <ErrorBoundary>
- <Integration />
- </ErrorBoundary>
- </Route>
- <Route path='/integrations/:providerId'>
- <ErrorBoundary>
- <ManageIntegration />
- </ErrorBoundary>
- </Route>
- <Route path='/connections/add/:providerId'>
- <ErrorBoundary>
- <AddConnection />
- </ErrorBoundary>
- </Route>
- <Route path='/connections/configure/:providerId/:connectionId'>
- <ErrorBoundary>
- <ConfigureConnection />
- </ErrorBoundary>
- </Route>
- <Route exact path='/integrations'>
- <ErrorBoundary>
- <Integration />
- </ErrorBoundary>
- </Route>
- <Route exact path='/blueprints/create'>
- <ErrorBoundary>
- <CreateBlueprint />
- </ErrorBoundary>
- </Route>
- <Route exact path='/blueprints/detail/:bId'>
- <ErrorBoundary>
- <BlueprintDetail />
- </ErrorBoundary>
- </Route>
- <Route exact path='/blueprints/settings/:bId'>
- <ErrorBoundary>
- <BlueprintSettings />
- </ErrorBoundary>
- </Route>
- <Route exact path='/blueprints'>
- <ErrorBoundary>
- <Blueprints />
- </ErrorBoundary>
- </Route>
- <Route exact path='/connections/incoming-webhook'>
- <IncomingWebhookConnection />
- </Route>
- <Route exact path='/offline'>
- <Offline />
- </Route>
- <MigrationAlertDialog
- isOpen={migrationAlertOpened}
- onClose={handleMigrationDialogClose}
- onCancel={handleCancelMigration}
- onConfirm={handleConfirmMigration}
- isMigrating={isProcessing}
- wasSuccessful={wasMigrationSuccessful}
- hasFailed={hasMigrationFailed}
- />
+ <Switch>
+ <Route exact path='/offline' component={() => <Offline />} />
+
+ <Route>
+ <BaseLayout>
+ <Switch>
+ <Route
+ path='/'
+ exact
+ component={() => <Redirect to='/integrations' />}
+ />
+ <Route
+ exact
+ path='/integrations'
+ component={() => (
+ <ErrorBoundary>
+ <Integration />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ path='/integrations/:providerId'
+ component={() => (
+ <ErrorBoundary>
+ <ManageIntegration />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ path='/connections/add/:providerId'
+ component={() => (
+ <ErrorBoundary>
+ <AddConnection />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ path='/connections/configure/:providerId/:connectionId'
+ component={() => (
+ <ErrorBoundary>
+ <ConfigureConnection />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ exact
+ path='/connections/incoming-webhook'
+ component={() => <IncomingWebhookConnection />}
+ />
+ <Route
+ exact
+ path='/blueprints'
+ component={() => (
+ <ErrorBoundary>
+ <Blueprints />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ exact
+ path='/blueprints/create'
+ component={() => (
+ <ErrorBoundary>
+ <CreateBlueprint />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ exact
+ path='/blueprints/detail/:bId'
+ component={() => (
+ <ErrorBoundary>
+ <BlueprintDetail />
+ </ErrorBoundary>
+ )}
+ />
+ <Route
+ exact
+ path='/blueprints/settings/:bId'
+ component={() => (
+ <ErrorBoundary>
+ <BlueprintSettings />
+ </ErrorBoundary>
+ )}
+ />
+ </Switch>
+ <MigrationAlertDialog
+ isOpen={migrationAlertOpened}
+ onClose={handleMigrationDialogClose}
+ onCancel={handleCancelMigration}
+ onConfirm={handleConfirmMigration}
+ isMigrating={isProcessing}
+ wasSuccessful={wasMigrationSuccessful}
+ hasFailed={hasMigrationFailed}
+ />
+ </BaseLayout>
+ </Route>
+ </Switch>
</Router>
)
}
diff --git a/config-ui/src/components/ErrorBoundary.jsx b/config-ui/src/components/ErrorBoundary.jsx
index dca0ecf16..84dd91d7c 100644
--- a/config-ui/src/components/ErrorBoundary.jsx
+++ b/config-ui/src/components/ErrorBoundary.jsx
@@ -25,11 +25,6 @@ import {
Elevation,
Card
} from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
-import ContentLoader from '@/components/loaders/ContentLoader'
import { ReactComponent as Logo } from '@/images/devlake-logo.svg'
import { ReactComponent as LogoText } from '@/images/devlake-textmark.svg'
@@ -55,73 +50,60 @@ class ErrorBoundary extends React.Component {
render() {
if (this.state.hasError) {
return (
- <>
- <div className='container'>
- <Nav />
- <Content>
- <main className='main' style={{ marginLeft: 0 }}>
- <div className='headlineContainer'>
- <div style={{ display: 'flex', justifyContent: 'center' }}>
- <div>
- <div className='devlake-logo' style={{ margin: 0 }}>
- <Logo width={48} height={48} className='logo' />
- <LogoText
- width={100}
- height={13}
- className='logo-textmark'
- />
- </div>
- <h1 style={{ margin: 0, textAlign: 'center' }}>
- Application Error
- </h1>
- <Card
- elevation={Elevation.TWO}
- style={{ margin: '18px 0', maxWidth: '700px' }}
- >
- <h2 style={{ margin: 0 }}>
- <span
- style={{
- display: 'inline-block',
- marginRight: '10px'
- }}
- >
- <Icon icon='error' color={Colors.RED5} size={16} />
- </span>
- {this.state.error?.toString() || 'Unknown Error'}
- </h2>
- <p style={{ margin: 0 }}>
- Please try again, if the problem persists include the
- above error message when filing a bug report on{' '}
- <strong>GitHub</strong>. You can also message us on{' '}
- <strong>Slack</strong> to engage with community
- members for solutions to common issues.
- </p>
- <p
- style={{ margin: '18px 0 0 0', textAlign: 'center' }}
- >
- <Button
- onClick={() => this.props.history.push('/')}
- text='Continue'
- intent={Intent.PRIMARY}
- />
- <a
- href='https://github.com/apache/incubator-devlake'
- className='bp3-button bp3-outlined'
- target='_blank'
- style={{ marginLeft: '10px' }}
- rel='noreferrer'
- >
- Visit GitHub
- </a>
- </p>
- </Card>
- </div>
- </div>
+ <main className='main' style={{ marginLeft: 0 }}>
+ <div className='headlineContainer'>
+ <div style={{ display: 'flex', justifyContent: 'center' }}>
+ <div>
+ <div className='devlake-logo' style={{ margin: 0 }}>
+ <Logo width={48} height={48} className='logo' />
+ <LogoText width={100} height={13} className='logo-textmark' />
</div>
- </main>
- </Content>
+ <h1 style={{ margin: 0, textAlign: 'center' }}>
+ Application Error
+ </h1>
+ <Card
+ elevation={Elevation.TWO}
+ style={{ margin: '18px 0', maxWidth: '700px' }}
+ >
+ <h2 style={{ margin: 0 }}>
+ <span
+ style={{
+ display: 'inline-block',
+ marginRight: '10px'
+ }}
+ >
+ <Icon icon='error' color={Colors.RED5} size={16} />
+ </span>
+ {this.state.error?.toString() || 'Unknown Error'}
+ </h2>
+ <p style={{ margin: 0 }}>
+ Please try again, if the problem persists include the above
+ error message when filing a bug report on{' '}
+ <strong>GitHub</strong>. You can also message us on{' '}
+ <strong>Slack</strong> to engage with community members for
+ solutions to common issues.
+ </p>
+ <p style={{ margin: '18px 0 0 0', textAlign: 'center' }}>
+ <Button
+ onClick={() => this.props.history.push('/')}
+ text='Continue'
+ intent={Intent.PRIMARY}
+ />
+ <a
+ href='https://github.com/apache/incubator-devlake'
+ className='bp3-button bp3-outlined'
+ target='_blank'
+ style={{ marginLeft: '10px' }}
+ rel='noreferrer'
+ >
+ Visit GitHub
+ </a>
+ </p>
+ </Card>
+ </div>
+ </div>
</div>
- </>
+ </main>
)
}
diff --git a/config-ui/src/components/Nav.jsx b/config-ui/src/components/Nav.jsx
deleted file mode 100644
index 347865f42..000000000
--- a/config-ui/src/components/Nav.jsx
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-import React, { useCallback, useContext, useEffect, useState } from 'react'
-import { Position, Popover, Navbar, Icon } from '@blueprintjs/core'
-import '@/styles/nav.scss'
-import { ReactComponent as SlackIcon } from '@/images/slack-mark-monochrome-black.svg'
-import { ReactComponent as SlackLogo } from '@/images/slack-rgb.svg'
-import UIContext from '@/store/UIContext'
-import useWindowSize from '@/hooks/useWIndowSize'
-
-const Nav = () => {
- const { changeSidebarVisibility, desktopBreakpointWidth, sidebarVisible } =
- useContext(UIContext)
- const [menuClass, setMenuClass] = useState('navbarMenuButton')
- const size = useWindowSize()
-
- const toggleSidebarOpen = useCallback(
- (open) => {
- changeSidebarVisibility(open)
- setMenuClass(() =>
- open ? 'navbarMenuButtonSidebarOpened' : 'navbarMenuButton'
- )
- },
- [changeSidebarVisibility]
- )
-
- useEffect(
- () =>
- desktopBreakpointWidth <= size.width
- ? toggleSidebarOpen(true)
- : toggleSidebarOpen(false),
- [size, toggleSidebarOpen, desktopBreakpointWidth]
- )
-
- return (
- <Navbar className='navbar'>
- <Navbar.Group className={menuClass}>
- <Icon
- icon={sidebarVisible ? 'menu-closed' : 'menu-open'}
- onClick={(e) => toggleSidebarOpen(!sidebarVisible)}
- size={16}
- />
- </Navbar.Group>
- {!sidebarVisible && (
- <Navbar.Group className='navbarItems'>
- <a
- href='https://github.com/apache/incubator-devlake'
- rel='noreferrer'
- target='_blank'
- className='navIconLink'
- >
- <Icon icon='git-branch' size={16} />
- </a>
- <Navbar.Divider />
- <a
- href='mailto:hello@merico.dev'
- rel='noreferrer'
- target='_blank'
- className='navIconLink'
- >
- <Icon icon='envelope' size={16} />
- </a>
- <Navbar.Divider />
- {/* DISCORD: !DISABLED! */}
- {/* <a href='https://discord.com/invite/83rDG6ydVZ' rel='noreferrer' target='_blank' className='navIconLink'>
- <DiscordIcon className='discordIcon' width={16} height={16} />
- </a> */}
- {/* SLACK: ENABLED (Primary) */}
- <Popover position={Position.LEFT}>
- <SlackIcon
- className='slackIcon'
- width={16}
- height={16}
- style={{ cursor: 'pointer' }}
- />
- <>
- <div
- style={{ maxWidth: '200px', padding: '10px', fontSize: '11px' }}
- >
- <SlackLogo
- width={131}
- height={49}
- style={{ display: 'block', margin: '0 auto' }}
- />
- <p style={{ textAlign: 'center' }}>
- Want to interact with the <strong>Merico Community</strong>?
- Join us on our Slack Channel.
- <br />
- <a
- href='https://join.slack.com/t/devlake-io/shared_invite/zt-17b6vuvps-x98pqseoUagM7EAmKC82xQ'
- rel='noreferrer'
- target='_blank'
- className='bp3-button bp3-intent-warning bp3-elevation-1 bp3-small'
- style={{ marginTop: '10px' }}
- >
- Message us on 
- <strong>Slack</strong>
- </a>
- </p>
- </div>
- </>
- </Popover>
- </Navbar.Group>
- )}
- </Navbar>
- )
-}
-
-export default Nav
diff --git a/config-ui/src/components/Sidebar.jsx b/config-ui/src/components/Sidebar.jsx
deleted file mode 100644
index 5714353ec..000000000
--- a/config-ui/src/components/Sidebar.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-import React, {
- useEffect,
- useState,
- useContext,
- useMemo,
- useCallback
-} from 'react'
-import {
- // BrowserRouter as Router,
- useRouteMatch
-} from 'react-router-dom'
-import { Card, Elevation } from '@blueprintjs/core'
-import request from '@/utils/request'
-import SidebarMenu from '@/components/Sidebar/SidebarMenu'
-import MenuConfiguration from '@/components/Sidebar/MenuConfiguration'
-import { DEVLAKE_ENDPOINT } from '@/utils/config'
-import { ReactComponent as Logo } from '@/images/devlake-logo.svg'
-import { ReactComponent as LogoText } from '@/images/devlake-textmark.svg'
-
-import '@/styles/sidebar.scss'
-import UIContext from '@/store/UIContext'
-
-const Sidebar = (props) => {
- const { integrations = [] } = props
- const activeRoute = useRouteMatch()
- const uiContext = useContext(UIContext)
-
- const getMenu = useCallback(
- () => MenuConfiguration(activeRoute, integrations),
- [activeRoute, integrations]
- )
-
- const ActiveMenu = useMemo(() => getMenu(), [getMenu])
-
- const [menu, setMenu] = useState(ActiveMenu)
- const [versionTag, setVersionTag] = useState('')
-
- // useEffect(() => {
- // setMenu(ActiveMenu)
- // }, [ActiveMenu])
-
- useEffect(() => {
- // @todo: re-enable version fetch
- // const fetchVersion = async () => {
- // try {
- // const versionUrl = `${DEVLAKE_ENDPOINT}/version`
- // const res = await request.get(versionUrl).catch((e) => {
- // console.log('>>> API VERSION ERROR...', e)
- // setVersionTag('')
- // })
- // setVersionTag(res?.data ? res.data?.version : '')
- // } catch (e) {
- // setVersionTag('')
- // }
- // }
- // fetchVersion()
- }, [])
-
- // useEffect(() => {}, [integrations])
-
- return uiContext.sidebarVisible ? (
- <Card
- interactive={false}
- elevation={Elevation.ZERO}
- className='card sidebar-card'
- >
- <div className='devlake-logo'>
- <Logo width={48} height={48} className='logo' />
- <LogoText width={100} height={13} className='logo-textmark' />
- </div>
- {/* <a href={GRAFANA_URL} rel='noreferrer' target='_blank' className='dashboardBtnLink'>
- <Button icon='grouped-bar-chart' outlined={true} className='dashboardBtn'>View Dashboards</Button>
- </a> */}
-
- {/* <h3
- className='sidebar-app-heading'
- style={{
- marginTop: '30px',
- letterSpacing: '3px',
- marginBottom: 0,
- fontWeight: 900,
- color: '#444444',
- textAlign: 'center'
- }}
- >
- <sup style={{ fontSize: '9px', color: '#cccccc', marginLeft: '-30px' }}>DEV</sup>LAKE
- </h3> */}
- <SidebarMenu menu={ActiveMenu} />
- <span className='copyright-tag'>
- {/* <span className='version-tag'>{versionTag || ''}</span><br /> */}
- <strong>Apache 2.0 License</strong>
- <br />
- </span>
- </Card>
- ) : (
- <></>
- )
-}
-
-export default Sidebar
diff --git a/config-ui/src/components/Sidebar/MenuConfiguration.jsx b/config-ui/src/components/Sidebar/MenuConfiguration.jsx
deleted file mode 100644
index ce51c3a37..000000000
--- a/config-ui/src/components/Sidebar/MenuConfiguration.jsx
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-import React from 'react'
-// import { ProviderLabels } from '@/data/Providers'
-import { GRAFANA_URL } from '@/utils/config'
-import MenuItem from '@/models/MenuItem'
-
-const MenuConfiguration = (activeRoute, integrations = []) => {
- return [
- {
- id: 0,
- label: 'Data Connections',
- route: '/integrations',
- active:
- activeRoute.url.startsWith('/integrations') || activeRoute.url === '/',
- icon: 'data-connection',
- classNames: [],
- children: integrations.map(
- (p, pIdx) =>
- new MenuItem({
- id: pIdx,
- // @todo: support disable prop with json config
- // disabled: false,
- label: p?.name,
- route: `/integrations/${p?.id}`,
- active:
- activeRoute.url.endsWith(`/integrations/${p?.id}`) ||
- activeRoute.url.endsWith(`${p.id}`),
- icon: p?.icon ? (
- <img
- className='providerMenuIconSvg'
- src={'/' + p?.icon}
- width={16}
- height={16}
- style={{
- display: 'flex',
- alignSelf: 'center',
- width: '16px',
- height: '16px'
- }}
- />
- ) : (
- 'layers'
- ),
- classNames: []
- // children: []
- })
- )
- },
- {
- id: 1,
- label: 'Blueprints',
- icon: 'home',
- route: '/blueprints',
- disabled: false,
- active: activeRoute.url === '/blueprints',
- children: [
- {
- id: 0,
- label: 'Create Bluepint',
- route: '/blueprints/create',
- active: activeRoute.url.endsWith('/blueprints/create'),
- icon: 'git-pull',
- classNames: []
- }
- ]
- },
- {
- id: 2,
- label: 'Connections',
- disabled: true,
- icon: 'git-merge',
- classNames: [],
- route: '/connections',
- active: activeRoute.url === '/connections',
- children: []
- },
- {
- id: 2,
- label: 'Dashboard',
- icon: 'dashboard',
- classNames: [],
- route: GRAFANA_URL,
- active: false,
- children: []
- }
- // {
- // id: 3,
- // label: 'Pipelines',
- // icon: 'git-merge',
- // classNames: [],
- // route: '/pipelines',
- // active: activeRoute.url.startsWith('/pipelines'),
- // children: [
- // {
- // id: 0,
- // label: 'Create Pipeline Run',
- // route: '/pipelines/create',
- // active: activeRoute.url.endsWith('/pipelines/create'),
- // icon: 'git-pull',
- // classNames: [],
- // },
- // {
- // id: 1,
- // label: 'All Pipeline Runs',
- // route: '/pipelines',
- // active: activeRoute.url.endsWith('/pipelines'),
- // icon: 'layers',
- // classNames: [],
- // disabled: false
- // },
- // {
- // id: 2,
- // label: 'Pipeline Blueprints',
- // route: '/blueprints',
- // active: activeRoute.url.endsWith('/blueprints'),
- // icon: 'grid',
- // classNames: [],
- // },
- // ]
- // },
- // {
- // id: 3,
- // label: 'Documentation',
- // icon: 'help',
- // classNames: [],
- // route: 'https://github.com/apache/incubator-devlake/wiki',
- // target: "_blank",
- // external: true,
- // active: activeRoute.url === '/documentation',
- // children: [
- // ]
- // },
- ]
-}
-
-export default MenuConfiguration
diff --git a/config-ui/src/components/Sidebar/SidebarMenu.jsx b/config-ui/src/components/Sidebar/SidebarMenu.jsx
deleted file mode 100644
index 65b9d4d77..000000000
--- a/config-ui/src/components/Sidebar/SidebarMenu.jsx
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-import React, { useEffect, Fragment } from 'react'
-import { Menu } from '@blueprintjs/core'
-import '@/styles/sidebar-menu.scss'
-import { useHistory } from 'react-router-dom'
-
-const SidebarMenu = (props) => {
- const history = useHistory()
- const { menu } = props
- // const activeRoute = useRouteMatch()
-
- useEffect(() => {}, [menu])
-
- const handleProviderClick = (e, route) => {
- // use history when route is not absolute url.
- if (route && !route.includes('//')) {
- e.preventDefault()
- e.stopPropagation()
- history.push(route)
- }
- }
-
- return (
- <>
- <Menu className='sidebarMenu' style={{ marginTop: '10px' }}>
- {menu.map((m, mIdx) =>
- m.children.length === 0 ? (
- <Menu.Item
- active={m.active}
- key={`menu-item-key${mIdx}`}
- icon={m.icon}
- text={m.label}
- href={m.route}
- onClick={(e) => handleProviderClick(e, m.route)}
- target={m.target}
- disabled={m.disabled}
- />
- ) : (
- <Menu.Item
- className='is-submenu has-children'
- active={m.active}
- key={`menu-item-key${mIdx}`}
- text={m.label}
- icon={m.icon}
- href={m.route}
- onClick={(e) => handleProviderClick(e, m.route)}
- disabled={m.disabled}
- >
- {m.children.map((mS, mSidx) => (
- <Menu.Item
- active={mS.active}
- key={`submenu-${mIdx}-item-key${mSidx}`}
- href={m.route}
- onClick={(e) => handleProviderClick(e, mS.route)}
- icon={mS.icon}
- text={mS.label}
- disabled={mS.disabled}
- // className={mS.classNames.join(' ')}
- />
- ))}
- </Menu.Item>
- )
- )}
- <Menu.Divider />
- </Menu>
- </>
- )
-}
-
-export default SidebarMenu
diff --git a/config-ui/src/components/Content.jsx b/config-ui/src/index.d.ts
similarity index 83%
copy from config-ui/src/components/Content.jsx
copy to config-ui/src/index.d.ts
index b9096cb7b..bfdcc83e0 100644
--- a/config-ui/src/components/Content.jsx
+++ b/config-ui/src/index.d.ts
@@ -15,11 +15,8 @@
* limitations under the License.
*
*/
-import React, { Fragment } from 'react'
-import '@/styles/common.scss'
-const Content = ({ children }) => {
- return <>{children}</>
+declare module '*.svg' {
+ const content: any
+ export default content
}
-
-export default Content
diff --git a/config-ui/src/layouts/base/base.tsx b/config-ui/src/layouts/base/base.tsx
new file mode 100644
index 000000000..928f483cc
--- /dev/null
+++ b/config-ui/src/layouts/base/base.tsx
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import React from 'react'
+import { useLocation, useHistory } from 'react-router-dom'
+import {
+ Menu,
+ MenuItem,
+ Navbar,
+ Icon,
+ Button,
+ Alignment,
+ Position,
+ Intent
+} from '@blueprintjs/core'
+import { Popover2 } from '@blueprintjs/popover2'
+
+import Logo from '@/images/devlake-logo.svg'
+import LogoText from '@/images/devlake-textmark.svg'
+import SlackIcon from '@/images/slack-mark-monochrome-black.svg'
+import SlackLogo from '@/images/slack-rgb.svg'
+
+import { useMenu, MenuItemType } from './use-menu'
+import * as S from './styled'
+
+interface Props {
+ children: React.ReactNode
+}
+
+export const BaseLayout = ({ children }: Props) => {
+ const menu = useMenu()
+ const { pathname } = useLocation()
+ const history = useHistory()
+
+ const handlePushPath = (it: MenuItemType) => {
+ if (!it.target) {
+ history.push(it.path)
+ } else {
+ window.open(it.path, '_blank')
+ }
+ }
+
+ return (
+ <S.Container>
+ <S.Sider>
+ <div className='logo'>
+ <img src={Logo} alt='' />
+ <img src={LogoText} alt='' />
+ </div>
+ <Menu className='menu'>
+ {menu.map((it) => (
+ <MenuItem
+ key={it.key}
+ className='menu-item'
+ text={it.title}
+ icon={it.icon}
+ active={pathname.includes(it.path)}
+ onClick={() => handlePushPath(it)}
+ >
+ {it.children?.map((cit) => (
+ <MenuItem
+ key={cit.key}
+ className='sub-menu-item'
+ text={cit.title}
+ icon={cit.icon ?? <img src={cit.iconUrl} width={16} alt='' />}
+ active={pathname.includes(cit.path)}
+ onClick={() => handlePushPath(cit)}
+ />
+ ))}
+ </MenuItem>
+ ))}
+ </Menu>
+ <div className='copyright'>
+ <span>Apache 2.0 License</span>
+ </div>
+ </S.Sider>
+ <S.Inner>
+ <S.Header>
+ <Navbar.Group align={Alignment.RIGHT}>
+ <a
+ href='https://github.com/apache/incubator-devlake'
+ rel='noreferrer'
+ target='_blank'
+ >
+ <Icon icon='git-branch' size={16} />
+ </a>
+ <Navbar.Divider />
+ <a
+ href='mailto:hello@merico.dev'
+ rel='noreferrer'
+ target='_blank'
+ className='navIconLink'
+ >
+ <Icon icon='envelope' size={16} />
+ </a>
+ <Navbar.Divider />
+ <Popover2
+ position={Position.LEFT}
+ content={
+ <S.SlackContainer>
+ <img src={SlackLogo} alt='' />
+ <p>
+ <span>Want to interact with the </span>
+ <strong>Merico Community</strong>
+ <span>? Join us on our Slack Channel.</span>
+ </p>
+ <p>
+ <a
+ href='https://join.slack.com/t/devlake-io/shared_invite/zt-17b6vuvps-x98pqseoUagM7EAmKC82xQ'
+ rel='noreferrer'
+ target='_blank'
+ >
+ <Button intent={Intent.WARNING}>
+ <span>Message us on </span>
+ <strong>Slack</strong>
+ </Button>
+ </a>
+ </p>
+ </S.SlackContainer>
+ }
+ >
+ <img
+ src={SlackIcon}
+ width={30}
+ alt=''
+ style={{ cursor: 'pointer' }}
+ />
+ </Popover2>
+ </Navbar.Group>
+ </S.Header>
+ <S.Content>{children}</S.Content>
+ </S.Inner>
+ </S.Container>
+ )
+}
diff --git a/config-ui/src/components/Content.jsx b/config-ui/src/layouts/base/index.ts
similarity index 83%
copy from config-ui/src/components/Content.jsx
copy to config-ui/src/layouts/base/index.ts
index b9096cb7b..0852d9746 100644
--- a/config-ui/src/components/Content.jsx
+++ b/config-ui/src/layouts/base/index.ts
@@ -15,11 +15,5 @@
* limitations under the License.
*
*/
-import React, { Fragment } from 'react'
-import '@/styles/common.scss'
-const Content = ({ children }) => {
- return <>{children}</>
-}
-
-export default Content
+export * from './base'
diff --git a/config-ui/src/layouts/base/styled.ts b/config-ui/src/layouts/base/styled.ts
new file mode 100644
index 000000000..6cad37d6c
--- /dev/null
+++ b/config-ui/src/layouts/base/styled.ts
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import styled from '@emotion/styled'
+import { Navbar } from '@blueprintjs/core'
+
+export const Container = styled.div`
+ display: flex;
+ min-height: 100vh;
+`
+
+export const Sider = styled.div`
+ flex: 0 0 250px;
+ position: relative;
+ width: 250px;
+ background-color: #292b3f;
+
+ .logo {
+ display: flex;
+ text-align: center;
+ flex-direction: column;
+ align-items: center;
+ margin: 20px 0;
+
+ img:first-child {
+ width: 48px;
+ height: 48px;
+ }
+
+ img:last-child {
+ margin-top: 10px;
+ width: 100px;
+ height: 13px;
+ }
+ }
+
+ .menu {
+ margin: 0 20px;
+ color: #fff;
+ background-color: transparent;
+
+ .menu-item,
+ .sub-menu-item {
+ display: flex;
+ align-items: center;
+ margin: 2px 0;
+ line-height: 26px;
+ transition: all 0.3s ease;
+ border-radius: 8px;
+ outline: none;
+ cursor: pointer;
+
+ &:hover {
+ background-color: rgba(167, 182, 194, 0.3);
+ }
+
+ &.bp3-active:hover {
+ background-color: #7497f7;
+ }
+
+ .bp3-icon {
+ svg {
+ width: 12px;
+ height: 12px;
+ }
+ }
+ }
+
+ .sub-menu-item {
+ border-radius: 3px;
+ }
+ }
+
+ .copyright {
+ position: absolute;
+ right: 0;
+ bottom: 30px;
+ left: 0;
+ text-align: center;
+ color: rgba(124, 124, 124, 0.7);
+ }
+`
+
+export const Inner = styled.div`
+ display: flex;
+ flex-direction: column;
+ flex: auto;
+ min-height: 100vh;
+`
+
+export const Header = styled(Navbar)`
+ flex: 0 0 50px;
+ box-shadow: none;
+`
+
+export const Content = styled.div`
+ flex: auto;
+ padding: 16px 24px;
+`
+
+export const SlackContainer = styled.div`
+ padding: 10px;
+ width: 200px;
+ font-size: 12px;
+
+ & > img {
+ display: block;
+ margin: 0 auto;
+ width: 130px;
+ height: 50px;
+ }
+
+ & > p {
+ text-align: center;
+ }
+`
diff --git a/config-ui/src/layouts/base/use-menu.ts b/config-ui/src/layouts/base/use-menu.ts
new file mode 100644
index 000000000..22d95f85d
--- /dev/null
+++ b/config-ui/src/layouts/base/use-menu.ts
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { useMemo } from 'react'
+import { IconName } from '@blueprintjs/core'
+
+import { Plugins } from '@/registry'
+
+export type MenuItemType = {
+ key: string
+ title: string
+ icon?: IconName
+ iconUrl?: string
+ path: string
+ children?: MenuItemType[]
+ target?: boolean
+}
+
+export const useMenu = () => {
+ const getGrafanaUrl = () => {
+ const suffix = '/d/0Rjxknc7z/demo-homepage?orgId=1'
+ const {protocol, hostname} = window.location
+
+ return process.env.LOCAL
+ ? `${protocol}//${hostname}:3002${suffix}`
+ : `/grafana/${suffix}`
+ }
+
+ return useMemo(
+ () =>
+ [
+ {
+ key: 'connection',
+ title: 'Data Connections',
+ icon: 'data-connection',
+ path: '/integrations',
+ children: Plugins.filter((p) => p.type === 'integration').map(
+ (it) => ({
+ key: it.id,
+ title: it.name,
+ iconUrl: `/${it.icon}`,
+ path: `/integrations/${it.id}`
+ })
+ )
+ },
+ {
+ key: 'blueprint',
+ title: 'Blueprints',
+ icon: 'home',
+ path: '/blueprints',
+ children: [
+ {
+ key: 'create-blueprint',
+ title: 'Create Bluepint',
+ icon: 'git-pull',
+ path: '/blueprints/create'
+ }
+ ]
+ },
+ {
+ key: 'dashboard',
+ title: 'Dashboard',
+ icon: 'dashboard',
+ path: getGrafanaUrl(),
+ target: true
+ }
+ ] as MenuItemType[],
+ []
+ )
+}
diff --git a/config-ui/src/components/Content.jsx b/config-ui/src/layouts/index.ts
similarity index 83%
rename from config-ui/src/components/Content.jsx
rename to config-ui/src/layouts/index.ts
index b9096cb7b..0852d9746 100644
--- a/config-ui/src/components/Content.jsx
+++ b/config-ui/src/layouts/index.ts
@@ -15,11 +15,5 @@
* limitations under the License.
*
*/
-import React, { Fragment } from 'react'
-import '@/styles/common.scss'
-const Content = ({ children }) => {
- return <>{children}</>
-}
-
-export default Content
+export * from './base'
diff --git a/config-ui/src/models/MenuItem.js b/config-ui/src/models/MenuItem.js
deleted file mode 100644
index eb77d2564..000000000
--- a/config-ui/src/models/MenuItem.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/**
- * @typedef {object} MenuItem
- * @property {number?} id
- * @property {boolean?} disabled
- * @property {string?} label
- * @property {string|Object?} route
- * @property {boolean?} active
- * @property {string|Object} icon
- * @property {<Array<string>>?} classNames
- * @property {<Array<MenuItem>>?} children
- * @property {string?} target
- */
-class MenuItem {
- constructor(data = {}) {
- this.id = data?.id || null
- this.disabled = !!data?.disabled
- this.label = data?.label || null
- this.route = data?.route || '#'
- this.active = !!data?.active
- this.icon = data?.icon || null
- this.classNames = Array.isArray(data?.classNames) ? data?.classNames : []
- this.target = data?.target || null
- }
-
- get(property) {
- return this[property]
- }
-
- set(property, value) {
- this[property] = value
- return this.property
- }
-}
-
-export default MenuItem
diff --git a/config-ui/src/pages/blueprints/blueprint-detail.jsx b/config-ui/src/pages/blueprints/blueprint-detail.jsx
index a1e459775..5d77b5368 100644
--- a/config-ui/src/pages/blueprints/blueprint-detail.jsx
+++ b/config-ui/src/pages/blueprints/blueprint-detail.jsx
@@ -50,9 +50,6 @@ import {
StatusBgColors
} from '@/data/Task'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import Content from '@/components/Content'
// import TaskActivity from '@/components/pipelines/TaskActivity'
import CodeInspector from '@/components/pipelines/CodeInspector'
import StageLane from '@/components/pipelines/StageLane'
@@ -65,10 +62,7 @@ import usePipelineManager from '@/hooks/usePipelineManager'
import usePaginator from '@/hooks/usePaginator'
const BlueprintDetail = (props) => {
- const {
- integrations: Integrations,
- ProviderLabels,
- } = useIntegrations()
+ const { integrations: Integrations, ProviderLabels } = useIntegrations()
const { bId } = useParams()
@@ -95,7 +89,7 @@ const BlueprintDetail = (props) => {
getNextRunDate,
activateBlueprint,
deactivateBlueprint,
- fetchBlueprint,
+ fetchBlueprint
} = useBlueprintManager()
const {
@@ -345,9 +339,11 @@ const BlueprintDetail = (props) => {
duration: [TaskStatus.CREATED, TaskStatus.RUNNING].includes(
activePipeline.status
)
- ? dayjs(activePipeline.beganAt || activePipeline.createdAt).toNow(true)
+ ? dayjs(activePipeline.beganAt || activePipeline.createdAt).toNow(
+ true
+ )
: dayjs(activePipeline.beganAt).from(
- activePipeline.finishedAt || activePipeline.updatedAt,
+ activePipeline.finishedAt || activePipeline.updatedAt,
true
),
stage: `Stage ${activePipeline.stage}`,
@@ -375,12 +371,7 @@ const BlueprintDetail = (props) => {
}
}
}
- }, [
- autoRefresh,
- fetchPipeline,
- activePipeline?.id,
- pollTimer
- ])
+ }, [autoRefresh, fetchPipeline, activePipeline?.id, pollTimer])
// useEffect(() => {
// console.log('>> VIEW PIPELINE RUN....', expandRun)
@@ -388,482 +379,458 @@ const BlueprintDetail = (props) => {
return (
<>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <div
- className='blueprint-header'
- style={{
- display: 'flex',
- width: '100%',
- justifyContent: 'space-between',
- marginBottom: '10px'
- }}
- >
- <div className='blueprint-name' style={{}}>
- <h2 style={{ fontWeight: 'bold' }}>{activeBlueprint?.name}</h2>
- </div>
- <div
- className='blueprint-info'
- style={{ display: 'flex', alignItems: 'center' }}
+ <main className='main'>
+ <div
+ className='blueprint-header'
+ style={{
+ display: 'flex',
+ width: '100%',
+ justifyContent: 'space-between',
+ marginBottom: '10px'
+ }}
+ >
+ <div className='blueprint-name' style={{}}>
+ <h2 style={{ fontWeight: 'bold' }}>{activeBlueprint?.name}</h2>
+ </div>
+ <div
+ className='blueprint-info'
+ style={{ display: 'flex', alignItems: 'center' }}
+ >
+ <div className='blueprint-schedule'>
+ <span
+ className='blueprint-schedule-interval'
+ style={{ textTransform: 'capitalize', padding: '0 10px' }}
>
- <div className='blueprint-schedule'>
- <span
- className='blueprint-schedule-interval'
- style={{ textTransform: 'capitalize', padding: '0 10px' }}
- >
- {activeBlueprint?.interval} (at{' '}
- {dayjs(getNextRunDate(activeBlueprint?.cronConfig)).format(
- 'hh:mm A'
- )}
- )
- </span>{' '}
- {' '}
- <span className='blueprint-schedule-nextrun'>
- {activeBlueprint?.isManual ? (
- <strong>Manual Mode</strong>
- ) : (
- <>
- Next Run{' '}
- {dayjs(
- getNextRunDate(activeBlueprint?.cronConfig)
- ).fromNow()}
- </>
- )}
- </span>
+ {activeBlueprint?.interval} (at{' '}
+ {dayjs(getNextRunDate(activeBlueprint?.cronConfig)).format(
+ 'hh:mm A'
+ )}
+ )
+ </span>{' '}
+ {' '}
+ <span className='blueprint-schedule-nextrun'>
+ {activeBlueprint?.isManual ? (
+ <strong>Manual Mode</strong>
+ ) : (
+ <>
+ Next Run{' '}
+ {dayjs(
+ getNextRunDate(activeBlueprint?.cronConfig)
+ ).fromNow()}
+ </>
+ )}
+ </span>
+ </div>
+ <div className='blueprint-actions' style={{ padding: '0 10px' }}>
+ <Button
+ intent={Intent.PRIMARY}
+ small
+ text='Run Now'
+ onClick={runBlueprint}
+ disabled={
+ !activeBlueprint?.enable ||
+ [TaskStatus.CREATED, TaskStatus.RUNNING].includes(
+ currentRun?.status
+ )
+ }
+ />
+ </div>
+ <div className='blueprint-enabled'>
+ <Switch
+ id='blueprint-enable'
+ name='blueprint-enable'
+ checked={activeBlueprint?.enable}
+ label={
+ activeBlueprint?.enable
+ ? 'Blueprint Enabled'
+ : 'Blueprint Disabled'
+ }
+ onChange={() => handleBlueprintActivation(activeBlueprint)}
+ style={{
+ marginBottom: 0,
+ marginTop: 0,
+ color: !activeBlueprint?.enable ? Colors.GRAY3 : 'inherit'
+ }}
+ disabled={currentRun?.status === TaskStatus.RUNNING}
+ />
+ </div>
+ <div style={{ padding: '0 10px' }}>
+ <Button
+ intent={Intent.PRIMARY}
+ icon='trash'
+ small
+ minimal
+ disabled
+ />
+ </div>
+ </div>
+ </div>
+
+ <BlueprintNavigationLinks blueprint={activeBlueprint} />
+
+ <div
+ className='blueprint-run'
+ style={{
+ width: '100%',
+ alignSelf: 'flex-start',
+ minWidth: '750px'
+ }}
+ >
+ <h3>Current Run</h3>
+ <Card
+ className={`current-run status-${currentRun?.status.toLowerCase()}`}
+ elevation={Elevation.TWO}
+ style={{ padding: '12px', marginBottom: '8px' }}
+ >
+ {currentRun && (
+ <div style={{ display: 'flex', justifyContent: 'space-between' }}>
+ <div>
+ <label style={{ color: '#94959F' }}>Status</label>
+ <div style={{ display: 'flex' }}>
+ <span style={{ marginRight: '6px', marginTop: '2px' }}>
+ {currentRun?.icon}
+ </span>
+ <h4
+ className={`status-${currentRun?.status.toLowerCase()}`}
+ style={{ fontSize: '15px', margin: 0, padding: 0 }}
+ >
+ {currentRun?.statusLabel}
+ </h4>
+ </div>
</div>
- <div
- className='blueprint-actions'
- style={{ padding: '0 10px' }}
- >
- <Button
- intent={Intent.PRIMARY}
- small
- text='Run Now'
- onClick={runBlueprint}
- disabled={
- !activeBlueprint?.enable ||
- [TaskStatus.CREATED, TaskStatus.RUNNING].includes(
- currentRun?.status
- )
- }
- />
+ <div>
+ <label style={{ color: '#94959F' }}>Started at</label>
+ <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
+ {currentRun?.startedAt}
+ </h4>
</div>
- <div className='blueprint-enabled'>
- <Switch
- id='blueprint-enable'
- name='blueprint-enable'
- checked={activeBlueprint?.enable}
- label={
- activeBlueprint?.enable
- ? 'Blueprint Enabled'
- : 'Blueprint Disabled'
- }
- onChange={() => handleBlueprintActivation(activeBlueprint)}
- style={{
- marginBottom: 0,
- marginTop: 0,
- color: !activeBlueprint?.enable ? Colors.GRAY3 : 'inherit'
- }}
- disabled={currentRun?.status === TaskStatus.RUNNING}
- />
+ <div>
+ <label style={{ color: '#94959F' }}>Duration</label>
+ <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
+ {currentRun?.duration}
+ </h4>
</div>
- <div style={{ padding: '0 10px' }}>
- <Button
- intent={Intent.PRIMARY}
- icon='trash'
- small
- minimal
- disabled
- />
+ <div>
+ <label style={{ color: '#94959F' }}>Current Stage</label>
+ <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
+ {currentRun?.stage}
+ </h4>
+ </div>
+ <div>
+ <label style={{ color: '#94959F' }}>Tasks Completed</label>
+ <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
+ {currentRun?.tasksFinished} / {currentRun?.tasksTotal}
+ </h4>
+ </div>
+ <div
+ style={{
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center'
+ }}
+ >
+ {currentRun?.status === 'TASK_RUNNING' && (
+ <div style={{ display: 'block' }}>
+ {/* <Button intent={Intent.PRIMARY} outlined text='Cancel' onClick={cancelRun} /> */}
+ <Popover
+ key='popover-help-key-cancel-run'
+ className='trigger-pipeline-cancel'
+ popoverClassName='popover-pipeline-cancel'
+ position={Position.BOTTOM}
+ autoFocus={false}
+ enforceFocus={false}
+ usePortal={true}
+ >
+ <Button
+ // icon='stop'
+ text='Cancel'
+ intent={Intent.PRIMARY}
+ outlined
+ />
+ <>
+ <div
+ style={{
+ fontSize: '12px',
+ padding: '12px',
+ maxWidth: '200px'
+ }}
+ >
+ <p>
+ Are you Sure you want to cancel this{' '}
+ <strong>Pipeline Run</strong>?
+ </p>
+ <div
+ style={{
+ display: 'flex',
+ width: '100%',
+ justifyContent: 'flex-end'
+ }}
+ >
+ <Button
+ text='NO'
+ minimal
+ small
+ className={Classes.POPOVER_DISMISS}
+ style={{
+ marginLeft: 'auto',
+ marginRight: '3px'
+ }}
+ />
+ <Button
+ className={Classes.POPOVER_DISMISS}
+ text='YES'
+ icon='small-tick'
+ intent={Intent.DANGER}
+ small
+ onClick={() => cancelPipeline(currentRun?.id)}
+ />
+ </div>
+ </div>
+ </>
+ </Popover>
+ </div>
+ )}
+ {currentRun?.status === TaskStatus.COMPLETE && (
+ <Button
+ intent={Intent.PRIMARY}
+ onClick={rerunAllFailedTasks}
+ >
+ Run Failed Tasks
+ </Button>
+ )}
</div>
</div>
- </div>
-
- <BlueprintNavigationLinks blueprint={activeBlueprint} />
-
- <div
- className='blueprint-run'
- style={{
- width: '100%',
- alignSelf: 'flex-start',
- minWidth: '750px'
- }}
+ )}
+ {!currentRun && (
+ <>
+ <p style={{ margin: 0 }}>
+ There is no current run for this blueprint.
+ </p>
+ </>
+ )}
+ {currentRun?.error && (
+ <div style={{ marginTop: '10px' }}>
+ <p className='error-msg' style={{ color: '#E34040' }}>
+ {currentRun?.error}
+ </p>
+ </div>
+ )}
+ </Card>
+ {currentRun && (
+ <Card
+ elevation={Elevation.TWO}
+ style={{ padding: '12px', marginBottom: '8px' }}
>
- <h3>Current Run</h3>
- <Card
- className={`current-run status-${currentRun?.status.toLowerCase()}`}
- elevation={Elevation.TWO}
- style={{ padding: '12px', marginBottom: '8px' }}
+ <div
+ className='blueprint-run-activity'
+ style={{ display: 'flex', width: '100%' }}
>
- {currentRun && (
- <div
- style={{ display: 'flex', justifyContent: 'space-between' }}
- >
- <div>
- <label style={{ color: '#94959F' }}>Status</label>
- <div style={{ display: 'flex' }}>
- <span style={{ marginRight: '6px', marginTop: '2px' }}>
- {currentRun?.icon}
- </span>
- <h4
- className={`status-${currentRun?.status.toLowerCase()}`}
- style={{ fontSize: '15px', margin: 0, padding: 0 }}
- >
- {currentRun?.statusLabel}
- </h4>
- </div>
- </div>
- <div>
- <label style={{ color: '#94959F' }}>Started at</label>
- <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
- {currentRun?.startedAt}
- </h4>
- </div>
- <div>
- <label style={{ color: '#94959F' }}>Duration</label>
- <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
- {currentRun?.duration}
- </h4>
- </div>
- <div>
- <label style={{ color: '#94959F' }}>Current Stage</label>
- <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
- {currentRun?.stage}
- </h4>
- </div>
- <div>
- <label style={{ color: '#94959F' }}>
- Tasks Completed
- </label>
- <h4 style={{ fontSize: '15px', margin: 0, padding: 0 }}>
- {currentRun?.tasksFinished} / {currentRun?.tasksTotal}
- </h4>
+ <div
+ className='pipeline-task-activity'
+ style={{
+ flex: 1,
+ padding: Object.keys(currentStages).length === 1 ? '0' : 0,
+ overflow: 'hidden',
+ textOverflow: 'ellipsis'
+ }}
+ >
+ {Object.keys(currentStages).length > 0 && (
+ <div className='pipeline-multistage-activity'>
+ {Object.keys(currentStages).map((sK, sIdx) => (
+ <StageLane
+ key={`stage-lane-key-${sIdx}`}
+ stages={currentStages}
+ sK={sK}
+ sIdx={sIdx}
+ showStageTasks={showCurrentRunTasks}
+ rerunTask={rerunTask}
+ />
+ ))}
</div>
- <div
+ )}
+ </div>
+
+ <Button
+ icon={showCurrentRunTasks ? 'chevron-down' : 'chevron-right'}
+ intent={Intent.NONE}
+ minimal
+ small
+ style={{
+ textAlign: 'center',
+ display: 'block',
+ float: 'right',
+ margin: '0 10px',
+ marginBottom: 'auto'
+ }}
+ onClick={() => setShowCurrentRunTasks((s) => !s)}
+ />
+ </div>
+ </Card>
+ )}
+ </div>
+
+ <div
+ className='blueprint-historical-runs'
+ style={{
+ width: '100%',
+ alignSelf: 'flex-start',
+ minWidth: '750px'
+ }}
+ >
+ <h3>Historical Runs</h3>
+ <Card
+ elevation={Elevation.TWO}
+ style={{ padding: '0', marginBottom: '8px' }}
+ >
+ <table
+ className='bp3-html-table bp3-html-table historical-runs-table'
+ style={{ width: '100%' }}
+ >
+ <thead>
+ <tr>
+ <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
+ Status
+ </th>
+ <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
+ Started at
+ </th>
+ <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
+ Completed at
+ </th>
+ <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
+ Duration
+ </th>
+ <th style={{ width: '100%', whiteSpace: 'nowrap' }} />
+ </tr>
+ </thead>
+ <tbody>
+ {pagedHistoricalRuns.map((run, runIdx) => (
+ <tr key={`historical-run-key-${runIdx}`}>
+ <td
style={{
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center'
+ width: '15%',
+ whiteSpace: 'nowrap',
+ borderBottom: '1px solid #f0f0f0'
}}
>
- {currentRun?.status === 'TASK_RUNNING' && (
- <div style={{ display: 'block' }}>
- {/* <Button intent={Intent.PRIMARY} outlined text='Cancel' onClick={cancelRun} /> */}
- <Popover
- key='popover-help-key-cancel-run'
- className='trigger-pipeline-cancel'
- popoverClassName='popover-pipeline-cancel'
- position={Position.BOTTOM}
- autoFocus={false}
- enforceFocus={false}
- usePortal={true}
- >
- <Button
- // icon='stop'
- text='Cancel'
- intent={Intent.PRIMARY}
- outlined
- />
- <>
- <div
- style={{
- fontSize: '12px',
- padding: '12px',
- maxWidth: '200px'
- }}
- >
- <p>
- Are you Sure you want to cancel this{' '}
- <strong>Pipeline Run</strong>?
- </p>
- <div
- style={{
- display: 'flex',
- width: '100%',
- justifyContent: 'flex-end'
- }}
- >
- <Button
- text='NO'
- minimal
- small
- className={Classes.POPOVER_DISMISS}
- style={{
- marginLeft: 'auto',
- marginRight: '3px'
- }}
- />
- <Button
- className={Classes.POPOVER_DISMISS}
- text='YES'
- icon='small-tick'
- intent={Intent.DANGER}
- small
- onClick={() =>
- cancelPipeline(currentRun?.id)
- }
- />
- </div>
- </div>
- </>
- </Popover>
- </div>
- )}
- {currentRun?.status === TaskStatus.COMPLETE && (
- <Button
- intent={Intent.PRIMARY}
- onClick={rerunAllFailedTasks}
- >
- Run Failed Tasks
- </Button>
- )}
- </div>
- </div>
- )}
- {!currentRun && (
- <>
- <p style={{ margin: 0 }}>
- There is no current run for this blueprint.
- </p>
- </>
- )}
- {currentRun?.error && (
- <div style={{ marginTop: '10px' }}>
- <p className='error-msg' style={{ color: '#E34040' }}>
- {currentRun?.error}
- </p>
- </div>
- )}
- </Card>
- {currentRun && (
- <Card
- elevation={Elevation.TWO}
- style={{ padding: '12px', marginBottom: '8px' }}
- >
- <div
- className='blueprint-run-activity'
- style={{ display: 'flex', width: '100%' }}
- >
- <div
- className='pipeline-task-activity'
+ <span
+ style={{
+ display: 'inline-block',
+ float: 'left',
+ marginRight: '5px'
+ }}
+ >
+ {run.statusIcon}
+ </span>{' '}
+ {run.statusLabel}
+ </td>
+ <td
style={{
- flex: 1,
- padding:
- Object.keys(currentStages).length === 1 ? '0' : 0,
- overflow: 'hidden',
- textOverflow: 'ellipsis'
+ width: '25%',
+ whiteSpace: 'nowrap',
+ borderBottom: '1px solid #f0f0f0'
}}
>
- {Object.keys(currentStages).length > 0 && (
- <div className='pipeline-multistage-activity'>
- {Object.keys(currentStages).map((sK, sIdx) => (
- <StageLane
- key={`stage-lane-key-${sIdx}`}
- stages={currentStages}
- sK={sK}
- sIdx={sIdx}
- showStageTasks={showCurrentRunTasks}
- rerunTask={rerunTask}
- />
- ))}
- </div>
- )}
- </div>
-
- <Button
- icon={
- showCurrentRunTasks ? 'chevron-down' : 'chevron-right'
- }
- intent={Intent.NONE}
- minimal
- small
+ {run.startedAt}
+ </td>
+ <td
style={{
- textAlign: 'center',
- display: 'block',
- float: 'right',
- margin: '0 10px',
- marginBottom: 'auto'
+ width: '25%',
+ whiteSpace: 'nowrap',
+ borderBottom: '1px solid #f0f0f0'
}}
- onClick={() => setShowCurrentRunTasks((s) => !s)}
- />
- </div>
- </Card>
- )}
- </div>
-
- <div
- className='blueprint-historical-runs'
- style={{
- width: '100%',
- alignSelf: 'flex-start',
- minWidth: '750px'
- }}
- >
- <h3>Historical Runs</h3>
- <Card
- elevation={Elevation.TWO}
- style={{ padding: '0', marginBottom: '8px' }}
- >
- <table
- className='bp3-html-table bp3-html-table historical-runs-table'
- style={{ width: '100%' }}
- >
- <thead>
- <tr>
- <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
- Status
- </th>
- <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
- Started at
- </th>
- <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
- Completed at
- </th>
- <th style={{ minWidth: '100px', whiteSpace: 'nowrap' }}>
- Duration
- </th>
- <th style={{ width: '100%', whiteSpace: 'nowrap' }} />
- </tr>
- </thead>
- <tbody>
- {pagedHistoricalRuns.map((run, runIdx) => (
- <tr key={`historical-run-key-${runIdx}`}>
- <td
- style={{
- width: '15%',
- whiteSpace: 'nowrap',
- borderBottom: '1px solid #f0f0f0'
- }}
- >
- <span
- style={{
- display: 'inline-block',
- float: 'left',
- marginRight: '5px'
- }}
- >
- {run.statusIcon}
- </span>{' '}
- {run.statusLabel}
- </td>
- <td
- style={{
- width: '25%',
- whiteSpace: 'nowrap',
- borderBottom: '1px solid #f0f0f0'
- }}
- >
- {run.startedAt}
- </td>
- <td
- style={{
- width: '25%',
- whiteSpace: 'nowrap',
- borderBottom: '1px solid #f0f0f0'
- }}
- >
- {run.completedAt}
- </td>
- <td
- style={{
- width: '15%',
- whiteSpace: 'nowrap',
- borderBottom: '1px solid #f0f0f0'
- }}
- >
- {run.duration}
- </td>
- <td
- style={{
- textAlign: 'right',
- borderBottom: '1px solid #f0f0f0',
- whiteSpace: 'nowrap'
- }}
- >
- <Tooltip intent={Intent.PRIMARY} content='View JSON'>
- <Button
- intent={Intent.PRIMARY}
- minimal
- small
- icon='code'
- onClick={() =>
- inspectRun(
- blueprintPipelines.find(
- (p) => p.id === run.id
- )
- )
- }
- />
- </Tooltip>
- <Tooltip
- intent={Intent.PRIMARY}
- content='Download Full Log'
- >
- <Button
- intent={Intent.NONE}
- loading={isDownloading}
- minimal
- small
- icon='document'
- style={{ marginLeft: '10px' }}
- onClick={() =>
- downloadPipelineLog(
- blueprintPipelines.find(
- (p) => p.id === run.id
- )
- )
- }
- />
- </Tooltip>
- <Tooltip
- intent={Intent.PRIMARY}
- content='Show Run Activity'
- >
- <Button
- intent={Intent.PRIMARY}
- minimal
- small
- icon={
- expandRun?.id === run.id
- ? 'chevron-down'
- : 'chevron-right'
- }
- style={{ marginLeft: '10px' }}
- onClick={() =>
- viewPipelineRun(
- blueprintPipelines.find(
- (p) => p.id === run.id
- )
- )
- }
- />
- </Tooltip>
- </td>
- </tr>
- ))}
- {historicalRuns.length === 0 && (
- <tr>
- <td colSpan={5}>
- There are no historical runs associated with this
- blueprint.
- </td>
- </tr>
- )}
- </tbody>
- </table>
- </Card>
- </div>
- {historicalRuns.length > 0 && (
- <div style={{ alignSelf: 'flex-end', padding: '10px' }}>
- {renderPagnationControls()}
- </div>
- )}
- </main>
- </Content>
- </div>
+ >
+ {run.completedAt}
+ </td>
+ <td
+ style={{
+ width: '15%',
+ whiteSpace: 'nowrap',
+ borderBottom: '1px solid #f0f0f0'
+ }}
+ >
+ {run.duration}
+ </td>
+ <td
+ style={{
+ textAlign: 'right',
+ borderBottom: '1px solid #f0f0f0',
+ whiteSpace: 'nowrap'
+ }}
+ >
+ <Tooltip intent={Intent.PRIMARY} content='View JSON'>
+ <Button
+ intent={Intent.PRIMARY}
+ minimal
+ small
+ icon='code'
+ onClick={() =>
+ inspectRun(
+ blueprintPipelines.find((p) => p.id === run.id)
+ )
+ }
+ />
+ </Tooltip>
+ <Tooltip
+ intent={Intent.PRIMARY}
+ content='Download Full Log'
+ >
+ <Button
+ intent={Intent.NONE}
+ loading={isDownloading}
+ minimal
+ small
+ icon='document'
+ style={{ marginLeft: '10px' }}
+ onClick={() =>
+ downloadPipelineLog(
+ blueprintPipelines.find((p) => p.id === run.id)
+ )
+ }
+ />
+ </Tooltip>
+ <Tooltip
+ intent={Intent.PRIMARY}
+ content='Show Run Activity'
+ >
+ <Button
+ intent={Intent.PRIMARY}
+ minimal
+ small
+ icon={
+ expandRun?.id === run.id
+ ? 'chevron-down'
+ : 'chevron-right'
+ }
+ style={{ marginLeft: '10px' }}
+ onClick={() =>
+ viewPipelineRun(
+ blueprintPipelines.find((p) => p.id === run.id)
+ )
+ }
+ />
+ </Tooltip>
+ </td>
+ </tr>
+ ))}
+ {historicalRuns.length === 0 && (
+ <tr>
+ <td colSpan={5}>
+ There are no historical runs associated with this
+ blueprint.
+ </td>
+ </tr>
+ )}
+ </tbody>
+ </table>
+ </Card>
+ </div>
+ {historicalRuns.length > 0 && (
+ <div style={{ alignSelf: 'flex-end', padding: '10px' }}>
+ {renderPagnationControls()}
+ </div>
+ )}
+ </main>
<CodeInspector
isOpen={showInspector}
activePipeline={inspectedPipeline}
diff --git a/config-ui/src/pages/blueprints/blueprint-settings.jsx b/config-ui/src/pages/blueprints/blueprint-settings.jsx
index 0f9e3e728..75ebd2ef0 100644
--- a/config-ui/src/pages/blueprints/blueprint-settings.jsx
+++ b/config-ui/src/pages/blueprints/blueprint-settings.jsx
@@ -41,9 +41,6 @@ import { BlueprintMode, NullBlueprint } from '@/data/NullBlueprint'
import { NullPipelineRun } from '@/data/NullPipelineRun'
import { TaskStatus } from '@/data/Task'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import Content from '@/components/Content'
import { ToastNotification } from '@/components/Toast'
import BlueprintNameCard from '@/components/blueprints/BlueprintNameCard'
import DataSync from '@/components/blueprints/create-workflow/DataSync'
@@ -851,301 +848,278 @@ const BlueprintSettings = (props) => {
return (
<>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- {activeBlueprint?.id !== null && blueprintErrors.length === 0 && (
- <div
- className='blueprint-header'
+ <main className='main'>
+ {activeBlueprint?.id !== null && blueprintErrors.length === 0 && (
+ <div
+ className='blueprint-header'
+ style={{
+ display: 'flex',
+ width: '100%',
+ justifyContent: 'space-between',
+ marginBottom: '10px',
+ whiteSpace: 'nowrap'
+ }}
+ >
+ <div className='blueprint-name' style={{}}>
+ <h2
style={{
+ fontWeight: 'bold',
display: 'flex',
- width: '100%',
- justifyContent: 'space-between',
- marginBottom: '10px',
- whiteSpace: 'nowrap'
+ alignItems: 'center',
+ color: !activeBlueprint?.enable ? Colors.GRAY1 : 'inherit'
}}
>
- <div className='blueprint-name' style={{}}>
- <h2
+ {activeBlueprint?.name}
+ <Tag
+ minimal
+ intent={
+ activeBlueprint.mode === BlueprintMode.ADVANCED
+ ? Intent.DANGER
+ : Intent.PRIMARY
+ }
+ style={{ marginLeft: '10px' }}
+ >
+ {activeBlueprint?.mode?.toString().toUpperCase()}
+ </Tag>
+ </h2>
+ </div>
+ <div
+ className='blueprint-info'
+ style={{ display: 'flex', alignItems: 'center' }}
+ >
+ <div className='blueprint-schedule'>
+ {activeBlueprint?.isManual ? (
+ <strong>Manual Mode</strong>
+ ) : (
+ <span
+ className='blueprint-schedule-interval'
style={{
- fontWeight: 'bold',
- display: 'flex',
- alignItems: 'center',
- color: !activeBlueprint?.enable ? Colors.GRAY1 : 'inherit'
+ textTransform: 'capitalize',
+ padding: '0 10px'
}}
>
- {activeBlueprint?.name}
- <Tag
- minimal
- intent={
- activeBlueprint.mode === BlueprintMode.ADVANCED
- ? Intent.DANGER
- : Intent.PRIMARY
- }
- style={{ marginLeft: '10px' }}
- >
- {activeBlueprint?.mode?.toString().toUpperCase()}
- </Tag>
- </h2>
+ {activeBlueprint?.interval} (at{' '}
+ {dayjs(getNextRunDate(activeBlueprint?.cronConfig)).format(
+ `hh:mm A ${
+ activeBlueprint?.interval !== 'Hourly'
+ ? ' MM/DD/YYYY'
+ : ''
+ }`
+ )}
+ )
+ </span>
+ )}{' '}
+ <span className='blueprint-schedule-nextrun'>
+ {!activeBlueprint?.isManual && (
+ <>
+ Next Run{' '}
+ {dayjs(
+ getNextRunDate(activeBlueprint?.cronConfig)
+ ).fromNow()}
+ </>
+ )}
+ </span>
+ </div>
+ <div className='blueprint-actions' style={{ padding: '0 10px' }}>
+ {/* <Button
+ intent={Intent.PRIMARY}
+ small
+ text='Run Now'
+ onClick={runBlueprint}
+ disabled={!activeBlueprint?.enable || currentRun?.status === TaskStatus.RUNNING}
+ /> */}
+ </div>
+ <div className='blueprint-enabled'>
+ <Switch
+ id='blueprint-enable'
+ name='blueprint-enable'
+ checked={activeBlueprint?.enable}
+ label={
+ activeBlueprint?.enable
+ ? 'Blueprint Enabled'
+ : 'Blueprint Disabled'
+ }
+ onChange={() => handleBlueprintActivation(activeBlueprint)}
+ style={{
+ marginBottom: 0,
+ marginTop: 0,
+ color: !activeBlueprint?.enable ? Colors.GRAY3 : 'inherit'
+ }}
+ disabled={currentRun?.status === TaskStatus.RUNNING}
+ />
+ </div>
+ <div style={{ padding: '0 10px' }}>
+ <Button
+ intent={Intent.PRIMARY}
+ icon='trash'
+ small
+ minimal
+ disabled
+ />
+ </div>
+ </div>
+ </div>
+ )}
+
+ {blueprintErrors?.length > 0 && (
+ <div className='bp3-non-ideal-state blueprint-non-ideal-state'>
+ <div className='bp3-non-ideal-state-visual'>
+ <Icon icon='warning-sign' size={32} color={Colors.RED5} />
+ </div>
+ <h4 className='bp3-heading'>Invalid Blueprint</h4>
+ <div>{blueprintErrors[0]}</div>
+ <button
+ className='bp3-button bp3-intent-primary'
+ onClick={viewBlueprints}
+ >
+ Continue
+ </button>
+ </div>
+ )}
+
+ {activeBlueprint?.id !== null && blueprintErrors.length === 0 && (
+ <>
+ <BlueprintNavigationLinks blueprint={activeBlueprint} />
+
+ <div
+ className='blueprint-main-settings'
+ style={{
+ display: 'flex',
+ alignSelf: 'flex-start',
+ color: !activeBlueprint?.enable ? Colors.GRAY2 : 'inherit'
+ }}
+ >
+ <div className='configure-settings-name'>
+ <h3>Name</h3>
+ <div style={{ display: 'flex', alignItems: 'center' }}>
+ <div className='blueprint-name'>{activeBlueprint?.name}</div>
+ <Button
+ icon='annotation'
+ intent={Intent.PRIMARY}
+ size={12}
+ small
+ minimal
+ onClick={() => modifySetting('name')}
+ />
</div>
- <div
- className='blueprint-info'
- style={{ display: 'flex', alignItems: 'center' }}
- >
- <div className='blueprint-schedule'>
+ </div>
+ <div
+ className='configure-settings-frequency'
+ style={{ marginLeft: '40px' }}
+ >
+ <h3>Sync Frequency</h3>
+ <div style={{ display: 'flex', alignItems: 'center' }}>
+ <div className='blueprint-frequency'>
{activeBlueprint?.isManual ? (
- <strong>Manual Mode</strong>
+ 'Manual'
) : (
- <span
- className='blueprint-schedule-interval'
- style={{
- textTransform: 'capitalize',
- padding: '0 10px'
- }}
- >
+ <span>
{activeBlueprint?.interval} (at{' '}
{dayjs(
getNextRunDate(activeBlueprint?.cronConfig)
- ).format(
- `hh:mm A ${
- activeBlueprint?.interval !== 'Hourly'
- ? ' MM/DD/YYYY'
- : ''
- }`
- )}
+ ).format('hh:mm A')}
)
</span>
- )}{' '}
- <span className='blueprint-schedule-nextrun'>
- {!activeBlueprint?.isManual && (
- <>
- Next Run{' '}
- {dayjs(
- getNextRunDate(activeBlueprint?.cronConfig)
- ).fromNow()}
- </>
- )}
- </span>
- </div>
- <div
- className='blueprint-actions'
- style={{ padding: '0 10px' }}
- >
- {/* <Button
- intent={Intent.PRIMARY}
- small
- text='Run Now'
- onClick={runBlueprint}
- disabled={!activeBlueprint?.enable || currentRun?.status === TaskStatus.RUNNING}
- /> */}
- </div>
- <div className='blueprint-enabled'>
- <Switch
- id='blueprint-enable'
- name='blueprint-enable'
- checked={activeBlueprint?.enable}
- label={
- activeBlueprint?.enable
- ? 'Blueprint Enabled'
- : 'Blueprint Disabled'
- }
- onChange={() =>
- handleBlueprintActivation(activeBlueprint)
- }
- style={{
- marginBottom: 0,
- marginTop: 0,
- color: !activeBlueprint?.enable
- ? Colors.GRAY3
- : 'inherit'
- }}
- disabled={currentRun?.status === TaskStatus.RUNNING}
- />
+ )}
</div>
- <div style={{ padding: '0 10px' }}>
- <Button
- intent={Intent.PRIMARY}
- icon='trash'
- small
- minimal
- disabled
- />
- </div>
- </div>
- </div>
- )}
-
- {blueprintErrors?.length > 0 && (
- <div className='bp3-non-ideal-state blueprint-non-ideal-state'>
- <div className='bp3-non-ideal-state-visual'>
- <Icon icon='warning-sign' size={32} color={Colors.RED5} />
+ <Button
+ icon='annotation'
+ intent={Intent.PRIMARY}
+ size={12}
+ small
+ minimal
+ onClick={() => modifySetting('cronConfig')}
+ />
</div>
- <h4 className='bp3-heading'>Invalid Blueprint</h4>
- <div>{blueprintErrors[0]}</div>
- <button
- className='bp3-button bp3-intent-primary'
- onClick={viewBlueprints}
- >
- Continue
- </button>
</div>
- )}
-
- {activeBlueprint?.id !== null && blueprintErrors.length === 0 && (
- <>
- <BlueprintNavigationLinks blueprint={activeBlueprint} />
+ </div>
+ {activeBlueprint?.id &&
+ activeBlueprint?.mode === BlueprintMode.NORMAL && (
<div
- className='blueprint-main-settings'
+ className='data-scopes-grid'
style={{
- display: 'flex',
- alignSelf: 'flex-start',
- color: !activeBlueprint?.enable ? Colors.GRAY2 : 'inherit'
+ width: '100%',
+ marginTop: '40px',
+ alignSelf: 'flex-start'
}}
>
- <div className='configure-settings-name'>
- <h3>Name</h3>
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <div className='blueprint-name'>
- {activeBlueprint?.name}
- </div>
- <Button
- icon='annotation'
- intent={Intent.PRIMARY}
- size={12}
- small
- minimal
- onClick={() => modifySetting('name')}
- />
- </div>
- </div>
- <div
- className='configure-settings-frequency'
- style={{ marginLeft: '40px' }}
- >
- <h3>Sync Frequency</h3>
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <div className='blueprint-frequency'>
- {activeBlueprint?.isManual ? (
- 'Manual'
- ) : (
- <span>
- {activeBlueprint?.interval} (at{' '}
- {dayjs(
- getNextRunDate(activeBlueprint?.cronConfig)
- ).format('hh:mm A')}
- )
- </span>
- )}
- </div>
- <Button
- icon='annotation'
- intent={Intent.PRIMARY}
- size={12}
- small
- minimal
- onClick={() => modifySetting('cronConfig')}
- />
- </div>
- </div>
- </div>
-
- {activeBlueprint?.id &&
- activeBlueprint?.mode === BlueprintMode.NORMAL && (
- <div
- className='data-scopes-grid'
- style={{
- width: '100%',
- marginTop: '40px',
- alignSelf: 'flex-start'
- }}
- >
- <h2
- style={{
- fontWeight: 'bold',
- color: !activeBlueprint?.enable
- ? Colors.GRAY1
- : 'inherit'
- }}
- >
- Data Scope and Transformation
- </h2>
- <DataScopesGrid
- providers={Providers}
- connections={connections}
- blueprint={activeBlueprint}
- onModify={modifyConnection}
- mode={activeBlueprint?.mode}
- loading={
- isFetchingBlueprint ||
- isFetchingJIRA ||
- isFetchingJenkins
- }
- />
- </div>
- )}
-
- {activeBlueprint?.id && mode === BlueprintMode.ADVANCED && (
- <div
- className='data-advanced'
+ <h2
style={{
- width: '100%',
- maxWidth: '100%',
- marginTop: '40px',
- alignSelf: 'flex-start'
+ fontWeight: 'bold',
+ color: !activeBlueprint?.enable ? Colors.GRAY1 : 'inherit'
}}
>
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <h2 style={{ fontWeight: 'bold' }}>
- Data Scope and Transformation
- </h2>
- <div>
- <Button
- icon='annotation'
- text='Edit JSON'
- intent={Intent.PRIMARY}
- small
- minimal
- onClick={() => modifySetting('plan')}
- style={{ fontSize: '12px' }}
- />
- </div>
- </div>
- <DataScopesGrid
- providers={Providers}
- connections={connections}
- blueprint={activeBlueprint}
- onModify={() => modifySetting('plan')}
- mode={activeBlueprint?.mode}
- classNames={['advanced-mode-grid']}
- loading={
- isFetchingBlueprint ||
- isFetchingJIRA ||
- isFetchingJenkins
- }
+ Data Scope and Transformation
+ </h2>
+ <DataScopesGrid
+ providers={Providers}
+ connections={connections}
+ blueprint={activeBlueprint}
+ onModify={modifyConnection}
+ mode={activeBlueprint?.mode}
+ loading={
+ isFetchingBlueprint || isFetchingJIRA || isFetchingJenkins
+ }
+ />
+ </div>
+ )}
+
+ {activeBlueprint?.id && mode === BlueprintMode.ADVANCED && (
+ <div
+ className='data-advanced'
+ style={{
+ width: '100%',
+ maxWidth: '100%',
+ marginTop: '40px',
+ alignSelf: 'flex-start'
+ }}
+ >
+ <div style={{ display: 'flex', alignItems: 'center' }}>
+ <h2 style={{ fontWeight: 'bold' }}>
+ Data Scope and Transformation
+ </h2>
+ <div>
+ <Button
+ icon='annotation'
+ text='Edit JSON'
+ intent={Intent.PRIMARY}
+ small
+ minimal
+ onClick={() => modifySetting('plan')}
+ style={{ fontSize: '12px' }}
/>
</div>
- )}
+ </div>
+ <DataScopesGrid
+ providers={Providers}
+ connections={connections}
+ blueprint={activeBlueprint}
+ onModify={() => modifySetting('plan')}
+ mode={activeBlueprint?.mode}
+ classNames={['advanced-mode-grid']}
+ loading={
+ isFetchingBlueprint || isFetchingJIRA || isFetchingJenkins
+ }
+ />
+ </div>
+ )}
- {ENVIRONMENT !== 'production' && (
- <Button
- // loading={isLoading}
- intent={Intent.PRIMARY}
- icon='code'
- text='Inspect'
- onClick={() => setShowBlueprintInspector(true)}
- style={{ margin: '12px auto' }}
- minimal
- small
- />
- )}
- </>
+ {ENVIRONMENT !== 'production' && (
+ <Button
+ // loading={isLoading}
+ intent={Intent.PRIMARY}
+ icon='code'
+ text='Inspect'
+ onClick={() => setShowBlueprintInspector(true)}
+ style={{ margin: '12px auto' }}
+ minimal
+ small
+ />
)}
- </main>
- </Content>
- </div>
+ </>
+ )}
+ </main>
<BlueprintDialog
isOpen={blueprintDialogIsOpen}
diff --git a/config-ui/src/pages/blueprints/create-blueprint.jsx b/config-ui/src/pages/blueprints/create-blueprint.jsx
index adadea672..f8cdf75fd 100644
--- a/config-ui/src/pages/blueprints/create-blueprint.jsx
+++ b/config-ui/src/pages/blueprints/create-blueprint.jsx
@@ -26,9 +26,6 @@ import {
// import { integrationsData } from '@/data/integrations'
import { Intent } from '@blueprintjs/core'
// import { Providers } from '@/data/Providers'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import Content from '@/components/Content'
import { ToastNotification } from '@/components/Toast'
import { BlueprintMode } from '@/data/NullBlueprint'
@@ -872,206 +869,193 @@ const CreateBlueprint = (props) => {
return (
<>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <WorkflowStepsBar activeStep={activeStep} steps={blueprintSteps} />
-
- <div
- className={`workflow-content workflow-step-id-${activeStep?.id}`}
- >
- {advancedMode ? (
- <>
- {activeStep?.id === 1 && (
- <AdvancedJSON
- activeStep={activeStep}
- advancedMode={advancedMode}
- runTasksAdvanced={runTasksAdvanced}
- blueprintConnections={blueprintConnections}
- connectionsList={connectionsList}
- name={name}
- setBlueprintName={setBlueprintName}
- // setBlueprintConnections={setBlueprintConnections}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- // addConnection={addConnection}
- // manageConnection={manageConnection}
- onAdvancedMode={handleAdvancedMode}
- // @todo add multistage checker method
- isMultiStagePipeline={() => {}}
- rawConfiguration={rawConfiguration}
- setRawConfiguration={setRawConfiguration}
- isSaving={isSaving}
- isValidConfiguration={isValidConfiguration}
- validationAdvancedError={validationAdvancedError}
- validationErrors={validationErrors}
- />
- )}
-
- {activeStep?.id === 2 && (
- <DataSync
- skipOnFail={skipOnFail}
- setSkipOnFail={setSkipOnFail}
- activeStep={activeStep}
- advancedMode={advancedMode}
- cronConfig={cronConfig}
- customCronConfig={customCronConfig}
- createCron={createCron}
- setCronConfig={setCronConfig}
- getCronPreset={getCronPreset}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- setCustomCronConfig={setCustomCronConfig}
- getCronPresetByConfig={getCronPresetByConfig}
- />
- )}
- </>
- ) : (
- <>
- {activeStep?.id === 1 && (
- <DataConnections
- activeStep={activeStep}
- advancedMode={advancedMode}
- blueprintConnections={dataConnections}
- // blueprintConnections={blueprintConnections}
- // eslint-disable-next-line max-len
- // blueprintConnections={[...blueprintConnections.map((c, cIdx) => ({...c, statusResponse: onlineStatus[cIdx], status: onlineStatus[cIdx]?.status }))]}
- onlineStatus={onlineStatus}
- connectionsList={connectionsList}
- name={name}
- setBlueprintName={setBlueprintName}
- setBlueprintConnections={setBlueprintConnections}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- addConnection={addConnection}
- manageConnection={manageConnection}
- onAdvancedMode={handleAdvancedMode}
- isTesting={isTestingConnection}
- />
- )}
-
- {activeStep?.id === 2 && (
- <DataScopes
- provider={provider}
- activeStep={activeStep}
- advancedMode={advancedMode}
- activeConnectionTab={activeConnectionTab}
- blueprintConnections={blueprintConnections}
- jiraBoards={jiraBoards}
- fetchJenkinsJobs={fetchJenkinsJobs}
- isFetchingJenkins={isFetchingJenkins}
- jenkinsJobs={jenkinsJobs}
- dataDomainsGroup={dataDomainsGroup}
- scopeEntitiesGroup={scopeEntitiesGroup}
- configuredConnection={configuredConnection}
- handleConnectionTabChange={handleConnectionTabChange}
- setDataDomainsGroup={setDataDomainsGroup}
- setScopeEntitiesGroup={setScopeEntitiesGroup}
- setBoardSearch={setBoardSearch}
- prevStep={prevStep}
- isSaving={isSaving}
- isRunning={isRunning}
- validationErrors={[
- ...validationErrors,
- ...blueprintValidationErrors
- ]}
- isFetching={
- isFetchingJIRA ||
- isFetchingJenkins ||
- isFetchingConnection
- }
- />
- )}
-
- {activeStep?.id === 3 && (
- <DataTransformations
- provider={provider}
- activeStep={activeStep}
- advancedMode={advancedMode}
- activeConnectionTab={activeConnectionTab}
- blueprintConnections={blueprintConnections}
- dataDomainsGroup={dataDomainsGroup}
- scopeEntitiesGroup={scopeEntitiesGroup}
- issueTypes={jiraApiIssueTypes}
- fields={jiraApiFields}
- configuredConnection={configuredConnection}
- configuredScopeEntity={configuredScopeEntity}
- handleConnectionTabChange={handleConnectionTabChange}
- prevStep={prevStep}
- setConfiguredScopeEntity={setConfiguredScopeEntity}
- activeTransformation={activeTransformation}
- hasConfiguredEntityTransformationChanged={
- hasConfiguredEntityTransformationChanged
- }
- changeConfiguredEntityTransformation={
- changeConfiguredEntityTransformation
- }
- onSave={handleTransformationSave}
- onCancel={handleTransformationCancel}
- onClear={handleTransformationClear}
- isSaving={isSaving}
- isSavingConnection={isSavingConnection}
- isRunning={isRunning}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- jiraProxyError={jiraProxyError}
- isFetchingJIRA={isFetchingJIRA}
- />
- )}
-
- {activeStep?.id === 4 && (
- <DataSync
- skipOnFail={skipOnFail}
- setSkipOnFail={setSkipOnFail}
- activeStep={activeStep}
- advancedMode={advancedMode}
- cronConfig={cronConfig}
- customCronConfig={customCronConfig}
- createCron={createCron}
- setCronConfig={setCronConfig}
- getCronPreset={getCronPreset}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- setCustomCronConfig={setCustomCronConfig}
- getCronPresetByConfig={getCronPresetByConfig}
- />
- )}
- </>
+ <main className='main'>
+ <WorkflowStepsBar activeStep={activeStep} steps={blueprintSteps} />
+
+ <div className={`workflow-content workflow-step-id-${activeStep?.id}`}>
+ {advancedMode ? (
+ <>
+ {activeStep?.id === 1 && (
+ <AdvancedJSON
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ runTasksAdvanced={runTasksAdvanced}
+ blueprintConnections={blueprintConnections}
+ connectionsList={connectionsList}
+ name={name}
+ setBlueprintName={setBlueprintName}
+ // setBlueprintConnections={setBlueprintConnections}
+ fieldHasError={fieldHasError}
+ getFieldError={getFieldError}
+ // addConnection={addConnection}
+ // manageConnection={manageConnection}
+ onAdvancedMode={handleAdvancedMode}
+ // @todo add multistage checker method
+ isMultiStagePipeline={() => {}}
+ rawConfiguration={rawConfiguration}
+ setRawConfiguration={setRawConfiguration}
+ isSaving={isSaving}
+ isValidConfiguration={isValidConfiguration}
+ validationAdvancedError={validationAdvancedError}
+ validationErrors={validationErrors}
+ />
)}
- </div>
-
- <WorkflowActions
- activeStep={activeStep}
- blueprintSteps={blueprintSteps}
- advancedMode={advancedMode}
- setShowBlueprintInspector={setShowBlueprintInspector}
- validationErrors={[
- ...validationErrors,
- ...blueprintValidationErrors
- ]}
- onNext={nextStep}
- onPrev={prevStep}
- onSave={handleBlueprintSave}
- onSaveAndRun={handleBlueprintSaveAndRun}
- isLoading={
- isSaving ||
- isFetchingJIRA ||
- isFetchingJenkins ||
- isFetchingConnection ||
- isTestingConnection
- }
- isValid={
- advancedMode
- ? isValidBlueprint && isValidPipeline
- : isValidBlueprint
- }
- canGoNext={canAdvanceNext}
- />
- </main>
- </Content>
- </div>
+
+ {activeStep?.id === 2 && (
+ <DataSync
+ skipOnFail={skipOnFail}
+ setSkipOnFail={setSkipOnFail}
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ cronConfig={cronConfig}
+ customCronConfig={customCronConfig}
+ createCron={createCron}
+ setCronConfig={setCronConfig}
+ getCronPreset={getCronPreset}
+ fieldHasError={fieldHasError}
+ getFieldError={getFieldError}
+ setCustomCronConfig={setCustomCronConfig}
+ getCronPresetByConfig={getCronPresetByConfig}
+ />
+ )}
+ </>
+ ) : (
+ <>
+ {activeStep?.id === 1 && (
+ <DataConnections
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ blueprintConnections={dataConnections}
+ // blueprintConnections={blueprintConnections}
+ // eslint-disable-next-line max-len
+ // blueprintConnections={[...blueprintConnections.map((c, cIdx) => ({...c, statusResponse: onlineStatus[cIdx], status: onlineStatus[cIdx]?.status }))]}
+ onlineStatus={onlineStatus}
+ connectionsList={connectionsList}
+ name={name}
+ setBlueprintName={setBlueprintName}
+ setBlueprintConnections={setBlueprintConnections}
+ fieldHasError={fieldHasError}
+ getFieldError={getFieldError}
+ addConnection={addConnection}
+ manageConnection={manageConnection}
+ onAdvancedMode={handleAdvancedMode}
+ isTesting={isTestingConnection}
+ />
+ )}
+
+ {activeStep?.id === 2 && (
+ <DataScopes
+ provider={provider}
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ activeConnectionTab={activeConnectionTab}
+ blueprintConnections={blueprintConnections}
+ jiraBoards={jiraBoards}
+ fetchJenkinsJobs={fetchJenkinsJobs}
+ isFetchingJenkins={isFetchingJenkins}
+ jenkinsJobs={jenkinsJobs}
+ dataDomainsGroup={dataDomainsGroup}
+ scopeEntitiesGroup={scopeEntitiesGroup}
+ configuredConnection={configuredConnection}
+ handleConnectionTabChange={handleConnectionTabChange}
+ setDataDomainsGroup={setDataDomainsGroup}
+ setScopeEntitiesGroup={setScopeEntitiesGroup}
+ setBoardSearch={setBoardSearch}
+ prevStep={prevStep}
+ isSaving={isSaving}
+ isRunning={isRunning}
+ validationErrors={[
+ ...validationErrors,
+ ...blueprintValidationErrors
+ ]}
+ isFetching={
+ isFetchingJIRA || isFetchingJenkins || isFetchingConnection
+ }
+ />
+ )}
+
+ {activeStep?.id === 3 && (
+ <DataTransformations
+ provider={provider}
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ activeConnectionTab={activeConnectionTab}
+ blueprintConnections={blueprintConnections}
+ dataDomainsGroup={dataDomainsGroup}
+ scopeEntitiesGroup={scopeEntitiesGroup}
+ issueTypes={jiraApiIssueTypes}
+ fields={jiraApiFields}
+ configuredConnection={configuredConnection}
+ configuredScopeEntity={configuredScopeEntity}
+ handleConnectionTabChange={handleConnectionTabChange}
+ prevStep={prevStep}
+ setConfiguredScopeEntity={setConfiguredScopeEntity}
+ activeTransformation={activeTransformation}
+ hasConfiguredEntityTransformationChanged={
+ hasConfiguredEntityTransformationChanged
+ }
+ changeConfiguredEntityTransformation={
+ changeConfiguredEntityTransformation
+ }
+ onSave={handleTransformationSave}
+ onCancel={handleTransformationCancel}
+ onClear={handleTransformationClear}
+ isSaving={isSaving}
+ isSavingConnection={isSavingConnection}
+ isRunning={isRunning}
+ fieldHasError={fieldHasError}
+ getFieldError={getFieldError}
+ jiraProxyError={jiraProxyError}
+ isFetchingJIRA={isFetchingJIRA}
+ />
+ )}
+
+ {activeStep?.id === 4 && (
+ <DataSync
+ skipOnFail={skipOnFail}
+ setSkipOnFail={setSkipOnFail}
+ activeStep={activeStep}
+ advancedMode={advancedMode}
+ cronConfig={cronConfig}
+ customCronConfig={customCronConfig}
+ createCron={createCron}
+ setCronConfig={setCronConfig}
+ getCronPreset={getCronPreset}
+ fieldHasError={fieldHasError}
+ getFieldError={getFieldError}
+ setCustomCronConfig={setCustomCronConfig}
+ getCronPresetByConfig={getCronPresetByConfig}
+ />
+ )}
+ </>
+ )}
+ </div>
+
+ <WorkflowActions
+ activeStep={activeStep}
+ blueprintSteps={blueprintSteps}
+ advancedMode={advancedMode}
+ setShowBlueprintInspector={setShowBlueprintInspector}
+ validationErrors={[...validationErrors, ...blueprintValidationErrors]}
+ onNext={nextStep}
+ onPrev={prevStep}
+ onSave={handleBlueprintSave}
+ onSaveAndRun={handleBlueprintSaveAndRun}
+ isLoading={
+ isSaving ||
+ isFetchingJIRA ||
+ isFetchingJenkins ||
+ isFetchingConnection ||
+ isTestingConnection
+ }
+ isValid={
+ advancedMode
+ ? isValidBlueprint && isValidPipeline
+ : isValidBlueprint
+ }
+ canGoNext={canAdvanceNext}
+ />
+ </main>
<ConnectionDialog
integrations={Integrations}
diff --git a/config-ui/src/pages/blueprints/index.jsx b/config-ui/src/pages/blueprints/index.jsx
index 72db24c45..8fe90c8fb 100644
--- a/config-ui/src/pages/blueprints/index.jsx
+++ b/config-ui/src/pages/blueprints/index.jsx
@@ -36,10 +36,6 @@ import usePipelineManager from '@/hooks/usePipelineManager'
import useBlueprintManager from '@/hooks/useBlueprintManager'
import useBlueprintValidation from '@/hooks/useBlueprintValidation'
import usePaginator from '@/hooks/usePaginator'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
// import AddBlueprintDialog from '@/components/blueprints/AddBlueprintDialog'
import { ReactComponent as NoBlueprintsIcon } from '@/images/no-blueprints.svg'
import BlueprintsGrid from '@/components/blueprints/BlueprintsGrid'
@@ -342,161 +338,122 @@ const Blueprints = (props) => {
}, [blueprints, setPaginatorData])
return (
- <>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- {/* <AppCrumbs
+ <main className='main'>
+ {/* <AppCrumbs
items={[
{ href: '/', icon: false, text: 'Dashboard' },
{ href: '/pipelines', icon: false, text: 'Pipelines' },
{ href: '/blueprints', icon: false, text: 'Pipeline Blueprints', current: true },
]}
/> */}
- <div className='headlineContainer'>
- <div style={{ display: 'flex' }}>
- <div>
- <h1 style={{ margin: 0 }}>Blueprints</h1>
- </div>
- <div style={{ marginLeft: 'auto' }}>
- {blueprints.length > 0 && (
+ <div className='headlineContainer'>
+ <div style={{ display: 'flex' }}>
+ <div>
+ <h1 style={{ margin: 0 }}>Blueprints</h1>
+ </div>
+ <div style={{ marginLeft: 'auto' }}>
+ {blueprints.length > 0 && (
+ <Button
+ // disabled={pipelines.length === 0}
+ icon='plus'
+ intent={Intent.PRIMARY}
+ text='New Blueprint'
+ onClick={() => createNewBlueprint()}
+ />
+ )}
+ </div>
+ </div>
+ </div>
+ {!isFetchingBlueprints && blueprints.length > 0 && (
+ <>
+ <BlueprintsGrid
+ blueprints={pagedData}
+ pipelines={relatedPipelines}
+ activeFilterStatus={activeFilterStatus}
+ onFilter={setActiveFilterStatus}
+ activeBlueprint={activeBlueprint}
+ blueprintSchedule={blueprintSchedule}
+ isActiveBlueprint={isActiveBlueprint}
+ expandBlueprint={expandBlueprint}
+ deleteBlueprint={deleteBlueprint}
+ createCron={createCron}
+ getNextRunDate={getNextRunDate}
+ handleBlueprintActivation={handleBlueprintActivation}
+ configureBlueprint={configureBlueprint}
+ configureBlueprintSettings={configureBlueprintSettings}
+ isDeleting={isDeleting}
+ isLoading={isFetchingAllPipelines}
+ expandDetails={expandDetails}
+ cronPresets={cronPresets}
+ onViewPipeline={viewPipeline}
+ />
+ </>
+ )}
+
+ {!isFetchingBlueprints && blueprints.length === 0 && (
+ <Card style={{ marginTop: '36px' }} elevation={Elevation.TWO}>
+ <NonIdealState
+ className='blueprints-non-ideal-state'
+ icon={
+ <NoBlueprintsIcon
+ width={120}
+ height={120}
+ style={{ marginBottom: '-30px' }}
+ />
+ }
+ title=''
+ description={
+ <>
+ <p
+ style={{
+ color: '#292B3F',
+ fontSize: '15px',
+ padding: '0 14%',
+ textAlign: 'center'
+ }}
+ >
+ A blueprint is a plan that covers all the work, such as
+ selecting and transforming the data you wish to collect, to
+ get your raw data ready for query and metric computation in
+ the dashboards. Try adding your first blueprint!
+ </p>
+ <div
+ style={{
+ display: 'flex',
+ alignSelf: 'center',
+ justifyContent: 'center',
+ marginTop: '5px'
+ }}
+ >
+ {pipelines.length === 0 ? (
<Button
// disabled={pipelines.length === 0}
icon='plus'
intent={Intent.PRIMARY}
text='New Blueprint'
- onClick={() => createNewBlueprint()}
+ style={{ marginRight: '10px' }}
+ onClick={createNewBlueprint}
+ />
+ ) : (
+ <Button
+ icon='plus'
+ intent={Intent.PRIMARY}
+ text='New Blueprint'
+ style={{ marginRight: '10px' }}
+ onClick={createNewBlueprint}
/>
)}
</div>
- </div>
- </div>
- {!isFetchingBlueprints && blueprints.length > 0 && (
- <>
- <BlueprintsGrid
- blueprints={pagedData}
- pipelines={relatedPipelines}
- activeFilterStatus={activeFilterStatus}
- onFilter={setActiveFilterStatus}
- activeBlueprint={activeBlueprint}
- blueprintSchedule={blueprintSchedule}
- isActiveBlueprint={isActiveBlueprint}
- expandBlueprint={expandBlueprint}
- deleteBlueprint={deleteBlueprint}
- createCron={createCron}
- getNextRunDate={getNextRunDate}
- handleBlueprintActivation={handleBlueprintActivation}
- configureBlueprint={configureBlueprint}
- configureBlueprintSettings={configureBlueprintSettings}
- isDeleting={isDeleting}
- isLoading={isFetchingAllPipelines}
- expandDetails={expandDetails}
- cronPresets={cronPresets}
- onViewPipeline={viewPipeline}
- />
</>
- )}
-
- {!isFetchingBlueprints && blueprints.length === 0 && (
- <Card style={{ marginTop: '36px' }} elevation={Elevation.TWO}>
- <NonIdealState
- className='blueprints-non-ideal-state'
- icon={
- <NoBlueprintsIcon
- width={120}
- height={120}
- style={{ marginBottom: '-30px' }}
- />
- }
- title=''
- description={
- <>
- <p
- style={{
- color: '#292B3F',
- fontSize: '15px',
- padding: '0 14%',
- textAlign: 'center'
- }}
- >
- A blueprint is a plan that covers all the work, such as
- selecting and transforming the data you wish to collect,
- to get your raw data ready for query and metric
- computation in the dashboards. Try adding your first
- blueprint!
- </p>
- <div
- style={{
- display: 'flex',
- alignSelf: 'center',
- justifyContent: 'center',
- marginTop: '5px'
- }}
- >
- {pipelines.length === 0 ? (
- <Button
- // disabled={pipelines.length === 0}
- icon='plus'
- intent={Intent.PRIMARY}
- text='New Blueprint'
- style={{ marginRight: '10px' }}
- onClick={createNewBlueprint}
- />
- ) : (
- <Button
- icon='plus'
- intent={Intent.PRIMARY}
- text='New Blueprint'
- style={{ marginRight: '10px' }}
- onClick={createNewBlueprint}
- />
- )}
- </div>
- </>
- }
- // action={createNewBlueprint}
- />
- </Card>
- )}
- <div style={{ alignSelf: 'flex-end', padding: '10px' }}>
- {renderPagnationControls()}
- </div>
- </main>
- </Content>
+ }
+ // action={createNewBlueprint}
+ />
+ </Card>
+ )}
+ <div style={{ alignSelf: 'flex-end', padding: '10px' }}>
+ {renderPagnationControls()}
</div>
-
- {/* <AddBlueprintDialog
- isLoading={isFetchingAllPipelines}
- isOpen={blueprintDialogIsOpen}
- setIsOpen={setBlueprintDialogIsOpen}
- name={name}
- cronConfig={cronConfig}
- customCronConfig={customCronConfig}
- enable={enable}
- tasks={tasks}
- draftBlueprint={draftBlueprint}
- setDraftBlueprint={setDraftBlueprint}
- setBlueprintName={setBlueprintName}
- setCronConfig={setCronConfig}
- setCustomCronConfig={setCustomCronConfig}
- setEnableBlueprint={setEnableBlueprint}
- setBlueprintTasks={setBlueprintTasks}
- createCron={createCron}
- saveBlueprint={saveBlueprint}
- isSaving={isSaving}
- isValidBlueprint={isValidBlueprint}
- fieldHasError={fieldHasError}
- getFieldError={getFieldError}
- pipelines={pipelineTemplates}
- selectedPipelineTemplate={selectedPipelineTemplate}
- setSelectedPipelineTemplate={setSelectedPipelineTemplate}
- detectedProviders={detectedProviderTasks}
- getCronPreset={getCronPreset}
- getCronPresetByConfig={getCronPresetByConfig}
- /> */}
- </>
+ </main>
)
}
diff --git a/config-ui/src/pages/configure/connections/AddConnection.jsx b/config-ui/src/pages/configure/connections/AddConnection.jsx
index 0b3bc7881..b1016d683 100644
--- a/config-ui/src/pages/configure/connections/AddConnection.jsx
+++ b/config-ui/src/pages/configure/connections/AddConnection.jsx
@@ -18,10 +18,7 @@
import React, { useEffect, useState } from 'react'
import { Link, useHistory, useParams } from 'react-router-dom'
import { Icon } from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
import ConnectionForm from '@/pages/configure/connections/ConnectionForm'
// import { integrationsData } from '@/data/integrations'
// import {
@@ -149,105 +146,92 @@ export default function AddConnection() {
}, [providerId, setActiveProvider, Integrations])
return (
- <>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <AppCrumbs
- items={[
- { href: '/', icon: false, text: 'Dashboard' },
- { href: '/integrations', icon: false, text: 'Connections' },
- {
- href: `/integrations/${activeProvider?.id}`,
- icon: false,
- text: `${activeProvider?.name}`
- },
- {
- href: `/connections/add/${activeProvider?.id}`,
- icon: false,
- text: 'Add Connection',
- current: true
- }
- ]}
- />
- <div style={{ width: '100%' }}>
- <Link
- style={{ float: 'right', marginLeft: '10px', color: '#777777' }}
- to={`/integrations/${activeProvider?.id}`}
- >
- <Icon icon='undo' size={16} /> Go Back
- </Link>
- <div style={{ display: 'flex' }}>
- <div>
- <span style={{ marginRight: '10px' }}>
- <img
- className='providerIconSvg'
- src={'/' + activeProvider?.icon}
- width={40}
- height={40}
- style={{ width: '40px', height: '40px' }}
- />
- </span>
- </div>
- <div>
- <h1 style={{ margin: 0 }}>
- {activeProvider?.name} Add Connection
- </h1>
- <p className='page-description'>
- Create a new connection for this provider.
- </p>
- </div>
- </div>
- <div className='addConnection' style={{ display: 'flex' }}>
- <ConnectionForm
- isLocked={connectionLimitReached}
- isValid={isValidForm}
- validationErrors={validationErrors}
- activeProvider={activeProvider}
- name={name}
- endpointUrl={endpointUrl}
- proxy={proxy}
- rateLimitPerHour={rateLimitPerHour}
- enableGraphql={enableGraphql}
- token={token}
- initialTokenStore={initialTokenStore}
- username={username}
- password={password}
- onSave={() => saveConnection({})}
- onTest={testConnection}
- onCancel={cancel}
- onValidate={validate}
- onNameChange={setName}
- onEndpointChange={setEndpointUrl}
- onProxyChange={setProxy}
- onRateLimitChange={setRateLimitPerHour}
- onEnableGraphqlChange={setEnableGraphql}
- onTokenChange={setToken}
- onUsernameChange={setUsername}
- onPasswordChange={setPassword}
- isSaving={isSaving}
- isTesting={isTesting}
- testStatus={testStatus}
- testResponse={testResponse}
- allTestResponses={allTestResponses}
- errors={errors}
- showError={showError}
- authType={activeProvider?.getAuthenticationType()}
- sourceLimits={ProviderConnectionLimits}
- labels={ProviderFormLabels[activeProvider?.id]}
- placeholders={ProviderFormPlaceholders[activeProvider?.id]}
- tooltips={ProviderFormTooltips[activeProvider?.id]}
- />
- </div>
- {/* {validationErrors.length > 0 && (
- <FormValidationErrors errors={validationErrors} />
- )} */}
- </div>
- </main>
- </Content>
+ <main className='main'>
+ <AppCrumbs
+ items={[
+ { href: '/', icon: false, text: 'Dashboard' },
+ { href: '/integrations', icon: false, text: 'Connections' },
+ {
+ href: `/integrations/${activeProvider?.id}`,
+ icon: false,
+ text: `${activeProvider?.name}`
+ },
+ {
+ href: `/connections/add/${activeProvider?.id}`,
+ icon: false,
+ text: 'Add Connection',
+ current: true
+ }
+ ]}
+ />
+ <div style={{ width: '100%' }}>
+ <Link
+ style={{ float: 'right', marginLeft: '10px', color: '#777777' }}
+ to={`/integrations/${activeProvider?.id}`}
+ >
+ <Icon icon='undo' size={16} /> Go Back
+ </Link>
+ <div style={{ display: 'flex' }}>
+ <div>
+ <span style={{ marginRight: '10px' }}>
+ <img
+ className='providerIconSvg'
+ src={'/' + activeProvider?.icon}
+ width={40}
+ height={40}
+ style={{ width: '40px', height: '40px' }}
+ />
+ </span>
+ </div>
+ <div>
+ <h1 style={{ margin: 0 }}>{activeProvider?.name} Add Connection</h1>
+ <p className='page-description'>
+ Create a new connection for this provider.
+ </p>
+ </div>
+ </div>
+ <div className='addConnection' style={{ display: 'flex' }}>
+ <ConnectionForm
+ isLocked={connectionLimitReached}
+ isValid={isValidForm}
+ validationErrors={validationErrors}
+ activeProvider={activeProvider}
+ name={name}
+ endpointUrl={endpointUrl}
+ proxy={proxy}
+ rateLimitPerHour={rateLimitPerHour}
+ enableGraphql={enableGraphql}
+ token={token}
+ initialTokenStore={initialTokenStore}
+ username={username}
+ password={password}
+ onSave={() => saveConnection({})}
+ onTest={testConnection}
+ onCancel={cancel}
+ onValidate={validate}
+ onNameChange={setName}
+ onEndpointChange={setEndpointUrl}
+ onProxyChange={setProxy}
+ onRateLimitChange={setRateLimitPerHour}
+ onEnableGraphqlChange={setEnableGraphql}
+ onTokenChange={setToken}
+ onUsernameChange={setUsername}
+ onPasswordChange={setPassword}
+ isSaving={isSaving}
+ isTesting={isTesting}
+ testStatus={testStatus}
+ testResponse={testResponse}
+ allTestResponses={allTestResponses}
+ errors={errors}
+ showError={showError}
+ authType={activeProvider?.getAuthenticationType()}
+ sourceLimits={ProviderConnectionLimits}
+ labels={ProviderFormLabels[activeProvider?.id]}
+ placeholders={ProviderFormPlaceholders[activeProvider?.id]}
+ tooltips={ProviderFormTooltips[activeProvider?.id]}
+ />
+ </div>
</div>
- </>
+ </main>
)
}
diff --git a/config-ui/src/pages/configure/connections/ConfigureConnection.jsx b/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
index 958659455..5b9919133 100644
--- a/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
+++ b/config-ui/src/pages/configure/connections/ConfigureConnection.jsx
@@ -18,10 +18,7 @@
import React, { useEffect, useState } from 'react'
import { Link, useHistory, useParams } from 'react-router-dom'
import { Button, Card, Elevation, Icon, Intent } from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
import ContentLoader from '@/components/loaders/ContentLoader'
import useIntegrations from '@/hooks/useIntegrations'
import useConnectionManager from '@/hooks/useConnectionManager'
@@ -183,202 +180,186 @@ export default function ConfigureConnection() {
// }, [saveConnectionComplete])
return (
- <>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <AppCrumbs
- items={[
- { href: '/', icon: false, text: 'Dashboard' },
- { href: '/integrations', icon: false, text: 'Connections' },
- {
- href: `/integrations/${activeProvider?.id}`,
- icon: false,
- text: `${activeProvider?.name}`
- },
- {
- href: `/connections/configure/${activeProvider?.id}/${activeConnection?.id}`,
- icon: false,
- text: `${
- activeConnection ? activeConnection.name : 'Configure'
- } Settings`,
- current: true
- }
- ]}
+ <main className='main'>
+ <AppCrumbs
+ items={[
+ { href: '/', icon: false, text: 'Dashboard' },
+ { href: '/integrations', icon: false, text: 'Connections' },
+ {
+ href: `/integrations/${activeProvider?.id}`,
+ icon: false,
+ text: `${activeProvider?.name}`
+ },
+ {
+ href: `/connections/configure/${activeProvider?.id}/${activeConnection?.id}`,
+ icon: false,
+ text: `${
+ activeConnection ? activeConnection.name : 'Configure'
+ } Settings`,
+ current: true
+ }
+ ]}
+ />
+ <div className='configureConnection' style={{ width: '100%' }}>
+ {!isLoadingConnection && (
+ <Link
+ style={{
+ float: 'right',
+ marginLeft: '10px',
+ color: '#777777'
+ }}
+ to={`/integrations/${activeProvider?.id}`}
+ >
+ <Icon icon='fast-backward' size={16} /> Connection List
+ </Link>
+ )}
+ <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
+ <div>
+ <span style={{ marginRight: '10px' }}>
+ <img
+ className='providerIconSvg'
+ src={'/' + activeProvider?.icon}
+ width={40}
+ height={40}
+ style={{ width: '40px', height: '40px' }}
+ />
+ </span>
+ </div>
+ {isLoadingConnection && (
+ <ContentLoader
+ title='Loading Connection ...'
+ message='Please wait while connection settings are loaded.'
/>
- <div className='configureConnection' style={{ width: '100%' }}>
- {!isLoadingConnection && (
- <Link
- style={{
- float: 'right',
- marginLeft: '10px',
- color: '#777777'
- }}
- to={`/integrations/${activeProvider?.id}`}
- >
- <Icon icon='fast-backward' size={16} /> Connection List
- </Link>
- )}
- <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
- <div>
- <span style={{ marginRight: '10px' }}>
- <img
- className='providerIconSvg'
- src={'/' + activeProvider?.icon}
- width={40}
- height={40}
- style={{ width: '40px', height: '40px' }}
- />
- </span>
- </div>
- {isLoadingConnection && (
- <ContentLoader
- title='Loading Connection ...'
- message='Please wait while connection settings are loaded.'
- />
- )}
- {!isLoadingConnection && (
- <div style={{ justifyContent: 'flex-start' }}>
- <div style={{ display: 'flex' }}>
- <h1 style={{ margin: 0 }}>
- Manage{' '}
- <strong style={{ fontWeight: 900 }}>
- {activeProvider?.name}
- </strong>{' '}
- Settings
- </h1>
- {activeProvider?.multiConnection && (
- <div style={{ paddingTop: '5px' }}>
- <DeleteAction
- id={deleteId}
- connection={activeConnection}
- text='Delete'
- showConfirmation={() =>
- setDeleteId(activeConnection.id)
- }
- onConfirm={deleteConnection}
- onCancel={(e) => setDeleteId(null)}
- isDisabled={isDeletingConnection}
- isLoading={isDeletingConnection}
- >
- <DeleteConfirmationMessage
- title={`DELETE "${activeConnection.name}"`}
- />
- </DeleteAction>
- </div>
- )}
- </div>
- {activeConnection && (
- <>
- {[
- Providers.GITLAB,
- Providers.JIRA,
- Providers.TAPD
- ].includes(activeProvider?.id) && (
- <h2 style={{ margin: 0 }}>
- #{activeConnection?.id} {activeConnection.name}
- </h2>
- )}
- <p className='page-description'>
- Manage settings and options for this connection.
- </p>
- </>
- )}
+ )}
+ {!isLoadingConnection && (
+ <div style={{ justifyContent: 'flex-start' }}>
+ <div style={{ display: 'flex' }}>
+ <h1 style={{ margin: 0 }}>
+ Manage{' '}
+ <strong style={{ fontWeight: 900 }}>
+ {activeProvider?.name}
+ </strong>{' '}
+ Settings
+ </h1>
+ {activeProvider?.multiConnection && (
+ <div style={{ paddingTop: '5px' }}>
+ <DeleteAction
+ id={deleteId}
+ connection={activeConnection}
+ text='Delete'
+ showConfirmation={() => setDeleteId(activeConnection.id)}
+ onConfirm={deleteConnection}
+ onCancel={(e) => setDeleteId(null)}
+ isDisabled={isDeletingConnection}
+ isLoading={isDeletingConnection}
+ >
+ <DeleteConfirmationMessage
+ title={`DELETE "${activeConnection.name}"`}
+ />
+ </DeleteAction>
</div>
)}
</div>
- {!isLoadingConnection && activeProvider && activeConnection && (
+ {activeConnection && (
+ <>
+ {[Providers.GITLAB, Providers.JIRA, Providers.TAPD].includes(
+ activeProvider?.id
+ ) && (
+ <h2 style={{ margin: 0 }}>
+ #{activeConnection?.id} {activeConnection.name}
+ </h2>
+ )}
+ <p className='page-description'>
+ Manage settings and options for this connection.
+ </p>
+ </>
+ )}
+ </div>
+ )}
+ </div>
+ {!isLoadingConnection && activeProvider && activeConnection && (
+ <>
+ <Card
+ interactive={false}
+ elevation={Elevation.ZERO}
+ style={{
+ backgroundColor: '#f8f8f8',
+ width: '100%',
+ marginBottom: '20px'
+ }}
+ >
+ <Button
+ type='button'
+ icon={showConnectionSettings ? 'eye-on' : 'eye-off'}
+ intent={
+ showConnectionSettings ? Intent.PRIMARY : Intent.DISABLED
+ }
+ style={{ margin: '2px', float: 'right' }}
+ onClick={() =>
+ setShowConnectionSettings(!showConnectionSettings)
+ }
+ minimal
+ small
+ />
+ {showConnectionSettings ? (
+ <div className='editConnection' style={{ display: 'flex' }}>
+ <ConnectionForm
+ isValid={isValidForm}
+ validationErrors={validationErrors}
+ activeProvider={activeProvider}
+ name={name}
+ endpointUrl={endpointUrl}
+ proxy={proxy}
+ rateLimitPerHour={rateLimitPerHour}
+ enableGraphql={enableGraphql}
+ token={token}
+ initialTokenStore={initialTokenStore}
+ username={username}
+ password={password}
+ onSave={() => saveConnection()}
+ onTest={testConnection}
+ onCancel={cancel}
+ onValidate={validate}
+ onNameChange={setName}
+ onEndpointChange={setEndpointUrl}
+ onProxyChange={setProxy}
+ onRateLimitChange={setRateLimitPerHour}
+ onEnableGraphqlChange={setEnableGraphql}
+ onTokenChange={setToken}
+ onUsernameChange={setUsername}
+ onPasswordChange={setPassword}
+ isSaving={isSavingConnection}
+ isTesting={isTestingConnection}
+ testStatus={testStatus}
+ testResponse={testResponse}
+ allTestResponses={allTestResponses}
+ errors={errors}
+ showError={showConnectionError}
+ authType={activeProvider?.getAuthenticationType()}
+ showLimitWarning={false}
+ sourceLimits={ProviderConnectionLimits}
+ labels={ProviderFormLabels[activeProvider?.id]}
+ placeholders={ProviderFormPlaceholders[activeProvider?.id]}
+ tooltips={ProviderFormTooltips[activeProvider?.id]}
+ />
+ </div>
+ ) : (
<>
- <Card
- interactive={false}
- elevation={Elevation.ZERO}
- style={{
- backgroundColor: '#f8f8f8',
- width: '100%',
- marginBottom: '20px'
- }}
- >
- <Button
- type='button'
- icon={showConnectionSettings ? 'eye-on' : 'eye-off'}
- intent={
- showConnectionSettings
- ? Intent.PRIMARY
- : Intent.DISABLED
- }
- style={{ margin: '2px', float: 'right' }}
- onClick={() =>
- setShowConnectionSettings(!showConnectionSettings)
- }
- minimal
- small
- />
- {showConnectionSettings ? (
- <div
- className='editConnection'
- style={{ display: 'flex' }}
- >
- <ConnectionForm
- isValid={isValidForm}
- validationErrors={validationErrors}
- activeProvider={activeProvider}
- name={name}
- endpointUrl={endpointUrl}
- proxy={proxy}
- rateLimitPerHour={rateLimitPerHour}
- enableGraphql={enableGraphql}
- token={token}
- initialTokenStore={initialTokenStore}
- username={username}
- password={password}
- onSave={() => saveConnection()}
- onTest={testConnection}
- onCancel={cancel}
- onValidate={validate}
- onNameChange={setName}
- onEndpointChange={setEndpointUrl}
- onProxyChange={setProxy}
- onRateLimitChange={setRateLimitPerHour}
- onEnableGraphqlChange={setEnableGraphql}
- onTokenChange={setToken}
- onUsernameChange={setUsername}
- onPasswordChange={setPassword}
- isSaving={isSavingConnection}
- isTesting={isTestingConnection}
- testStatus={testStatus}
- testResponse={testResponse}
- allTestResponses={allTestResponses}
- errors={errors}
- showError={showConnectionError}
- authType={activeProvider?.getAuthenticationType()}
- showLimitWarning={false}
- sourceLimits={ProviderConnectionLimits}
- labels={ProviderFormLabels[activeProvider?.id]}
- placeholders={
- ProviderFormPlaceholders[activeProvider?.id]
- }
- tooltips={ProviderFormTooltips[activeProvider?.id]}
- />
- </div>
- ) : (
- <>
- <h2 style={{ margin: 0 }}>Configure Connection</h2>
- <p className='description' style={{ margin: 0 }}>
- ( Click the <strong>Visibility</strong> icon to your
- right to edit connection )
- </p>
- </>
- )}
- {/* {validationErrors.length > 0 && (
+ <h2 style={{ margin: 0 }}>Configure Connection</h2>
+ <p className='description' style={{ margin: 0 }}>
+ ( Click the <strong>Visibility</strong> icon to your right
+ to edit connection )
+ </p>
+ </>
+ )}
+ {/* {validationErrors.length > 0 && (
<FormValidationErrors errors={validationErrors} />
)} */}
- </Card>
- {/* <div style={{ marginTop: '30px' }}>
+ </Card>
+ {/* <div style={{ marginTop: '30px' }}>
{renderProviderSettings(providerId, activeProvider)}
</div> */}
- {/* <div className='form-actions-block' style={{ display: 'flex', marginTop: '60px', justifyContent: 'space-between' }}>
+ {/* <div className='form-actions-block' style={{ display: 'flex', marginTop: '60px', justifyContent: 'space-between' }}>
<div />
<div>
<Button icon='remove' text='Cancel' onClick={cancel} disabled={isSaving} />
@@ -393,12 +374,9 @@ export default function ConfigureConnection() {
/>
</div>
</div> */}
- </>
- )}
- </div>
- </main>
- </Content>
+ </>
+ )}
</div>
- </>
+ </main>
)
}
diff --git a/config-ui/src/pages/configure/integration/index.jsx b/config-ui/src/pages/configure/integration/index.jsx
index ef3ce932c..cdfb1a636 100644
--- a/config-ui/src/pages/configure/integration/index.jsx
+++ b/config-ui/src/pages/configure/integration/index.jsx
@@ -18,10 +18,7 @@
import React, { useEffect, useState } from 'react'
import { useHistory } from 'react-router-dom'
import { Colors, Icon } from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
// @todo: replace with Integrations Hook
// import { integrationsData } from '@/data/integrations'
import useIntegrations from '@/hooks/useIntegrations'
@@ -59,111 +56,95 @@ export default function Integration() {
// useEffect(() => {}, [])
return (
- <>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <AppCrumbs
- items={[
- { href: '/', icon: false, text: 'Dashboard' },
- {
- href: '/integrations',
- icon: false,
- text: 'Connections',
- current: true
- }
- ]}
- />
- <div className='headlineContainer'>
- <h1>Data Connections</h1>
- <p className='page-description'>
- {Integrations.length} connections are available for data
- collection.
- </p>
- </div>
- <div className='integrationProviders'>
- {Integrations.map((provider) => (
- <div
- className='iProvider'
- key={`provider-${provider.id}`}
- onClick={() => handleProviderClick(provider.id)}
- style={{ position: 'relative' }}
- >
- {provider?.private && (
- <span
- style={{
- width: '20px',
- height: '20px',
- position: 'absolute',
- top: '-5px',
- right: '-5px',
- textAlign: 'center',
- lineHeight: '16px',
- backgroundColor: '#fff',
- display: 'block',
- borderRadius: '50%',
- border: '1px solid #eee'
- }}
- >
- <Icon
- icon='lock'
- size={10}
- style={{ color: Colors.RED5 }}
- />
- </span>
- )}
- <div className='providerIcon'>
- <img
- className='providerIconSvg'
- src={provider.icon}
- width={40}
- height={40}
- style={{ width: '40px', height: '40px' }}
- />
- </div>
- <div className='providerName'>
- {provider.name}{' '}
- {provider.isBeta && (
- <>
- <sup>(beta)</sup>
- </>
- )}
- </div>
- </div>
- ))}
- </div>
- <div className='headlineContainer'>
- <h1>Webhooks</h1>
- <p className='page-description'>
- You can use webhooks to import deployments and incidents from
- the unsupported data integrations to calculate DORA metrics,
- etc. Please note: webhooks cannot be created or managed in
- Blueprints.
- </p>
- </div>
- <div className='integrationProviders'>
- <div
- className='iProvider'
- style={{ width: 130 }}
- onClick={() => history.push('/connections/incoming-webhook')}
+ <main className='main'>
+ <AppCrumbs
+ items={[
+ { href: '/', icon: false, text: 'Dashboard' },
+ {
+ href: '/integrations',
+ icon: false,
+ text: 'Connections',
+ current: true
+ }
+ ]}
+ />
+ <div className='headlineContainer'>
+ <h1>Data Connections</h1>
+ <p className='page-description'>
+ {Integrations.length} connections are available for data collection.
+ </p>
+ </div>
+ <div className='integrationProviders'>
+ {Integrations.map((provider) => (
+ <div
+ className='iProvider'
+ key={`provider-${provider.id}`}
+ onClick={() => handleProviderClick(provider.id)}
+ style={{ position: 'relative' }}
+ >
+ {provider?.private && (
+ <span
+ style={{
+ width: '20px',
+ height: '20px',
+ position: 'absolute',
+ top: '-5px',
+ right: '-5px',
+ textAlign: 'center',
+ lineHeight: '16px',
+ backgroundColor: '#fff',
+ display: 'block',
+ borderRadius: '50%',
+ border: '1px solid #eee'
+ }}
>
- <div className='providerIcon'>
- <WebHookProviderIcon
- className='providerIconSvg'
- width='40'
- height='40'
- />
- </div>
- <div className='providerName'>
- Issue/Deployment Incoming Webhook
- </div>
- </div>
+ <Icon icon='lock' size={10} style={{ color: Colors.RED5 }} />
+ </span>
+ )}
+ <div className='providerIcon'>
+ <img
+ className='providerIconSvg'
+ src={provider.icon}
+ width={40}
+ height={40}
+ style={{ width: '40px', height: '40px' }}
+ />
</div>
- </main>
- </Content>
+ <div className='providerName'>
+ {provider.name}{' '}
+ {provider.isBeta && (
+ <>
+ <sup>(beta)</sup>
+ </>
+ )}
+ </div>
+ </div>
+ ))}
+ </div>
+ <div className='headlineContainer'>
+ <h1>Webhooks</h1>
+ <p className='page-description'>
+ You can use webhooks to import deployments and incidents from the
+ unsupported data integrations to calculate DORA metrics, etc. Please
+ note: webhooks cannot be created or managed in Blueprints.
+ </p>
+ </div>
+ <div className='integrationProviders'>
+ <div
+ className='iProvider'
+ style={{ width: 130 }}
+ onClick={() => history.push('/connections/incoming-webhook')}
+ >
+ <div className='providerIcon'>
+ <WebHookProviderIcon
+ className='providerIconSvg'
+ width='40'
+ height='40'
+ />
+ </div>
+ <div className='providerName'>Issue/Deployment Incoming Webhook</div>
+ </div>
</div>
- </>
+ </main>
)
}
diff --git a/config-ui/src/pages/configure/integration/manage.jsx b/config-ui/src/pages/configure/integration/manage.jsx
index 84379cc82..5db046245 100644
--- a/config-ui/src/pages/configure/integration/manage.jsx
+++ b/config-ui/src/pages/configure/integration/manage.jsx
@@ -28,10 +28,7 @@ import {
Intent,
Icon
} from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
import AppCrumbs from '@/components/Breadcrumbs'
-import Content from '@/components/Content'
import { ToastNotification } from '@/components/Toast'
import useIntegrations from '@/hooks/useIntegrations'
import useConnectionManager from '@/hooks/useConnectionManager'
@@ -180,284 +177,254 @@ export default function ManageIntegration() {
}, [connections, testAllConnections])
return (
- <>
- <div className='container'>
- <Nav />
- <Sidebar key={Integrations} integrations={Integrations} />
- <Content>
- <main className='main'>
- <AppCrumbs
- items={[
- { href: '/', icon: false, text: 'Dashboard' },
- { href: '/integrations', icon: false, text: 'Connections' },
- {
- href: `/integrations/${activeProvider?.id}`,
- icon: false,
- text: `${activeProvider?.name}`,
- current: true
- }
- ]}
- />
- <div className='headlineContainer'>
- <Link
- style={{ float: 'right', marginLeft: '10px', color: '#777777' }}
- to='/integrations'
- >
- <Icon icon='undo' size={16} /> Go Back
- </Link>
- <div style={{ display: 'flex' }}>
- <div>
- <span style={{ marginRight: '10px' }}>
- <img
- className='providerIconSvg'
- src={'/' + activeProvider?.icon}
- width={40}
- height={40}
- style={{ width: '40px', height: '40px' }}
- />
- </span>
- </div>
- <div>
- <h1 style={{ margin: 0 }}>
- {activeProvider?.name} Connections{' '}
- {activeProvider?.isBeta && (
- <>
- <sup>(beta)</sup>
- </>
- )}
- </h1>
- <p className='page-description'>Manage connections.</p>
- </div>
- </div>
- </div>
- <div className='manageProvider'>
- {errors && errors.length > 0 && (
- <Card
- interactive={false}
- elevation={Elevation.TWO}
- style={{ width: '100%', marginBottom: '20px' }}
- >
- <div style={{}}>
- <h4 className='bp3-heading'>
- <Icon
- icon='warning-sign'
- size={18}
- color={Colors.RED5}
- style={{ marginRight: '10px' }}
- />
- Warning — This integration has issues
- </h4>
- <p
- className='bp3-ui-text bp3-text-large'
- style={{ margin: 0 }}
- >
- Please see below for all messages that will need to be
- resolved.
- </p>
- </div>
- </Card>
+ <main className='main'>
+ <AppCrumbs
+ items={[
+ { href: '/', icon: false, text: 'Dashboard' },
+ { href: '/integrations', icon: false, text: 'Connections' },
+ {
+ href: `/integrations/${activeProvider?.id}`,
+ icon: false,
+ text: `${activeProvider?.name}`,
+ current: true
+ }
+ ]}
+ />
+ <div className='headlineContainer'>
+ <Link
+ style={{ float: 'right', marginLeft: '10px', color: '#777777' }}
+ to='/integrations'
+ >
+ <Icon icon='undo' size={16} /> Go Back
+ </Link>
+ <div style={{ display: 'flex' }}>
+ <div>
+ <span style={{ marginRight: '10px' }}>
+ <img
+ className='providerIconSvg'
+ src={'/' + activeProvider?.icon}
+ width={40}
+ height={40}
+ style={{ width: '40px', height: '40px' }}
+ />
+ </span>
+ </div>
+ <div>
+ <h1 style={{ margin: 0 }}>
+ {activeProvider?.name} Connections{' '}
+ {activeProvider?.isBeta && (
+ <>
+ <sup>(beta)</sup>
+ </>
)}
- {isLoading && (
- <ContentLoader
- title='Loading Connections ...'
- message='Please wait while the connections are loaded.'
+ </h1>
+ <p className='page-description'>Manage connections.</p>
+ </div>
+ </div>
+ </div>
+ <div className='manageProvider'>
+ {errors && errors.length > 0 && (
+ <Card
+ interactive={false}
+ elevation={Elevation.TWO}
+ style={{ width: '100%', marginBottom: '20px' }}
+ >
+ <div style={{}}>
+ <h4 className='bp3-heading'>
+ <Icon
+ icon='warning-sign'
+ size={18}
+ color={Colors.RED5}
+ style={{ marginRight: '10px' }}
/>
- )}
- {!isLoading && connections && connections.length === 0 && (
- <Card
- interactive={false}
- elevation={Elevation.TWO}
- style={{ width: '100%', marginBottom: '20px' }}
- >
- <div style={{}}>
- <h4 className='bp3-heading'>
- <Icon
- icon='offline'
- size={18}
- color={Colors.GRAY3}
- style={{ marginRight: '10px' }}
- />{' '}
- No Connection Entries
- </h4>
- <p
- className='bp3-ui-text bp3-text-large'
- style={{ margin: 0 }}
- >
- Please check your connection settings and try again. Also
- verify the authentication token (if applicable) for
- accuracy.
- </p>
- <p
- className='bp3-monospace-text'
- style={{
- margin: '0 0 20px 0',
- fontSize: '10px',
- color: Colors.GRAY4
- }}
- >
- If the problem persists, please contact our team on{' '}
- <strong>GitHub</strong>
- </p>
- <p>
- <Button
- disabled={connectionLimitReached}
- onClick={addConnection}
- rightIcon='add'
- intent='primary'
- text='Add Connection'
- style={{ marginRight: '10px' }}
- />
- <Button
- rightIcon='refresh'
- text='Refresh Connections'
- minimal
- onClick={refreshConnections}
- />
- </p>
- </div>
- </Card>
- )}
- {!isLoading && connections && connections.length > 0 && (
- <>
- <p>
- <Button
- id='btn-add-new-connection'
- className='add-new-connection'
- disabled={connectionLimitReached}
- onClick={addConnection}
- rightIcon='add'
- intent='primary'
- text='Add Connection'
- style={{ marginRight: '10px' }}
- />
- <Button
- rightIcon='refresh'
- text='Refresh Connections'
- minimal
- onClick={refreshConnections}
- />
- </p>
- <Card
- interactive={false}
- elevation={Elevation.TWO}
- style={{ width: '100%', padding: '2px' }}
- >
- <table
- className='bp3-html-table bp3-html-table-bordered connections-table'
- style={{ width: '100%' }}
+ Warning — This integration has issues
+ </h4>
+ <p className='bp3-ui-text bp3-text-large' style={{ margin: 0 }}>
+ Please see below for all messages that will need to be resolved.
+ </p>
+ </div>
+ </Card>
+ )}
+ {isLoading && (
+ <ContentLoader
+ title='Loading Connections ...'
+ message='Please wait while the connections are loaded.'
+ />
+ )}
+ {!isLoading && connections && connections.length === 0 && (
+ <Card
+ interactive={false}
+ elevation={Elevation.TWO}
+ style={{ width: '100%', marginBottom: '20px' }}
+ >
+ <div style={{}}>
+ <h4 className='bp3-heading'>
+ <Icon
+ icon='offline'
+ size={18}
+ color={Colors.GRAY3}
+ style={{ marginRight: '10px' }}
+ />{' '}
+ No Connection Entries
+ </h4>
+ <p className='bp3-ui-text bp3-text-large' style={{ margin: 0 }}>
+ Please check your connection settings and try again. Also verify
+ the authentication token (if applicable) for accuracy.
+ </p>
+ <p
+ className='bp3-monospace-text'
+ style={{
+ margin: '0 0 20px 0',
+ fontSize: '10px',
+ color: Colors.GRAY4
+ }}
+ >
+ If the problem persists, please contact our team on{' '}
+ <strong>GitHub</strong>
+ </p>
+ <p>
+ <Button
+ disabled={connectionLimitReached}
+ onClick={addConnection}
+ rightIcon='add'
+ intent='primary'
+ text='Add Connection'
+ style={{ marginRight: '10px' }}
+ />
+ <Button
+ rightIcon='refresh'
+ text='Refresh Connections'
+ minimal
+ onClick={refreshConnections}
+ />
+ </p>
+ </div>
+ </Card>
+ )}
+ {!isLoading && connections && connections.length > 0 && (
+ <>
+ <p>
+ <Button
+ id='btn-add-new-connection'
+ className='add-new-connection'
+ disabled={connectionLimitReached}
+ onClick={addConnection}
+ rightIcon='add'
+ intent='primary'
+ text='Add Connection'
+ style={{ marginRight: '10px' }}
+ />
+ <Button
+ rightIcon='refresh'
+ text='Refresh Connections'
+ minimal
+ onClick={refreshConnections}
+ />
+ </p>
+ <Card
+ interactive={false}
+ elevation={Elevation.TWO}
+ style={{ width: '100%', padding: '2px' }}
+ >
+ <table
+ className='bp3-html-table bp3-html-table-bordered connections-table'
+ style={{ width: '100%' }}
+ >
+ <thead>
+ <tr>
+ {!connectionLimitReached && <th>ID</th>}
+ <th>Connection Name</th>
+ <th>Endpoint</th>
+ <th>Status</th>
+ <th />
+ </tr>
+ </thead>
+ <tbody>
+ {connections.map((connection, idx) => (
+ <tr
+ key={`connection-row-${idx}`}
+ // eslint-disable-next-line max-len
+ className={
+ getTestedConnection(connection) &&
+ getTestedConnection(connection).status !== 1
+ ? 'connection-offline'
+ : 'connection-online'
+ }
>
- <thead>
- <tr>
- {!connectionLimitReached && <th>ID</th>}
- <th>Connection Name</th>
- <th>Endpoint</th>
- <th>Status</th>
- <th />
- </tr>
- </thead>
- <tbody>
- {connections.map((connection, idx) => (
- <tr
- key={`connection-row-${idx}`}
- // eslint-disable-next-line max-len
- className={
- getTestedConnection(connection) &&
- getTestedConnection(connection).status !== 1
- ? 'connection-offline'
- : 'connection-online'
- }
+ {!connectionLimitReached && (
+ <td style={{ cursor: 'pointer' }} className='cell-name'>
+ <Tooltip
+ content='Use this ConnectionID for Triggers'
+ position={Position.TOP}
>
- {!connectionLimitReached && (
- <td
- style={{ cursor: 'pointer' }}
- className='cell-name'
- >
- <Tooltip
- content='Use this ConnectionID for Triggers'
- position={Position.TOP}
- >
- <span
- style={{
- color: Colors.BLUE3,
- fontWeight: 'bold'
- }}
- >
- {connection.id}
- </span>
- </Tooltip>
- </td>
- )}
- <td
- onClick={(e) =>
- configureConnection(connection, e)
- }
- style={{ cursor: 'pointer' }}
- className='cell-name'
- >
- {/* <Icon icon='power' color={Colors.GRAY4} size={10} style={{ float: 'right', marginLeft: '10px' }} /> */}
- <strong>
- {connection.name || connection.Name}
- </strong>
- <a
- href='#'
- data-provider={connection.id}
- className='table-action-link'
- onClick={(e) => editConnection(connection, e)}
- />
- </td>
- <td
- className='cell-endpoint'
- onClick={(e) =>
- configureConnection(connection, e)
- }
- style={{ cursor: 'pointer' }}
+ <span
+ style={{
+ color: Colors.BLUE3,
+ fontWeight: 'bold'
+ }}
>
- {connection.endpoint || connection.Endpoint}
- {!connection.endpoint && !connection.Endpoint && (
- <span style={{ color: Colors.GRAY4 }}>
- ( To be configured )
- </span>
- )}
- </td>
- <td className='cell-status'>
- {getConnectionStatus(connection)}
- </td>
- <td className='cell-actions'>
- <a
- href='#'
- data-provider={connection.id}
- className='table-action-link actions-link'
- // onClick={() => editConnection(connection)}
- onClick={(e) =>
- configureConnection(connection, e)
- }
- >
- <Icon icon='settings' size={12} />
- Settings
- </a>
- {activeProvider?.multiConnection && (
- <DeleteAction
- id={deleteId}
- connection={connection}
- text='Delete'
- showConfirmation={() =>
- setDeleteId(connection.id)
- }
- onConfirm={runDeletion}
- onCancel={(e) => setDeleteId(false)}
- isDisabled={
- isRunningDelete || isDeletingConnection
- }
- isLoading={
- isRunningDelete || isDeletingConnection
- }
- >
- <DeleteConfirmationMessage
- title={`DELETE "${connection.name}"`}
- />
- </DeleteAction>
- )}
- {/* <a
+ {connection.id}
+ </span>
+ </Tooltip>
+ </td>
+ )}
+ <td
+ onClick={(e) => configureConnection(connection, e)}
+ style={{ cursor: 'pointer' }}
+ className='cell-name'
+ >
+ {/* <Icon icon='power' color={Colors.GRAY4} size={10} style={{ float: 'right', marginLeft: '10px' }} /> */}
+ <strong>{connection.name || connection.Name}</strong>
+ <a
+ href='#'
+ data-provider={connection.id}
+ className='table-action-link'
+ onClick={(e) => editConnection(connection, e)}
+ />
+ </td>
+ <td
+ className='cell-endpoint'
+ onClick={(e) => configureConnection(connection, e)}
+ style={{ cursor: 'pointer' }}
+ >
+ {connection.endpoint || connection.Endpoint}
+ {!connection.endpoint && !connection.Endpoint && (
+ <span style={{ color: Colors.GRAY4 }}>
+ ( To be configured )
+ </span>
+ )}
+ </td>
+ <td className='cell-status'>
+ {getConnectionStatus(connection)}
+ </td>
+ <td className='cell-actions'>
+ <a
+ href='#'
+ data-provider={connection.id}
+ className='table-action-link actions-link'
+ // onClick={() => editConnection(connection)}
+ onClick={(e) => configureConnection(connection, e)}
+ >
+ <Icon icon='settings' size={12} />
+ Settings
+ </a>
+ {activeProvider?.multiConnection && (
+ <DeleteAction
+ id={deleteId}
+ connection={connection}
+ text='Delete'
+ showConfirmation={() => setDeleteId(connection.id)}
+ onConfirm={runDeletion}
+ onCancel={(e) => setDeleteId(false)}
+ isDisabled={isRunningDelete || isDeletingConnection}
+ isLoading={isRunningDelete || isDeletingConnection}
+ >
+ <DeleteConfirmationMessage
+ title={`DELETE "${connection.name}"`}
+ />
+ </DeleteAction>
+ )}
+ {/* <a
href='#'
data-provider={connection.id}
className='table-action-link actions-link'
@@ -466,7 +433,7 @@ export default function ManageIntegration() {
<Icon icon='refresh' size={12} />
Collect
</a> */}
- {/* <a
+ {/* <a
href='#'
data-provider={connection.id}
className='table-action-link actions-link'
@@ -475,48 +442,45 @@ export default function ManageIntegration() {
<Icon icon='data-connection' size={12} />
Test
</a> */}
- </td>
- </tr>
- ))}
- </tbody>
- </table>
- {!!connectionLimitReached && (
- <p
- style={{
- margin: 0,
- padding: '10px',
- backgroundColor: '#f0f0f0',
- borderTop: '1px solid #cccccc'
- }}
- >
- <Icon
- icon='warning-sign'
- size='16'
- color={Colors.GRAY1}
- style={{ marginRight: '5px' }}
- />
- You have reached the maximum number of allowed
- connections for this provider.
- </p>
- )}
- </Card>
- <p
- style={{
- textAlign: 'right',
- margin: '12px 6px',
- fontSize: '10px',
- color: '#aaaaaa'
- }}
- >
- Fetched <strong>{connections.length}</strong> connection(s)
- from Lake API for <strong>{activeProvider?.name}</strong>
- </p>
- </>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ {!!connectionLimitReached && (
+ <p
+ style={{
+ margin: 0,
+ padding: '10px',
+ backgroundColor: '#f0f0f0',
+ borderTop: '1px solid #cccccc'
+ }}
+ >
+ <Icon
+ icon='warning-sign'
+ size='16'
+ color={Colors.GRAY1}
+ style={{ marginRight: '5px' }}
+ />
+ You have reached the maximum number of allowed connections for
+ this provider.
+ </p>
)}
- </div>
- </main>
- </Content>
+ </Card>
+ <p
+ style={{
+ textAlign: 'right',
+ margin: '12px 6px',
+ fontSize: '10px',
+ color: '#aaaaaa'
+ }}
+ >
+ Fetched <strong>{connections.length}</strong> connection(s) from
+ Lake API for <strong>{activeProvider?.name}</strong>
+ </p>
+ </>
+ )}
</div>
- </>
+ </main>
)
}
diff --git a/config-ui/src/pages/connections/incoming-webhook/index.jsx b/config-ui/src/pages/connections/incoming-webhook/index.jsx
index 3ce3285d9..f641b2667 100644
--- a/config-ui/src/pages/connections/incoming-webhook/index.jsx
+++ b/config-ui/src/pages/connections/incoming-webhook/index.jsx
@@ -20,9 +20,6 @@ import React, { useState } from 'react'
import { Link } from 'react-router-dom'
import { Icon, Button, Intent } from '@blueprintjs/core'
-import Nav from '@/components/Nav'
-import Sidebar from '@/components/Sidebar'
-import Content from '@/components/Content'
import AppCrumbs from '@/components/Breadcrumbs'
import { useWebhookManager } from '@/hooks/useWebhookManager'
import { ReactComponent as WebHookProviderIcon } from '@/images/integrations/incoming-webhook.svg'
@@ -70,98 +67,94 @@ export const IncomingWebhook = () => {
return (
<div className='container'>
- <Nav />
- <Sidebar />
- <Content>
- <div className='main'>
- <AppCrumbs
- items={[
- { href: '/', icon: false, text: 'Dashboard' },
- // use /connections replace here
- { href: '/integrations', icon: false, text: 'Connections' },
- {
- href: '/connections/incoming-webhook',
- icon: false,
- text: 'Incoming Webhook',
- current: true
- }
- ]}
- />
- <div className='headlineContainer'>
- <div
- style={{
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'space-between',
- marginBottom: 12
- }}
- >
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <WebHookProviderIcon
- className='providerIconSvg'
- width='30'
- height='30'
- />
- <h1 style={{ margin: '0 0 0 8px' }}>Incoming Webhook</h1>
- </div>
- <Link style={{ color: '#777777' }} to='/integrations'>
- <Icon icon='undo' size={16} /> Go Back
- </Link>
- </div>
- <div className='page-description'>
- Use Webhooks to define Incidents and Deployments for your CI tools
- if they are not listed in Data Sources.
+ <div className='main'>
+ <AppCrumbs
+ items={[
+ { href: '/', icon: false, text: 'Dashboard' },
+ // use /connections replace here
+ { href: '/integrations', icon: false, text: 'Connections' },
+ {
+ href: '/connections/incoming-webhook',
+ icon: false,
+ text: 'Incoming Webhook',
+ current: true
+ }
+ ]}
+ />
+ <div className='headlineContainer'>
+ <div
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ marginBottom: 12
+ }}
+ >
+ <div style={{ display: 'flex', alignItems: 'center' }}>
+ <WebHookProviderIcon
+ className='providerIconSvg'
+ width='30'
+ height='30'
+ />
+ <h1 style={{ margin: '0 0 0 8px' }}>Incoming Webhook</h1>
</div>
+ <Link style={{ color: '#777777' }} to='/integrations'>
+ <Icon icon='undo' size={16} /> Go Back
+ </Link>
</div>
- <div className='manageProvider'>
- <S.Container>
- <span>
- <Button
- intent='primary'
- text='Add Incoming Webhook'
- loading={operating}
- onClick={() => handleShowModal('add')}
- />
- </span>
- <S.Wrapper>
- <S.Grid className='title'>
- <li>ID</li>
- <li>Incoming Webhook Name</li>
- <li />
- </S.Grid>
- {loading ? (
- <div>Loading</div>
- ) : (
- data.map((it) => (
- <S.Grid key={it.id}>
- <li>{it.id}</li>
- <li>{it.name}</li>
- <li>
- <Button
- loading={operating}
- intent={Intent.PRIMARY}
- minimal
- small
- icon={<EditIcon width={18} height={18} />}
- onClick={() => handleShowModal('edit', it)}
- />
- <Button
- loading={operating}
- intent={Intent.PRIMARY}
- minimal
- small
- icon={<DeleteIcon width={18} height={18} />}
- onClick={() => handleShowModal('delete', it)}
- />
- </li>
- </S.Grid>
- ))
- )}
- </S.Wrapper>
- </S.Container>
+ <div className='page-description'>
+ Use Webhooks to define Incidents and Deployments for your CI tools
+ if they are not listed in Data Sources.
</div>
</div>
- </Content>
+ <div className='manageProvider'>
+ <S.Container>
+ <span>
+ <Button
+ intent='primary'
+ text='Add Incoming Webhook'
+ loading={operating}
+ onClick={() => handleShowModal('add')}
+ />
+ </span>
+ <S.Wrapper>
+ <S.Grid className='title'>
+ <li>ID</li>
+ <li>Incoming Webhook Name</li>
+ <li />
+ </S.Grid>
+ {loading ? (
+ <div>Loading</div>
+ ) : (
+ data.map((it) => (
+ <S.Grid key={it.id}>
+ <li>{it.id}</li>
+ <li>{it.name}</li>
+ <li>
+ <Button
+ loading={operating}
+ intent={Intent.PRIMARY}
+ minimal
+ small
+ icon={<EditIcon width={18} height={18} />}
+ onClick={() => handleShowModal('edit', it)}
+ />
+ <Button
+ loading={operating}
+ intent={Intent.PRIMARY}
+ minimal
+ small
+ icon={<DeleteIcon width={18} height={18} />}
+ onClick={() => handleShowModal('delete', it)}
+ />
+ </li>
+ </S.Grid>
+ ))
+ )}
+ </S.Wrapper>
+ </S.Container>
+ </div>
+ </div>
{modalType === 'add' && (
<AddModal onSubmit={onCreate} onCancel={handleHideModal} />
)}
diff --git a/config-ui/src/registry/index.ts b/config-ui/src/registry/index.ts
new file mode 100644
index 000000000..6f0b45854
--- /dev/null
+++ b/config-ui/src/registry/index.ts
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import AE from './plugins/ae.json'
+import Azure from './plugins/azure.json'
+import BitBucket from './plugins/bitbucket.json'
+import DBT from './plugins/dbt.json'
+import DORA from './plugins/dora.json'
+import Feishu from './plugins/feishu.json'
+import Gitee from './plugins/gitee.json'
+import GitExtractor from './plugins/gitextractor.json'
+import GitHub from './plugins/github.json'
+import GitLab from './plugins/gitlab.json'
+import Jenkins from './plugins/jenkins.json'
+import JIRA from './plugins/jira.json'
+import Refdiff from './plugins/refdiff.json'
+import Starrocks from './plugins/starrocks.json'
+import TAPD from './plugins/tapd.json'
+
+export const Plugins = [
+ AE,
+ Azure,
+ BitBucket,
+ DBT,
+ DORA,
+ Feishu,
+ Gitee,
+ GitExtractor,
+ GitHub,
+ GitLab,
+ Jenkins,
+ JIRA,
+ Refdiff,
+ Starrocks,
+ TAPD
+]
diff --git a/config-ui/src/styles/app.scss b/config-ui/src/styles/app.scss
index 7cfe8dc0a..8cbedf327 100644
--- a/config-ui/src/styles/app.scss
+++ b/config-ui/src/styles/app.scss
@@ -17,7 +17,7 @@
@import '@/styles/fonts.scss';
// Load Core BlueprintJS SCSS Modules
@import '@blueprintjs/core/src/blueprint.scss';
-// @import '@blueprintjs/popover2/src/blueprint-popover2.scss';
+@import '~@blueprintjs/popover2/lib/css/blueprint-popover2.css';
// App-level "blueprint" overrides
@import '@/styles/libraries/blueprint.scss';
// Global App styles
diff --git a/config-ui/src/styles/blueprints.scss b/config-ui/src/styles/blueprints.scss
index 01d238de6..0d25e7e63 100644
--- a/config-ui/src/styles/blueprints.scss
+++ b/config-ui/src/styles/blueprints.scss
@@ -20,7 +20,6 @@
white-space: nowrap;
border: 0;
outline: none;
- min-width: 740px;
display: flex;
justify-content: center;
-webkit-user-select: none;
@@ -118,11 +117,9 @@
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
+ margin-top: 32px;
width: 100%;
- max-width: 700px;
- min-width: 700px;
min-height: 400px;
- margin-top: 32px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
@@ -157,10 +154,9 @@
.workflow-actions {
display: flex;
+ margin-top: 32px;
width: 100%;
- max-width: 700px;
justify-content: space-between;
- margin-top: 32px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
diff --git a/config-ui/src/styles/common.scss b/config-ui/src/styles/common.scss
index 5d0077db1..81a8c0c66 100644
--- a/config-ui/src/styles/common.scss
+++ b/config-ui/src/styles/common.scss
@@ -27,21 +27,8 @@
}
.main {
- // padding: 4rem 4rem 4rem calc(250px + 4rem);
- padding: 4rem;
- margin-left: calc(250px);
- flex: 1;
- display: flex;
- max-width: calc(100vw + -250px);
- flex-direction: column;
- justify-content: flex-start;
- align-items: center;
-
- @media only screen and (max-width: 850px) {
- margin-left: 0;
- max-width: 100vw;
- padding: 0rem;
- }
+ margin: 0 auto;
+ width: 750px;
}
.description {
@@ -65,11 +52,6 @@
}
}
-.logo {
- max-width: 60px;
- margin-bottom: 0.5rem;
-}
-
.code {
margin-right: 0.2rem;
}
diff --git a/config-ui/src/styles/integration.scss b/config-ui/src/styles/integration.scss
index 91ff50ee0..bb6a3dffc 100644
--- a/config-ui/src/styles/integration.scss
+++ b/config-ui/src/styles/integration.scss
@@ -14,15 +14,13 @@
// limitations under the License.
.integrationProviders {
- border: 0;
display: flex;
- width: 80%;
- min-width: 520px;
align-self: flex-start;
+ flex-wrap: wrap;
padding: 10px;
+ border: 0;
.iProvider {
- margin: 0 30px 15px 0;
text-align: center;
width: 96px;
height: 96px;
diff --git a/config-ui/src/styles/nav.scss b/config-ui/src/styles/nav.scss
deleted file mode 100644
index e4f625abe..000000000
--- a/config-ui/src/styles/nav.scss
+++ /dev/null
@@ -1,83 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.navbar {
- position: fixed;
- top: 0;
- border-radius: 0;
- background: #ffffff;
- box-shadow: none;
- z-index: 1;
-}
-
-.navbarMenuButton {
- position: absolute;
- display: none;
- color: #7497F7;
- &:hover {
- color: #E8471C;
- }
-
- @media only screen and (max-width: 850px) {
- display: flex;
- left: 0px;
- }
-}
-
-.navbarMenuButtonSidebarOpened {
- position: absolute;
- display: none;
- color: #7497F7;
- &:hover {
- color: #E8471C;
- }
-
- @media only screen and (max-width: 850px) {
- display: flex;
- left: 240px;
- }
-}
-
-.navbarItems {
- position:absolute;
- right:40px;
-}
-
-.navIconLink:hover {
- color: #E8471C;
-}
-
-.discordIcon {
- height: 1.4em;
- width: 1.4em;
- display: block;
- margin-left: auto;
- margin-right: auto;
- &:hover {
- filter: invert(33%) sepia(24%) saturate(6982%) hue-rotate(355deg) brightness(97%) contrast(88%);
- }
-}
-
-.slackIcon {
- height: 2.5em;
- width: 2.5em;
- display: block;
- margin-left: -5px;
- margin-right: -5px;
- margin-top: 2px;
- &:hover {
- filter: invert(33%) sepia(24%) saturate(6982%) hue-rotate(355deg) brightness(97%) contrast(88%);
- }
-}
\ No newline at end of file
diff --git a/config-ui/src/styles/sidebar-menu.scss b/config-ui/src/styles/sidebar-menu.scss
deleted file mode 100644
index 0cd4abd13..000000000
--- a/config-ui/src/styles/sidebar-menu.scss
+++ /dev/null
@@ -1,80 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.sidebarMenu {
- margin-bottom: auto;
- background-color: transparent;
- color: #ddd;
-
- > li {
- font-size: 12px;
- transition: all 0.3s ease;
- color: #ffffff;
-
- .bp3-menu-item {
- line-height: 26px;
- transition: all 0.3s ease;
- border-radius: 8px;
- margin-bottom: 2px;
- outline: none !important;
-
- &.bp3-active {
- // font-weight: bold;
- background-color: #7497F7;
- color: #ffffff;
- }
-
- .bp3-icon {
- margin-top: 6px;
-
- svg {
- width: 12px;
- margin-right: 5px;
- }
- }
-
- }
-
- .bp3-submenu {
- .bp3-menu-item {
- border-radius: 3px;
- }
- }
- }
-}
-
-.menu-icon {
- display: inline-block;
- width: 14px;
- height: 14px;
- background-position: center left;
- background-size: contain;
- background-repeat: no-repeat;
- &.jira {
- background-position: center left;
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N13uFxV1cfx7wolEBCpgkgJJRRpIqD0oohgpSvqizThBRtIV8GOBQVERQVUbKAi5UWlg3RCJ/QaQhcJPZSQst4/9r7k5nLb3JlzfufMWZ/nmScBktmLZM5ea3Y1dyeEUG1mNgewSH4t2ufV8+/mB+YGRvd6zT3EzwGmAq/nHwf7ec8/TwEmA8/kH3u/ngGecfcZRfw5hBA6x6IACEHLzBYFlsuv5fOPSzJ7sl8QMFWMLXLgeWYvCp4AHgIm5h8fcvfJsghDCFEAhFA0MxvDmxN879dbdNFJ [...]
- background-repeat: no-repeat;
- }
- &.gitlab {
- background-position: center left;
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N13uFxV1cfx7wolEBCpgkgJJRRpIqD0oohgpSvqizThBRtIV8GOBQVERQVUbKAi5UWlg3RCJ/QaQhcJPZSQst4/9r7k5nLb3JlzfufMWZ/nmScBktmLZM5ea3Y1dyeEUG1mNgewSH4t2ufV8+/mB+YGRvd6zT3EzwGmAq/nHwf7ec8/TwEmA8/kH3u/ngGecfcZRfw5hBA6x6IACEHLzBYFlsuv5fOPSzJ7sl8QMFWMLXLgeWYvCp4AHgIm5h8fcvfJsghDCFEAhFA0MxvDmxN879dbdNFJ [...]
- background-repeat: no-repeat;
- }
- &.jenkins {
- background-position: center left;
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N13uFxV1cfx7wolEBCpgkgJJRRpIqD0oohgpSvqizThBRtIV8GOBQVERQVUbKAi5UWlg3RCJ/QaQhcJPZSQst4/9r7k5nLb3JlzfufMWZ/nmScBktmLZM5ea3Y1dyeEUG1mNgewSH4t2ufV8+/mB+YGRvd6zT3EzwGmAq/nHwf7ec8/TwEmA8/kH3u/ngGecfcZRfw5hBA6x6IACEHLzBYFlsuv5fOPSzJ7sl8QMFWMLXLgeWYvCp4AHgIm5h8fcvfJsghDCFEAhFA0MxvDmxN879dbdNFJ [...]
- background-repeat: no-repeat;
- }
-}
\ No newline at end of file
diff --git a/config-ui/src/styles/sidebar.scss b/config-ui/src/styles/sidebar.scss
deleted file mode 100644
index d9cae500c..000000000
--- a/config-ui/src/styles/sidebar.scss
+++ /dev/null
@@ -1,82 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-.card.sidebar-card {
- width: 250px;
- border-radius: 0;
- background-color: #292B3F;
- color: #ffffff;
- z-index: 10;
- box-shadow: none;
- position: fixed;
- height: 100vh;
- left: 0;
- top: 0;
- // padding-top: 50px;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
-
- &:hover {
- box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 1px 1px rgba(16, 22, 26, 0.2), 0 2px 6px rgba(16, 22, 26, 0.2)
- }
-}
-
-.logo {
- max-width: 48px;
- width: 48px;
- height: 48px;
- display: block;
- margin: 28px auto;
-}
-
-.logo-textmark {
- margin: 10px auto;
- display: block;
- max-width: 120px;
- width: 120px;
-}
-
-.copyright-tag {
- display: inline-block;
- margin-top: auto;
- font-size: 11px;
- margin-left: 14px;
- align-self: flex-start;
- color: rgba(124, 124, 124, 0.7);
- text-align: left;
- strong {
- color: rgba(124, 124, 124, 0.9);
- }
-}
-
-.dashboardBtn {
- margin: 0 auto;
- display: block;
- background-color: #7497F7 !important;
- color: #fff !important;
-}
-
-.dashboardBtn:hover {
- opacity: 0.9;
-}
-
-.dashboardBtnLink:hover {
- text-decoration: none;
-}
-
-.dashboardBtn span svg {
- fill: #ff7b56 !important;
-}
\ No newline at end of file