diff --git a/ui/package-lock.json b/ui/package-lock.json index 02095f1..38c278f 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -41,7 +41,8 @@ "eslint": "^8.57.1", "jest": "^29.1.2", "typescript": "^4.8.3", - "vite": "^6.3.5" + "vite": "^6.3.5", + "vite-plugin-svgr": "^4.3.0" }, "engines": { "node": ">=22.0.0" @@ -2412,6 +2413,42 @@ "node": ">=14.0.0" } }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.40.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", @@ -2776,6 +2813,291 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@svgr/core/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svgr/core/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@svgr/core/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, "node_modules/@tokenizer/inflate": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", @@ -4247,6 +4569,17 @@ "csstype": "^3.0.2" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4286,6 +4619,19 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4626,6 +4972,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6372,6 +6725,16 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6632,6 +6995,17 @@ "node": ">= 0.4.0" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -7621,6 +7995,17 @@ "npm": ">= 3.0.0" } }, + "node_modules/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/socks": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", @@ -7880,6 +8265,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/tar": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", @@ -8312,6 +8704,21 @@ } } }, + "node_modules/vite-plugin-svgr": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.3.0.tgz", + "integrity": "sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.3", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=2.6.0" + } + }, "node_modules/vite/node_modules/fdir": { "version": "6.4.4", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", diff --git a/ui/package.json b/ui/package.json index d9bd809..ac94b6c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -48,6 +48,7 @@ "eslint": "^8.57.1", "jest": "^29.1.2", "typescript": "^4.8.3", - "vite": "^6.3.5" + "vite": "^6.3.5", + "vite-plugin-svgr": "^4.3.0" } } diff --git a/ui/src/components/GitBranch/GitBranch.tsx b/ui/src/components/GitBranch/GitBranch.tsx new file mode 100644 index 0000000..1b294b7 --- /dev/null +++ b/ui/src/components/GitBranch/GitBranch.tsx @@ -0,0 +1,6 @@ +import GitBranchSVG from './git-branch.svg?react' +import { SvgIcon, SvgIconProps } from '@mui/material' + +export default function GitBranch(props: SvgIconProps) { + return +} diff --git a/ui/src/components/GitBranch/git-branch.svg b/ui/src/components/GitBranch/git-branch.svg new file mode 100644 index 0000000..29b9a6d --- /dev/null +++ b/ui/src/components/GitBranch/git-branch.svg @@ -0,0 +1,2 @@ + +ionicons-v5-d \ No newline at end of file diff --git a/ui/src/pages/ApplicationDetailsPage/components/BranchesList/BranchCard.tsx b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/BranchCard.tsx new file mode 100644 index 0000000..138d9cc --- /dev/null +++ b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/BranchCard.tsx @@ -0,0 +1,77 @@ +import { Card, CardActionArea, CardContent, Skeleton, Stack, Typography } from '@mui/material' +import { ArtifactListItemReducedDTO } from '../../../../../autogenerated/client/backend' +import { useNavigate } from 'react-router-dom' +import moment from 'moment' +import { Commit, LayersOutlined, SvgIconComponent, SyncOutlined } from '@mui/icons-material' +import GitBranch from '../../../../components/GitBranch/GitBranch' +import InstallDialog from '../InstallDialog' +import { useState } from 'react' +import HintIcon, { LoadingHintIcon } from './HintIcon' + +export default function BranchCard({ branch, version, artifact }: +{ branch: { name: string, pattern: string }, version: string, artifact: ArtifactListItemReducedDTO }) { + const [ installDialogOpen, setInstallDialogOpen ] = useState(false) + + const navigate = useNavigate() + + function onInstall() { + setInstallDialogOpen(false) + navigate('/workloads') + } + + return ( + <> + + setInstallDialogOpen(true) }> + + + + Version { version } + + + + + + + + + + + + setInstallDialogOpen(false) }/> + + ) +} + +export function LoadingBranchCard() { + return ( + + + + + + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/ui/src/pages/ApplicationDetailsPage/components/BranchesList/HintIcon.tsx b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/HintIcon.tsx new file mode 100644 index 0000000..baefc39 --- /dev/null +++ b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/HintIcon.tsx @@ -0,0 +1,28 @@ +import { SvgIconComponent } from '@mui/icons-material' +import { PopperProps, Tooltip, Stack, SvgIcon, Typography, Skeleton } from '@mui/material' + +export default function HintIcon({ tooltip, icon, text }: { tooltip: string, icon: SvgIconComponent, text: string }) { + const popperProps: Partial = { + modifiers: [ + { + name: 'offset', + options: { + offset: [0, -4] + } + } + ] + } + + return ( + + + + { text } + + + ) +} + +export function LoadingHintIcon({ width = 70 }: { width?: number }) { + return +} diff --git a/ui/src/pages/ApplicationDetailsPage/components/BranchesList/index.tsx b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/index.tsx new file mode 100644 index 0000000..48710eb --- /dev/null +++ b/ui/src/pages/ApplicationDetailsPage/components/BranchesList/index.tsx @@ -0,0 +1,61 @@ +import { Stack, Typography } from '@mui/material' +import { ApplicationDTOPackagingFormatEnum, BranchDTO, VersionDTO } from '../../../../../autogenerated/client/backend' +import { useEffect } from 'react' +import { checkKubernetes } from '../../../../clients/kubectl' +import { createDockerDesktopClient } from '@docker/extension-api-client' +import { enqueueSnackbar } from 'notistack' +import { checkDocker } from '../../../../clients/docker' +import { sortArtifacts } from '../../../../clients/util' +import BranchCard from './BranchCard' + +const ddClient = createDockerDesktopClient() + +export default function BranchesList({ branches, packagingFormat }: { branches: BranchDTO[], packagingFormat?: ApplicationDTOPackagingFormatEnum }) { + if (!packagingFormat) { + return This application cannot be deployed yet + } + + useEffect(() => { + switch(packagingFormat) { + case 'HELM_CHART': + checkKubernetes(ddClient) + .catch(e => { + console.error(e) + enqueueSnackbar('Error with kubernetes, make sure the cluster is up and reachable') + }) + break + case 'CONTAINER': + checkDocker(ddClient) + .catch(e => { + console.error(e) + enqueueSnackbar('Error with docker engine, make sure it is running') + }) + break + } + }, []) + + return ( + + { + branches + .filter(branch => branch.versions && branch.versions.length > 0 && branch.versions.find(v => v.artifacts.find(a => a.packaging_format === packagingFormat))) + .flatMap(branch => { + const version = (branch.versions as VersionDTO[]).find(v => v.artifacts.sort(sortArtifacts).find(a => a.packaging_format === packagingFormat)) as VersionDTO + return { + branch: { name: branch.branch_name, pattern: branch.branch_pattern }, + version: version.version_number, + artifact: version.artifacts.reverse().find(a => a.packaging_format === packagingFormat) + } + }) + .filter(({ artifact }) => artifact !== undefined) + .map(({ branch, version, artifact }) => artifact && + + ) + } + + ) +} \ No newline at end of file diff --git a/ui/src/pages/ApplicationDetailsPage/components/BranchesTable.tsx b/ui/src/pages/ApplicationDetailsPage/components/BranchesTable.tsx deleted file mode 100644 index 3f92c9b..0000000 --- a/ui/src/pages/ApplicationDetailsPage/components/BranchesTable.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import { createDockerDesktopClient } from '@docker/extension-api-client' -import { ApplicationDTOPackagingFormatEnum, ArtifactListItemReducedDTO, BranchDTO, VersionDTO } from '../../../../autogenerated/client/backend' -import { Box, CircularProgress, IconButton, Skeleton, Stack, Table, TableBody, TableCell, TableHead, TableRow, Tooltip, Typography } from '@mui/material' -import { PlayCircleOutlined, SettingsOutlined, UpdateOutlined, WarningAmberOutlined } from '@mui/icons-material' -import { useEffect, useState } from 'react' -import { findHelmChart, HelmListItem, upgradeHelmChart, WorkloadStatus } from '../../../clients/helm' -import { compareVersions, sortArtifacts } from '../../../clients/util' -import moment from 'moment' -import InstallDialog from './InstallDialog' -import { checkKubernetes } from '../../../clients/kubectl' -import { enqueueSnackbar } from 'notistack' -import { checkDocker } from '../../../clients/docker' -import { useNavigate } from 'react-router-dom' - -const ddClient = createDockerDesktopClient() - -export default function BranchesTable({ branches, packagingFormat }: { branches: BranchDTO[], packagingFormat?: ApplicationDTOPackagingFormatEnum }) { - if (!packagingFormat) { - return This application cannot be deployed yet - } - - useEffect(() => { - switch(packagingFormat) { - case 'HELM_CHART': - checkKubernetes(ddClient) - .catch(e => { - console.error(e) - enqueueSnackbar('Error with kubernetes, make sure the cluster is up and reachable') - }) - break - case 'CONTAINER': - checkDocker(ddClient) - .catch(e => { - console.error(e) - enqueueSnackbar('Error with docker engine, make sure it is running') - }) - break - } - }, []) - - return ( - - - - Version - Revision - App Version - Registered - Digest - Actions - - - - { - branches - .filter(branch => branch.versions && branch.versions.length > 0 && branch.versions.find(v => v.artifacts.find(a => a.packaging_format === packagingFormat))) - .flatMap(branch => { - const version = (branch.versions as VersionDTO[]).find(v => v.artifacts.sort(sortArtifacts).find(a => a.packaging_format === packagingFormat)) as VersionDTO - return { - branch: { name: branch.branch_name, pattern: branch.branch_pattern }, - version: version.version_number, - artifact: version.artifacts.reverse().find(a => a.packaging_format === packagingFormat) - } - }) - .filter(({ artifact }) => artifact !== undefined) - .map(({ branch, version, artifact }) => artifact && - - ) - } - -
- ) -} - -function BranchRow({ branch, version, artifact }: { branch: { name: string, pattern: string }, version: string, artifact: ArtifactListItemReducedDTO }) { - const [ runningInstance, setRunningInstance ] = useState() - const [ status, setStatus ] = useState() - const [ error, setError ] = useState() - const [ installDialogOpen, setInstallDialogOpen ] = useState(false) - - const navigate = useNavigate() - - useEffect(() => { - switch (artifact.packaging_format) { - case 'HELM_CHART': - findHelmChart(ddClient, artifact.name.split(':')[0], new RegExp(branch.pattern)) - .then(release => { - if (release) { - setRunningInstance(release) - setStatus(release.status) - } else { - setStatus(WorkloadStatus.NotRunning) - } - }) - .catch(e => { - setStatus(WorkloadStatus.Error) - setError(error) - }) - break - case 'CONTAINER': - case 'RPM': - default: - } - }, []) - - function upgrade() { - setStatus(WorkloadStatus.Loading) - switch (artifact.packaging_format) { - case 'HELM_CHART': - if (runningInstance) { - upgradeHelmChart(ddClient, artifact, runningInstance) - .then(result => { - setRunningInstance(result) - setStatus(result.status) - }) - .catch(e => { - setStatus(WorkloadStatus.Error) - setError(e) - }) - } - case 'RPM': - case 'CONTAINER': - } - } - - return ( - <> - - { artifact?.version } - { artifact?.revision } - { version } - { moment(artifact.registered_at).fromNow() } - { artifact?.digest.value.substring(0, 7) } - - { - status ? - - { status === WorkloadStatus.NotRunning && - - setInstallDialogOpen(true) } sx={ { p: 0 } }> - - } - { status === WorkloadStatus.Running && - - navigate('/workloads') } sx={ { p: 0 } }> - - } - { status === WorkloadStatus.Running && runningInstance && compareVersions(artifact.version as string, runningInstance.version as string) != 0 && - - upgrade() } sx={ { p: 0 } }> - - } - { - status === WorkloadStatus.Error && - - - - } - { - status === WorkloadStatus.Loading && - - - - } - - : - - } - - - { status === WorkloadStatus.NotRunning && - { - setRunningInstance(result) - setStatus(result.status) - setInstallDialogOpen(false) - navigate('/workloads') - } } - onDismiss={ () => setInstallDialogOpen(false) }/> } - - ) -} \ No newline at end of file diff --git a/ui/src/pages/ApplicationDetailsPage/index.tsx b/ui/src/pages/ApplicationDetailsPage/index.tsx index 7b0edde..9e051b2 100644 --- a/ui/src/pages/ApplicationDetailsPage/index.tsx +++ b/ui/src/pages/ApplicationDetailsPage/index.tsx @@ -4,7 +4,8 @@ import { ApplicationDTO, ApplicationDTOPackagingFormatEnum, ComponentDTO } from import { useEffect, useState } from 'react' import { applicationsClient, componentsClient } from '../../clients/backend' import { useLoaderData } from 'react-router-dom' -import BranchesTable from './components/BranchesTable' +import BranchesList from './components/BranchesList' +import { LoadingBranchCard } from './components/BranchesList/BranchCard' export async function loader({ params }: { params: any }): Promise { return params.slugName @@ -47,8 +48,11 @@ export default function ApplicationDetailsPage() { Manage branches - Install, pause, stop and update workloads - + Run new workloads in your cluster + + + + ) } @@ -70,8 +74,8 @@ export default function ApplicationDetailsPage() { { application.description } Manage branches - Install, pause, stop and update workloads - !b.inactive_at || new Date(b.inactive_at) > new Date()) } packagingFormat={ application.packaging_format } /> + Run new workloads in your cluster + !b.inactive_at || new Date(b.inactive_at) > new Date()) } packagingFormat={ application.packaging_format } /> ) } \ No newline at end of file diff --git a/ui/src/vite-env.d.ts b/ui/src/vite-env.d.ts index 11f02fe..b1f45c7 100644 --- a/ui/src/vite-env.d.ts +++ b/ui/src/vite-env.d.ts @@ -1 +1,2 @@ /// +/// diff --git a/ui/vite.config.ts b/ui/vite.config.ts index 5ff4b7c..9f10af8 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -1,9 +1,10 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import svgr from 'vite-plugin-svgr' // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [react(), svgr()], base: './', build: { outDir: 'build',