mirror of
https://github.com/outbackdingo/openapi-ui.git
synced 2026-01-28 10:19:50 +00:00
2
.env
2
.env
@@ -31,3 +31,5 @@ VITE_REMOVE_BACKLINK=true
|
||||
VITE_REMOVE_BACKLINK_TEXT=true
|
||||
|
||||
VITE_DOCS_URL=https://in-cloud.io/docs/tech-docs/introduction/
|
||||
|
||||
VITE_SEARCH_TABLE_CUSTOMIZATION_PREFIX=stock-
|
||||
|
||||
@@ -33,3 +33,5 @@ REMOVE_BACKLINK=
|
||||
REMOVE_BACKLINK_TEXT=
|
||||
|
||||
DOCS_URL=
|
||||
|
||||
SEARCH_TABLE_CUSTOMIZATION_PREFIX=
|
||||
|
||||
10
.github/workflows/docker-build.yml
vendored
10
.github/workflows/docker-build.yml
vendored
@@ -2,7 +2,9 @@ name: release
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
- main
|
||||
- develop
|
||||
- release/*
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+'
|
||||
@@ -28,6 +30,10 @@ jobs:
|
||||
username: ${{ secrets.CUSTOM_DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.CUSTOM_DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Sanitize branch name
|
||||
id: sanitize
|
||||
run: echo "branch=$(echo '${{ github.head_ref || github.ref_name }}' | tr '/' '-')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
@@ -35,6 +41,6 @@ jobs:
|
||||
file: ./Dockerfile.build
|
||||
builder: default
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ secrets.CUSTOM_DOCKERHUB_USERNAME }}/openapi-ui:${{ github.head_ref || github.ref_name }}-${{ steps.short-sha.outputs.sha }}
|
||||
tags: ${{ secrets.CUSTOM_DOCKERHUB_USERNAME }}/openapi-ui:${{ steps.sanitize.outputs.branch }}-${{ steps.short-sha.outputs.sha }}
|
||||
build-args: |
|
||||
NODE_VERSION=${{ env.NODE_VERSION }}
|
||||
|
||||
@@ -35,3 +35,4 @@ This app can be configured through environment variables.
|
||||
| `REMOVE_BACKLINK` | `boolean` | Remove backlink arrow from right-side navigation |
|
||||
| `REMOVE_BACKLINK_TEXT` | `boolean` | Remove backlink text from right-side navigation |
|
||||
| `DOCS_URL` | `string` | URL to navigate from question mark |
|
||||
| `SEARCH_TABLE_CUSTOMIZATION_PREFIX` | `string` | Search tables Customization id prefix |
|
||||
|
||||
118
package-lock.json
generated
118
package-lock.json
generated
@@ -11,7 +11,7 @@
|
||||
"@ant-design/icons": "5.6.0",
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
"@originjs/vite-plugin-federation": "1.3.6",
|
||||
"@prorobotech/openapi-k8s-toolkit": "^0.0.1-alpha.121",
|
||||
"@prorobotech/openapi-k8s-toolkit": "^0.0.1-alpha.129",
|
||||
"@readme/openapi-parser": "4.0.0",
|
||||
"@reduxjs/toolkit": "2.2.5",
|
||||
"@tanstack/react-query": "5.62.2",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"antd": "5.26.4",
|
||||
"axios": "1.4.0",
|
||||
"axios": "1.12.2",
|
||||
"cross-env": "7.0.3",
|
||||
"dotenv": "16.4.5",
|
||||
"express": "4.19.2",
|
||||
@@ -146,6 +146,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.0.tgz",
|
||||
"integrity": "sha512-Mb6QkQmPLZsmIHJ6oBsoyKrrT8/kAUdQ6+8q38e2bQSclROi69SiDlI4zZroaIPseae1w110RJH0zGrphAvlSQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.0.0",
|
||||
"@ant-design/icons-svg": "^4.4.0",
|
||||
@@ -257,6 +258,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
|
||||
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
@@ -1857,7 +1859,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
|
||||
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
@@ -1878,6 +1879,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -1901,6 +1903,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -1957,7 +1960,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
|
||||
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"colorspace": "1.1.x",
|
||||
"enabled": "2.0.x",
|
||||
@@ -2802,9 +2804,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@prorobotech/openapi-k8s-toolkit": {
|
||||
"version": "0.0.1-alpha.121",
|
||||
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.121.tgz",
|
||||
"integrity": "sha512-lH693F4RGC8QT5GymDkyY4NHQgDGW67ncTbbT94r/U7ZdHWoME6+z17XNThEMi65OnaMES2PpbF++hEI/Um+IQ==",
|
||||
"version": "0.0.1-alpha.129",
|
||||
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.129.tgz",
|
||||
"integrity": "sha512-V5hrvOfbx7ZXCHu3sDYfvVKJPEbiymMk7Zb/1cQNfkyzjqvBB2JVRVEGVR9c6uyuWOHchBAMkiw2S5c5pm+yfQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
@@ -2812,7 +2814,7 @@
|
||||
"@xterm/addon-attach": "0.11.0",
|
||||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"axios": "1.4.0",
|
||||
"axios": "1.12.2",
|
||||
"cross-env": "7.0.3",
|
||||
"dotenv": "16.4.7",
|
||||
"jsonpath": "1.1.1",
|
||||
@@ -3709,6 +3711,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.62.2.tgz",
|
||||
"integrity": "sha512-fkTpKKfwTJtVPKVR+ag7YqFgG/7TRVVPzduPAUF9zRCiiA8Wu305u+KJl8rCrh98Qce77vzIakvtUyzWLtaPGA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "5.62.2"
|
||||
},
|
||||
@@ -3725,6 +3728,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.62.2.tgz",
|
||||
"integrity": "sha512-s4+88OZ6ygD4ziNfUgh9y1XxsGqpscI77c8EaLP7KwEfa5WqnlB9MT/uslFkFq3vwb8JhMjB7Osv2MYrSMry6w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@tanstack/query-devtools": "5.61.4"
|
||||
},
|
||||
@@ -3859,6 +3863,7 @@
|
||||
"integrity": "sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -3948,8 +3953,7 @@
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
|
||||
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/use-sync-external-store": {
|
||||
"version": "0.0.3",
|
||||
@@ -3997,7 +4001,6 @@
|
||||
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.32.1",
|
||||
"@typescript-eslint/types": "8.32.1",
|
||||
@@ -4023,7 +4026,6 @@
|
||||
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.32.1",
|
||||
"@typescript-eslint/visitor-keys": "8.32.1"
|
||||
@@ -4042,7 +4044,6 @@
|
||||
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.32.1",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
@@ -4061,7 +4062,6 @@
|
||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
@@ -4188,7 +4188,6 @@
|
||||
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
@@ -4203,7 +4202,6 @@
|
||||
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.32.1",
|
||||
"@typescript-eslint/visitor-keys": "8.32.1",
|
||||
@@ -4231,7 +4229,6 @@
|
||||
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.32.1",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
@@ -4250,7 +4247,6 @@
|
||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
@@ -4264,7 +4260,6 @@
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
@@ -4278,7 +4273,6 @@
|
||||
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
},
|
||||
@@ -4439,7 +4433,8 @@
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
@@ -4460,6 +4455,7 @@
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -4482,6 +4478,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -4538,6 +4535,7 @@
|
||||
"resolved": "https://registry.npmjs.org/antd/-/antd-5.26.4.tgz",
|
||||
"integrity": "sha512-e1EnOvEkvvqcQ18dxfzChBJyJACyih13WpNf2OtnP9z2POh/SF0fXL+ynUemT1zfr+p+P1po/tmHXaMc5PMghg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.2.1",
|
||||
"@ant-design/cssinjs": "^1.23.0",
|
||||
@@ -4855,8 +4853,7 @@
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async-function": {
|
||||
"version": "1.0.0",
|
||||
@@ -4901,13 +4898,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
@@ -5259,6 +5256,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001716",
|
||||
"electron-to-chromium": "^1.5.149",
|
||||
@@ -5508,7 +5506,6 @@
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
|
||||
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.3",
|
||||
"color-string": "^1.6.0"
|
||||
@@ -5538,7 +5535,6 @@
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
@@ -5549,7 +5545,6 @@
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -5558,8 +5553,7 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/colord": {
|
||||
"version": "2.9.3",
|
||||
@@ -5572,7 +5566,6 @@
|
||||
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
|
||||
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color": "^3.1.3",
|
||||
"text-hex": "1.0.x"
|
||||
@@ -5970,7 +5963,8 @@
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
@@ -6200,8 +6194,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
@@ -6570,6 +6563,7 @@
|
||||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
@@ -6731,6 +6725,7 @@
|
||||
"integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"array-includes": "^3.1.6",
|
||||
"array.prototype.findlastindex": "^1.2.2",
|
||||
@@ -6810,6 +6805,7 @@
|
||||
"integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.7",
|
||||
"aria-query": "^5.1.3",
|
||||
@@ -6895,6 +6891,7 @@
|
||||
"integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"array-includes": "^3.1.6",
|
||||
"array.prototype.flatmap": "^1.3.1",
|
||||
@@ -6926,6 +6923,7 @@
|
||||
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
@@ -7503,8 +7501,7 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
|
||||
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
@@ -7607,8 +7604,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
@@ -7647,14 +7643,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
@@ -8744,7 +8741,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
@@ -9035,8 +9031,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/language-subtag-registry": {
|
||||
"version": "0.3.23",
|
||||
@@ -9132,7 +9127,6 @@
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
|
||||
"integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/triple-beam": "^1.3.2",
|
||||
@@ -9678,7 +9672,6 @@
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fn.name": "1.x.x"
|
||||
}
|
||||
@@ -9687,7 +9680,8 @@
|
||||
"version": "12.1.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
@@ -9973,6 +9967,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.8",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -10022,6 +10017,7 @@
|
||||
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
@@ -10093,6 +10089,7 @@
|
||||
"integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -10138,6 +10135,7 @@
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz",
|
||||
"integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"tdigest": "^0.1.1"
|
||||
@@ -10914,6 +10912,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -10926,6 +10925,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -10984,6 +10984,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz",
|
||||
"integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.18.0",
|
||||
"react-router": "6.25.1"
|
||||
@@ -11027,7 +11028,8 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/redux-thunk": {
|
||||
"version": "3.1.0",
|
||||
@@ -11259,6 +11261,7 @@
|
||||
"integrity": "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.7"
|
||||
},
|
||||
@@ -11397,7 +11400,6 @@
|
||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
|
||||
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -11682,7 +11684,6 @@
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
@@ -11691,8 +11692,7 @@
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "2.0.0",
|
||||
@@ -11758,7 +11758,6 @@
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
@@ -12283,8 +12282,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
@@ -12347,7 +12345,6 @@
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
|
||||
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
}
|
||||
@@ -12977,6 +12974,7 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -13213,6 +13211,7 @@
|
||||
"integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
@@ -13464,7 +13463,6 @@
|
||||
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
|
||||
"integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"logform": "^2.7.0",
|
||||
"readable-stream": "^3.6.2",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@ant-design/icons": "5.6.0",
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
"@originjs/vite-plugin-federation": "1.3.6",
|
||||
"@prorobotech/openapi-k8s-toolkit": "0.0.1-alpha.121",
|
||||
"@prorobotech/openapi-k8s-toolkit": "0.0.1-alpha.129",
|
||||
"@readme/openapi-parser": "4.0.0",
|
||||
"@reduxjs/toolkit": "2.2.5",
|
||||
"@tanstack/react-query": "5.62.2",
|
||||
@@ -29,7 +29,7 @@
|
||||
"@xterm/addon-fit": "0.10.0",
|
||||
"@xterm/xterm": "5.5.0",
|
||||
"antd": "5.26.4",
|
||||
"axios": "1.4.0",
|
||||
"axios": "1.12.2",
|
||||
"cross-env": "7.0.3",
|
||||
"dotenv": "16.4.5",
|
||||
"express": "4.19.2",
|
||||
|
||||
@@ -68,6 +68,11 @@ const REMOVE_BACKLINK_TEXT =
|
||||
|
||||
const DOCS_URL = process.env.LOCAL === 'true' ? options?.DOCS_URL : process.env.DOCS_URL
|
||||
|
||||
const SEARCH_TABLE_CUSTOMIZATION_PREFIX =
|
||||
process.env.LOCAL === 'true'
|
||||
? options?.SEARCH_TABLE_CUSTOMIZATION_PREFIX
|
||||
: process.env.SEARCH_TABLE_CUSTOMIZATION_PREFIX
|
||||
|
||||
const healthcheck = require('express-healthcheck')
|
||||
const promBundle = require('express-prom-bundle')
|
||||
|
||||
@@ -192,6 +197,7 @@ app.get(`${basePrefix ? basePrefix : ''}/env.js`, (_, res) => {
|
||||
LOGOUT_URL: ${JSON.stringify(LOGOUT_URL) || '"check envs"'},
|
||||
LOGIN_USERNAME_FIELD: ${JSON.stringify(LOGIN_USERNAME_FIELD) || '"check envs"'},
|
||||
DOCS_URL: ${JSON.stringify(DOCS_URL) || '"/docs"'},
|
||||
SEARCH_TABLE_CUSTOMIZATION_PREFIX: ${JSON.stringify(SEARCH_TABLE_CUSTOMIZATION_PREFIX) || '"search-"'},
|
||||
REMOVE_BACKLINK: ${!!REMOVE_BACKLINK ? JSON.stringify(REMOVE_BACKLINK).toLowerCase() : '"false"'},
|
||||
REMOVE_BACKLINK_TEXT: ${!!REMOVE_BACKLINK_TEXT ? JSON.stringify(REMOVE_BACKLINK_TEXT).toLowerCase() : '"false"'}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,9 @@ export const App: FC<TAppProps> = ({ isFederation, forcedTheme }) => {
|
||||
colorText: colors?.colorText,
|
||||
colorTextLightSolid: colors?.colorText,
|
||||
},
|
||||
Popover: {
|
||||
colorBgElevated: colors?.colorBgLayout,
|
||||
},
|
||||
Table: {
|
||||
headerBg: colors?.colorBgLayout,
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
checkIfApiInstanceNamespaceScoped,
|
||||
useBuiltinResources,
|
||||
useApiResources,
|
||||
Spacer,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { FlexGrow, PaddingContainer } from 'components'
|
||||
import { TABLE_PROPS } from 'constants/tableProps'
|
||||
@@ -34,13 +35,13 @@ type TTableApiBuiltinProps = {
|
||||
apiGroup?: string // api
|
||||
apiVersion?: string // api
|
||||
typeName: string
|
||||
specificName?: string
|
||||
labels?: string[]
|
||||
fields?: string[]
|
||||
limit: string | null
|
||||
inside?: boolean
|
||||
customizationIdPrefix: string
|
||||
searchMount?: boolean
|
||||
kindName?: string
|
||||
}
|
||||
|
||||
export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
@@ -49,13 +50,13 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
apiGroup,
|
||||
apiVersion,
|
||||
typeName,
|
||||
specificName,
|
||||
labels,
|
||||
fields,
|
||||
limit,
|
||||
inside,
|
||||
customizationIdPrefix,
|
||||
searchMount,
|
||||
kindName,
|
||||
}) => {
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
@@ -156,7 +157,6 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
clusterName: cluster,
|
||||
namespace,
|
||||
typeName,
|
||||
specificName,
|
||||
labels,
|
||||
fields,
|
||||
limit,
|
||||
@@ -173,7 +173,6 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
apiGroup: apiGroup || '',
|
||||
apiVersion: apiVersion || '',
|
||||
typeName,
|
||||
specificName,
|
||||
labels,
|
||||
fields,
|
||||
limit,
|
||||
@@ -196,6 +195,8 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
const fullPath = `${location.pathname}${location.search}`
|
||||
|
||||
return (
|
||||
<>
|
||||
{((resourceType === 'builtin' && isPendingBuiltin) || (resourceType === 'api' && isPendingApi)) && <Spin />}
|
||||
@@ -234,7 +235,7 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
cluster={cluster}
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={getDataItems({ resourceType, dataBuiltin, dataApi, isSingle: !!specificName })}
|
||||
dataItems={getDataItems({ resourceType, dataBuiltin, dataApi })}
|
||||
dataForControls={{
|
||||
cluster,
|
||||
syntheticProject: params.syntheticProject,
|
||||
@@ -251,6 +252,8 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
}),
|
||||
deletePathPrefix:
|
||||
resourceType === 'builtin' ? `/api/clusters/${cluster}/k8s/api` : `/api/clusters/${cluster}/k8s/apis`,
|
||||
@@ -268,6 +271,7 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
},
|
||||
}}
|
||||
tableProps={{ ...TABLE_PROPS, disablePagination: !searchMount }}
|
||||
namespaceScopedWithoutNamespace={isNamespaced && !namespace}
|
||||
// maxHeight={height - 65}
|
||||
/>
|
||||
)}
|
||||
@@ -286,49 +290,47 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
|
||||
</MarginTopContainer>
|
||||
)} */}
|
||||
</OverflowContainer>
|
||||
{!searchMount && (
|
||||
<>
|
||||
<FlexGrow />
|
||||
<PaddingContainer $padding="4px">
|
||||
<Flex justify="space-between">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
const url = getLinkToForm({
|
||||
resourceType,
|
||||
cluster,
|
||||
baseprefix,
|
||||
namespace,
|
||||
syntheticProject: params.syntheticProject,
|
||||
apiGroup,
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
})
|
||||
navigate(url)
|
||||
}}
|
||||
loading={isNamespaced ? false : createPermission.isPending}
|
||||
disabled={isNamespaced ? false : !createPermission.data?.status.allowed}
|
||||
>
|
||||
<PlusOutlined />
|
||||
Add
|
||||
{searchMount ? <Spacer $space={12} $samespace /> : <FlexGrow />}
|
||||
<PaddingContainer $padding="4px">
|
||||
<Flex justify="space-between">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
const url = getLinkToForm({
|
||||
resourceType,
|
||||
cluster,
|
||||
baseprefix,
|
||||
namespace,
|
||||
syntheticProject: params.syntheticProject,
|
||||
apiGroup,
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
})
|
||||
navigate(url)
|
||||
}}
|
||||
loading={isNamespaced ? false : createPermission.isPending}
|
||||
disabled={isNamespaced ? false : !createPermission.data?.status.allowed}
|
||||
>
|
||||
<PlusOutlined />
|
||||
Add {kindName}
|
||||
</Button>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<Flex gap={16}>
|
||||
<Button type="primary" onClick={clearSelected}>
|
||||
<ClearOutlined />
|
||||
Clear
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
|
||||
<MinusOutlined />
|
||||
Delete
|
||||
</Button>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<Flex gap={16}>
|
||||
<Button type="primary" onClick={clearSelected}>
|
||||
<ClearOutlined />
|
||||
Clear
|
||||
</Button>
|
||||
<Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
|
||||
<MinusOutlined />
|
||||
Delete
|
||||
</Button>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
</PaddingContainer>
|
||||
</>
|
||||
)}
|
||||
)}
|
||||
</Flex>
|
||||
</PaddingContainer>
|
||||
{isDeleteModalOpen && (
|
||||
<DeleteModal
|
||||
name={isDeleteModalOpen.name}
|
||||
|
||||
@@ -4,22 +4,11 @@ export const getDataItems = ({
|
||||
resourceType,
|
||||
dataBuiltin,
|
||||
dataApi,
|
||||
isSingle,
|
||||
}: {
|
||||
resourceType: 'builtin' | 'api'
|
||||
dataBuiltin?: TBuiltinResources
|
||||
dataApi?: TApiResources
|
||||
isSingle?: boolean
|
||||
}): TJSON[] => {
|
||||
if (isSingle) {
|
||||
if (resourceType === 'builtin') {
|
||||
return dataBuiltin ? [dataBuiltin] : []
|
||||
}
|
||||
|
||||
if (resourceType === 'api') {
|
||||
return dataApi ? [dataApi] : []
|
||||
}
|
||||
}
|
||||
return resourceType === 'builtin' ? dataBuiltin?.items || [] : dataApi?.items || []
|
||||
}
|
||||
|
||||
@@ -30,6 +19,8 @@ export const getBackLinkToBuiltinTable = ({
|
||||
syntheticProject,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
}: {
|
||||
cluster: string
|
||||
baseprefix?: string
|
||||
@@ -37,7 +28,12 @@ export const getBackLinkToBuiltinTable = ({
|
||||
syntheticProject?: string
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
if (searchMount) {
|
||||
return encodeURIComponent(fullPath)
|
||||
}
|
||||
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
|
||||
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
|
||||
|
||||
@@ -53,6 +49,8 @@ export const getBackLinkToApiTable = ({
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
}: {
|
||||
cluster: string
|
||||
baseprefix?: string
|
||||
@@ -62,7 +60,13 @@ export const getBackLinkToApiTable = ({
|
||||
apiVersion?: string // api
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
if (searchMount) {
|
||||
return encodeURIComponent(fullPath)
|
||||
}
|
||||
|
||||
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
|
||||
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
|
||||
|
||||
@@ -82,6 +86,8 @@ export const getBackLinkToTable = ({
|
||||
apiVersion?: string // api
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
return resourceType === 'builtin' ? getBackLinkToBuiltinTable({ ...rest }) : getBackLinkToApiTable({ ...rest })
|
||||
}
|
||||
@@ -93,6 +99,8 @@ export const getLinkToBuiltinForm = ({
|
||||
syntheticProject,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
}: {
|
||||
cluster: string
|
||||
baseprefix?: string
|
||||
@@ -100,10 +108,21 @@ export const getLinkToBuiltinForm = ({
|
||||
syntheticProject?: string
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
|
||||
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
|
||||
const backlink = getBackLinkToBuiltinTable({ cluster, baseprefix, namespace, syntheticProject, typeName, inside })
|
||||
const backlink = getBackLinkToBuiltinTable({
|
||||
cluster,
|
||||
baseprefix,
|
||||
namespace,
|
||||
syntheticProject,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
})
|
||||
|
||||
return `${mainRoute}/forms/builtin/v1/${typeName}?backlink=${backlink}`
|
||||
}
|
||||
@@ -117,6 +136,8 @@ export const getLinkToApiForm = ({
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
}: {
|
||||
cluster: string
|
||||
baseprefix?: string
|
||||
@@ -126,6 +147,8 @@ export const getLinkToApiForm = ({
|
||||
apiVersion?: string // api
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
|
||||
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
|
||||
@@ -138,6 +161,8 @@ export const getLinkToApiForm = ({
|
||||
apiVersion,
|
||||
typeName,
|
||||
inside,
|
||||
fullPath,
|
||||
searchMount,
|
||||
})
|
||||
|
||||
return `${mainRoute}/forms/apis/${apiGroup}/${apiVersion}/${typeName}?backlink=${backlink}`
|
||||
@@ -156,6 +181,8 @@ export const getLinkToForm = ({
|
||||
apiVersion?: string // api
|
||||
typeName: string
|
||||
inside?: boolean
|
||||
fullPath: string
|
||||
searchMount?: boolean
|
||||
}): string => {
|
||||
return resourceType === 'builtin' ? getLinkToBuiltinForm({ ...rest }) : getLinkToApiForm({ ...rest })
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import { Styled } from './styled'
|
||||
|
||||
type THeaderProps = {
|
||||
inside?: boolean
|
||||
isSearch?: boolean
|
||||
}
|
||||
|
||||
export const HeaderSecond: FC<THeaderProps> = ({ inside }) => {
|
||||
export const HeaderSecond: FC<THeaderProps> = ({ inside, isSearch }) => {
|
||||
// const { projectName, instanceName, clusterName, entryType, namespace, syntheticProject } = useParams()
|
||||
const { projectName, instanceName, clusterName, namespace, syntheticProject } = useParams()
|
||||
const { token } = theme.useToken()
|
||||
@@ -24,14 +25,14 @@ export const HeaderSecond: FC<THeaderProps> = ({ inside }) => {
|
||||
<Flex gap={18}>
|
||||
{inside ? <SelectorClusterInside clusterName={clusterName} /> : <SelectorCluster clusterName={clusterName} />}
|
||||
{inside && <SelectorInside clusterName={clusterName} namespace={namespace} />}
|
||||
{!inside && BASE_USE_NAMESPACE_NAV !== 'true' && (
|
||||
{!inside && !isSearch && BASE_USE_NAMESPACE_NAV !== 'true' && (
|
||||
<Selector
|
||||
clusterName={clusterName}
|
||||
projectName={projectName || possibleProject}
|
||||
instanceName={instanceName || possibleInstance}
|
||||
/>
|
||||
)}
|
||||
{!inside && BASE_USE_NAMESPACE_NAV === 'true' && (
|
||||
{!inside && (isSearch || BASE_USE_NAMESPACE_NAV === 'true') && (
|
||||
<SelectorNamespace clusterName={clusterName} namespace={namespace} />
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import React, { FC, useState } from 'react'
|
||||
import { Flex, Typography } from 'antd'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { useDirectUnknownResource } from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { useSelector } from 'react-redux'
|
||||
import type { RootState } from 'store/store'
|
||||
import { useNavSelectorInside } from 'hooks/useNavSelectorInside'
|
||||
import { useMountEffect } from 'hooks/useMountEffect'
|
||||
import { useIsSearchPage } from 'hooks/useIsSearchPage'
|
||||
import { EntrySelect } from 'components/atoms'
|
||||
import {
|
||||
BASE_API_GROUP,
|
||||
@@ -19,6 +22,9 @@ type TSelectorNamespaceProps = {
|
||||
|
||||
export const SelectorNamespace: FC<TSelectorNamespaceProps> = ({ clusterName, namespace }) => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
|
||||
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
|
||||
|
||||
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
|
||||
const [selectedNamespace, setSelectedNamespace] = useState(namespace)
|
||||
@@ -34,7 +40,45 @@ export const SelectorNamespace: FC<TSelectorNamespaceProps> = ({ clusterName, na
|
||||
isEnabled: clusterName !== undefined,
|
||||
})
|
||||
|
||||
const isSearchPage = useIsSearchPage(baseprefix || '')
|
||||
|
||||
const handleNamepsaceChange = (value?: string) => {
|
||||
if (isSearchPage) {
|
||||
const { pathname, search, hash } = location
|
||||
const segs = pathname.split('/')
|
||||
|
||||
// Assume pattern: /prefix/:clusterName/:namespace?/:syntheticProject?/search/*
|
||||
// Find the "search" segment index
|
||||
const searchIdx = segs.indexOf('search')
|
||||
const clusterIdx = segs.indexOf(selectedClusterName || '')
|
||||
if (clusterIdx === -1) {
|
||||
return
|
||||
} // bail if we can't find the cluster
|
||||
|
||||
const nsIdx = clusterIdx + 1 // where namespace would live if present
|
||||
const spIdx = clusterIdx + 2 // where syntheticProject would live if present
|
||||
const nsExists = nsIdx < searchIdx // true if something occupies ns slot
|
||||
const spExists = spIdx < searchIdx // true if something occupies sp slot
|
||||
|
||||
if (value && value !== 'all') {
|
||||
setSelectedNamespace(value)
|
||||
|
||||
if (nsExists) {
|
||||
// replace namespace in place
|
||||
segs[nsIdx] = value
|
||||
} else {
|
||||
// insert namespace before "search" (or before syntheticProject if present)
|
||||
const insertAt = spExists ? spIdx : searchIdx
|
||||
segs.splice(insertAt, 0, value)
|
||||
}
|
||||
} else if (nsExists) {
|
||||
segs.splice(nsIdx, 1) // removes namespace; syntheticProject (if any) shifts left
|
||||
}
|
||||
// if ns didn't exist, nothing to clear
|
||||
|
||||
navigate(segs.join('/') + search + hash, { replace: true })
|
||||
return
|
||||
}
|
||||
if (value && value !== 'all') {
|
||||
setSelectedNamespace(value)
|
||||
const changeUrl =
|
||||
|
||||
@@ -1,34 +1,324 @@
|
||||
/* eslint-disable max-lines-per-function */
|
||||
import React, { FC, Fragment, useState } from 'react'
|
||||
import { Search as PackageSearch, Spacer } from '@prorobotech/openapi-k8s-toolkit'
|
||||
import React, { FC, Fragment, useState, useEffect, useLayoutEffect, useRef } from 'react'
|
||||
import { useLocation, useSearchParams } from 'react-router-dom'
|
||||
import {
|
||||
Search as PackageSearch,
|
||||
Spacer,
|
||||
TRequestError,
|
||||
TKindIndex,
|
||||
TKindWithVersion,
|
||||
getKinds,
|
||||
getSortedKindsAll,
|
||||
LookingGlassIcon,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { ConfigProvider, theme as antdtheme, Form, Spin, Alert } from 'antd'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import { HEAD_FIRST_ROW, HEAD_SECOND_ROW, FOOTER_HEIGHT, NAV_HEIGHT, CONTENT_CARD_PADDING } from 'constants/blocksSizes'
|
||||
import {
|
||||
FIELD_NAME,
|
||||
FIELD_NAME_STRING,
|
||||
FIELD_NAME_LABELS,
|
||||
FIELD_NAME_FIELDS,
|
||||
QUERY_KEY,
|
||||
NAME_QUERY_KEY,
|
||||
LABELS_QUERY_KEY,
|
||||
FIELDS_QUERY_KEY,
|
||||
TYPE_SELECTOR,
|
||||
TYPE_QUERY_KEY,
|
||||
} from './constants'
|
||||
import {
|
||||
useDebouncedCallback,
|
||||
getArrayParam,
|
||||
setArrayParam,
|
||||
getStringParam,
|
||||
setStringParam,
|
||||
getTypeParam,
|
||||
setTypeParam,
|
||||
} from './utils'
|
||||
import { SearchEntry } from './molecules'
|
||||
import { Styled } from './styled'
|
||||
|
||||
export const Search: FC = () => {
|
||||
const cluster = useSelector((state: RootState) => state.cluster.cluster)
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const location = useLocation()
|
||||
const { token } = antdtheme.useToken()
|
||||
|
||||
const [currentSearch, setCurrentSearch] = useState<{
|
||||
resources?: string[]
|
||||
name?: string
|
||||
labels?: string[]
|
||||
fields?: string[]
|
||||
}>()
|
||||
const cluster = useSelector((state: RootState) => state.cluster.cluster)
|
||||
const theme = useSelector((state: RootState) => state.openapiTheme.theme)
|
||||
|
||||
const [form] = Form.useForm()
|
||||
|
||||
const [error, setError] = useState<TRequestError | undefined>()
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [kindIndex, setKindIndex] = useState<TKindIndex>()
|
||||
const [kindsWithVersion, setKindWithVersion] = useState<TKindWithVersion[]>()
|
||||
|
||||
const [height, setHeight] = useState(0)
|
||||
const [emptyHeight, setEmptyHeight] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const height =
|
||||
window.innerHeight - HEAD_FIRST_ROW - HEAD_SECOND_ROW - NAV_HEIGHT - CONTENT_CARD_PADDING * 2 - FOOTER_HEIGHT - 1
|
||||
setHeight(height)
|
||||
|
||||
const handleResize = () => {
|
||||
setHeight(height)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const emptyHeight =
|
||||
window.innerHeight -
|
||||
HEAD_FIRST_ROW -
|
||||
HEAD_SECOND_ROW -
|
||||
NAV_HEIGHT -
|
||||
CONTENT_CARD_PADDING * 2 -
|
||||
FOOTER_HEIGHT -
|
||||
1 -
|
||||
50 // packagesearch emptyy height
|
||||
setEmptyHeight(emptyHeight)
|
||||
|
||||
const handleResize = () => {
|
||||
setEmptyHeight(emptyHeight)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true)
|
||||
setError(undefined)
|
||||
getKinds({ clusterName: cluster })
|
||||
.then(data => {
|
||||
setKindIndex(data)
|
||||
setKindWithVersion(getSortedKindsAll(data))
|
||||
setIsLoading(false)
|
||||
setError(undefined)
|
||||
})
|
||||
.catch(error => {
|
||||
setIsLoading(false)
|
||||
setError(error)
|
||||
})
|
||||
}, [cluster])
|
||||
|
||||
const watchedKinds = Form.useWatch<string[] | undefined>(FIELD_NAME, form)
|
||||
const watchedName = Form.useWatch<string | undefined>(FIELD_NAME_STRING, form)
|
||||
const watchedLabels = Form.useWatch<string[] | undefined>(FIELD_NAME_LABELS, form)
|
||||
const watchedFields = Form.useWatch<string[] | undefined>(FIELD_NAME_FIELDS, form)
|
||||
const watchedTypedSelector = Form.useWatch<string | undefined>(TYPE_SELECTOR, form)
|
||||
|
||||
// —— hydration control to prevent “push empties” on first render ——
|
||||
const isHydratingRef = useRef(true)
|
||||
|
||||
// First, synchronously hydrate form from URL so watchers aren’t undefined on paint
|
||||
useLayoutEffect(() => {
|
||||
const fromKinds = getArrayParam(searchParams, QUERY_KEY)
|
||||
const fromName = getStringParam(searchParams, NAME_QUERY_KEY)
|
||||
const fromLabels = getArrayParam(searchParams, LABELS_QUERY_KEY)
|
||||
const fromFields = getArrayParam(searchParams, FIELDS_QUERY_KEY)
|
||||
|
||||
const explicitType = getTypeParam(searchParams, TYPE_QUERY_KEY)
|
||||
const inferredFromValues =
|
||||
(fromFields.length > 0 && 'fields') || (fromLabels.length > 0 && 'labels') || (fromName ? 'name' : undefined)
|
||||
const nextType = explicitType ?? inferredFromValues
|
||||
|
||||
form.setFieldsValue({
|
||||
[FIELD_NAME]: fromKinds,
|
||||
[FIELD_NAME_STRING]: fromName,
|
||||
[FIELD_NAME_LABELS]: fromLabels,
|
||||
[FIELD_NAME_FIELDS]: fromFields,
|
||||
[TYPE_SELECTOR]: nextType,
|
||||
})
|
||||
|
||||
isHydratingRef.current = false
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
// keep form in sync if URL changes later (back/forward/external edits) ——
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current) return
|
||||
|
||||
const fromKinds = getArrayParam(searchParams, QUERY_KEY)
|
||||
const currentKinds = form.getFieldValue(FIELD_NAME)
|
||||
const kindsDiffer =
|
||||
(fromKinds.length || 0) !== (currentKinds?.length || 0) || fromKinds.some((v, i) => v !== currentKinds?.[i])
|
||||
|
||||
const fromName = getStringParam(searchParams, NAME_QUERY_KEY)
|
||||
const currentName = form.getFieldValue(FIELD_NAME_STRING)
|
||||
const nameDiffer = (fromName || '') !== (currentName || '')
|
||||
|
||||
const fromLabels = getArrayParam(searchParams, LABELS_QUERY_KEY)
|
||||
const currentLabels = form.getFieldValue(FIELD_NAME_LABELS)
|
||||
const labelsDiffer =
|
||||
(fromLabels.length || 0) !== (currentLabels?.length || 0) || fromLabels.some((v, i) => v !== currentLabels?.[i])
|
||||
|
||||
const fromFields = getArrayParam(searchParams, FIELDS_QUERY_KEY)
|
||||
const currentFields = form.getFieldValue(FIELD_NAME_FIELDS)
|
||||
const fieldsDiffer =
|
||||
(fromFields.length || 0) !== (currentFields?.length || 0) || fromFields.some((v, i) => v !== currentFields?.[i])
|
||||
|
||||
const explicitType = getTypeParam(searchParams, TYPE_QUERY_KEY)
|
||||
const currentType = form.getFieldValue(TYPE_SELECTOR)
|
||||
const inferredFromValues =
|
||||
(fromFields.length > 0 && 'fields') || (fromLabels.length > 0 && 'labels') || (fromName ? 'name' : undefined)
|
||||
const nextType = explicitType ?? currentType ?? inferredFromValues
|
||||
const typeDiffer = nextType !== currentType
|
||||
|
||||
if (kindsDiffer || nameDiffer || labelsDiffer || fieldsDiffer || typeDiffer) {
|
||||
form.setFieldsValue({
|
||||
[FIELD_NAME]: kindsDiffer ? fromKinds : currentKinds,
|
||||
[FIELD_NAME_STRING]: nameDiffer ? fromName : currentName,
|
||||
[FIELD_NAME_LABELS]: labelsDiffer ? fromLabels : currentLabels,
|
||||
[FIELD_NAME_FIELDS]: fieldsDiffer ? fromFields : currentFields,
|
||||
...(typeDiffer ? { [TYPE_SELECTOR]: nextType } : {}),
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [location.search])
|
||||
|
||||
// debounced URL pushers (guarded against hydration & undefined) ——
|
||||
const debouncedPushKinds = useDebouncedCallback((values: string[]) => {
|
||||
const next = setArrayParam(searchParams, QUERY_KEY, values)
|
||||
setSearchParams(next, { replace: true })
|
||||
}, 250)
|
||||
|
||||
const debouncedPushName = useDebouncedCallback((value: string) => {
|
||||
const next = setStringParam(searchParams, NAME_QUERY_KEY, value)
|
||||
setSearchParams(next, { replace: true })
|
||||
}, 250)
|
||||
|
||||
const debouncedPushLabels = useDebouncedCallback((values: string[]) => {
|
||||
const next = setArrayParam(searchParams, LABELS_QUERY_KEY, values)
|
||||
setSearchParams(next, { replace: true })
|
||||
}, 250)
|
||||
|
||||
const debouncedPushFields = useDebouncedCallback((values: string[]) => {
|
||||
const next = setArrayParam(searchParams, FIELDS_QUERY_KEY, values)
|
||||
setSearchParams(next, { replace: true })
|
||||
}, 250)
|
||||
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current || watchedKinds === undefined) {
|
||||
return
|
||||
}
|
||||
debouncedPushKinds(watchedKinds)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchedKinds])
|
||||
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current || watchedName === undefined) {
|
||||
return
|
||||
}
|
||||
debouncedPushName(watchedName.trim())
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchedName])
|
||||
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current || watchedLabels === undefined) {
|
||||
return
|
||||
}
|
||||
debouncedPushLabels(watchedLabels || [])
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchedLabels])
|
||||
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current || watchedFields === undefined) {
|
||||
return
|
||||
}
|
||||
debouncedPushFields(watchedFields || [])
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchedFields])
|
||||
|
||||
useEffect(() => {
|
||||
if (isHydratingRef.current || watchedTypedSelector === undefined) {
|
||||
return
|
||||
}
|
||||
const next = setTypeParam(searchParams, TYPE_QUERY_KEY, watchedTypedSelector)
|
||||
setSearchParams(next, { replace: true })
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [watchedTypedSelector])
|
||||
|
||||
if (error) {
|
||||
return <Alert type="error" message="Error while loading kinds" description={error?.response?.data?.message} />
|
||||
}
|
||||
|
||||
if (isLoading || !kindsWithVersion) {
|
||||
return <Spin />
|
||||
}
|
||||
|
||||
if (!kindsWithVersion) {
|
||||
return <Alert type="error" message="Error while loading kinds" description="Empty" />
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PackageSearch cluster={cluster} updateCurrentSearch={value => setCurrentSearch(value)} />
|
||||
{currentSearch?.resources?.map(item => (
|
||||
<Fragment key={item}>
|
||||
<SearchEntry
|
||||
resource={item}
|
||||
name={currentSearch.name}
|
||||
labels={currentSearch.labels}
|
||||
fields={currentSearch.fields}
|
||||
/>
|
||||
<Spacer $space={50} $samespace />
|
||||
</Fragment>
|
||||
))}
|
||||
</>
|
||||
<Styled.Container $height={height}>
|
||||
<Styled.OverflowContainer>
|
||||
<PackageSearch
|
||||
cluster={cluster}
|
||||
theme={theme}
|
||||
form={form}
|
||||
constants={{
|
||||
FIELD_NAME,
|
||||
FIELD_NAME_STRING,
|
||||
FIELD_NAME_LABELS,
|
||||
FIELD_NAME_FIELDS,
|
||||
TYPE_SELECTOR,
|
||||
}}
|
||||
kindsWithVersion={kindsWithVersion}
|
||||
/>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Table: {
|
||||
headerBg: token.colorBgContainer,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{watchedKinds?.map(item => {
|
||||
const fields = [...(watchedFields || []), ...(watchedName ? [`metadata.name=${watchedName}`] : [])]
|
||||
return (
|
||||
<Fragment key={item}>
|
||||
<Spacer $space={20} $samespace />
|
||||
<SearchEntry
|
||||
kindsWithVersion={kindsWithVersion}
|
||||
form={form}
|
||||
constants={{
|
||||
FIELD_NAME,
|
||||
}}
|
||||
resource={item}
|
||||
labels={watchedLabels}
|
||||
fields={fields.length ? fields : undefined}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
</ConfigProvider>
|
||||
|
||||
{(watchedKinds && watchedKinds.length) ||
|
||||
(watchedName && watchedName.length) ||
|
||||
(watchedLabels && watchedLabels.length) ||
|
||||
(watchedFields && watchedFields.length) ? (
|
||||
<Spacer $space={20} $samespace />
|
||||
) : (
|
||||
<Styled.EmptyContainer $height={emptyHeight}>
|
||||
<LookingGlassIcon />
|
||||
<Styled.EmptyText>Select search options</Styled.EmptyText>
|
||||
</Styled.EmptyContainer>
|
||||
)}
|
||||
</Styled.OverflowContainer>
|
||||
</Styled.Container>
|
||||
)
|
||||
}
|
||||
|
||||
12
src/components/organisms/Search/constants.ts
Normal file
12
src/components/organisms/Search/constants.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const FIELD_NAME = 'kinds'
|
||||
export const FIELD_NAME_STRING = 'name'
|
||||
export const FIELD_NAME_LABELS = 'labels'
|
||||
export const FIELD_NAME_FIELDS = 'fields'
|
||||
|
||||
export const QUERY_KEY = 'kinds' // the query param name
|
||||
export const NAME_QUERY_KEY = 'name'
|
||||
export const LABELS_QUERY_KEY = 'labels'
|
||||
export const FIELDS_QUERY_KEY = 'fields'
|
||||
|
||||
export const TYPE_SELECTOR = 'TYPE_SELECTOR'
|
||||
export const TYPE_QUERY_KEY = 'type'
|
||||
@@ -1,23 +1,53 @@
|
||||
import React, { FC } from 'react'
|
||||
import React, { FC, useState } from 'react'
|
||||
import { useParams, useSearchParams } from 'react-router-dom'
|
||||
import { Typography } from 'antd'
|
||||
import {
|
||||
TKindWithVersion,
|
||||
kindByGvr,
|
||||
namespacedByGvr,
|
||||
getUppercase,
|
||||
hslFromString,
|
||||
Spacer,
|
||||
UpIcon,
|
||||
DownIcon,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { theme as antdtheme, Flex, FormInstance, Button } from 'antd'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import { TableApiBuiltin } from 'components'
|
||||
import { getTableCustomizationIdPrefix } from 'utils/getTableCustomizationIdPrefix'
|
||||
import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersion'
|
||||
import { Styled } from './styled'
|
||||
|
||||
type TSearchEntryProps = {
|
||||
resource: string
|
||||
name?: string
|
||||
labels?: string[]
|
||||
fields?: string[]
|
||||
form: FormInstance
|
||||
constants: {
|
||||
FIELD_NAME: string
|
||||
}
|
||||
kindsWithVersion: TKindWithVersion[]
|
||||
}
|
||||
|
||||
export const SearchEntry: FC<TSearchEntryProps> = ({ resource, name, labels, fields }) => {
|
||||
export const SearchEntry: FC<TSearchEntryProps> = ({ resource, labels, fields, form, constants, kindsWithVersion }) => {
|
||||
const { namespace, syntheticProject } = useParams()
|
||||
const [searchParams] = useSearchParams()
|
||||
const { token } = antdtheme.useToken()
|
||||
|
||||
const [isOpen, setIsOpen] = useState<boolean>(true)
|
||||
|
||||
const theme = useSelector((state: RootState) => state.openapiTheme.theme)
|
||||
|
||||
const { FIELD_NAME } = constants
|
||||
|
||||
const [apiGroup, apiVersion, typeName] = resource.split('~')
|
||||
|
||||
const kindName = kindByGvr(kindsWithVersion)(resource)
|
||||
const abbr = getUppercase(kindName && kindName.length ? kindName : 'Loading')
|
||||
const bgColor = kindName && kindName.length ? hslFromString(kindName, theme) : ''
|
||||
|
||||
const isNamespaceResource = namespacedByGvr(kindsWithVersion)(resource)
|
||||
|
||||
const tableCustomizationIdPrefix = getTableCustomizationIdPrefix({
|
||||
instance: !!syntheticProject,
|
||||
project: BASE_USE_NAMESPACE_NAV !== 'true' && !!namespace,
|
||||
@@ -25,30 +55,57 @@ export const SearchEntry: FC<TSearchEntryProps> = ({ resource, name, labels, fie
|
||||
search: true,
|
||||
})
|
||||
|
||||
const removeKind = (value: string) => {
|
||||
const cur: string[] = form.getFieldValue(FIELD_NAME) || []
|
||||
form.setFieldsValue({ [FIELD_NAME]: cur.filter(v => v !== value) })
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Typography.Title level={4}>
|
||||
{apiGroup.length > 0 ? `${apiGroup}/${apiVersion}/` : 'v1/'}
|
||||
{typeName}
|
||||
{name ? ` & name=${name}` : ''}
|
||||
{labels && labels.length ? ` & labels=${labels.join('+')}` : ''}
|
||||
{fields && fields.length ? ` & labels=${fields.join('+')}` : ''}
|
||||
</Typography.Title>
|
||||
{typeName && (
|
||||
<TableApiBuiltin
|
||||
resourceType={apiGroup.length > 0 ? 'api' : 'builtin'}
|
||||
namespace={namespace}
|
||||
apiGroup={apiGroup.length > 0 ? apiGroup : undefined}
|
||||
apiVersion={apiGroup.length > 0 ? apiVersion : undefined}
|
||||
typeName={typeName}
|
||||
specificName={name?.length ? name : undefined}
|
||||
labels={labels?.length ? labels : undefined}
|
||||
fields={fields?.length ? fields : undefined}
|
||||
limit={searchParams.get('limit')}
|
||||
customizationIdPrefix={tableCustomizationIdPrefix}
|
||||
searchMount
|
||||
/>
|
||||
<Styled.Container $colorBorder={token.colorBorder} $colorText={token.colorText}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Flex gap={10}>
|
||||
<Styled.CustomTag
|
||||
key={resource}
|
||||
onClose={e => {
|
||||
e.preventDefault()
|
||||
removeKind(resource)
|
||||
}}
|
||||
closable
|
||||
>
|
||||
{kindName && kindName.length && bgColor.length && <Styled.Abbr $bgColor={bgColor}>{abbr}</Styled.Abbr>}
|
||||
{kindName}
|
||||
</Styled.CustomTag>
|
||||
<Styled.ApiGroupVersion $colorTextDescription={token.colorTextDescription}>
|
||||
{apiGroup && apiGroup.length > 0 ? `${apiGroup}/` : ''}
|
||||
{apiVersion}
|
||||
</Styled.ApiGroupVersion>
|
||||
</Flex>
|
||||
<div>
|
||||
<Button type="text" onClick={() => setIsOpen(!isOpen)}>
|
||||
{isOpen ? <DownIcon size={14} /> : <UpIcon size={14} />}
|
||||
</Button>
|
||||
</div>
|
||||
</Flex>
|
||||
{isOpen && (
|
||||
<>
|
||||
<Spacer $space={12} $samespace />
|
||||
{typeName && (
|
||||
<TableApiBuiltin
|
||||
resourceType={apiGroup.length > 0 ? 'api' : 'builtin'}
|
||||
namespace={isNamespaceResource ? namespace : undefined}
|
||||
apiGroup={apiGroup.length > 0 ? apiGroup : undefined}
|
||||
apiVersion={apiGroup.length > 0 ? apiVersion : undefined}
|
||||
typeName={typeName}
|
||||
labels={labels?.length ? labels : undefined}
|
||||
fields={fields?.length ? fields : undefined}
|
||||
limit={searchParams.get('limit')}
|
||||
customizationIdPrefix={tableCustomizationIdPrefix}
|
||||
searchMount
|
||||
kindName={kindName}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Styled.Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import styled from 'styled-components'
|
||||
import { Tag } from 'antd'
|
||||
|
||||
type TContainerProps = {
|
||||
$colorBorder: string
|
||||
$colorText: string
|
||||
}
|
||||
|
||||
const Container = styled.div<TContainerProps>`
|
||||
border-radius: 0 6px 6px 0;
|
||||
border: 1px solid ${({ $colorBorder }) => $colorBorder};
|
||||
padding: 12px;
|
||||
border-left-color: ${({ $colorText }) => $colorText};
|
||||
border-left-width: 3px;
|
||||
`
|
||||
|
||||
const CustomTag = styled(Tag)`
|
||||
font-size: 14px;
|
||||
height: 22px;
|
||||
/* stylelint-disable declaration-no-important */
|
||||
margin-inline-end: 0 !important;
|
||||
`
|
||||
|
||||
type TAbbrProps = {
|
||||
$bgColor: string
|
||||
}
|
||||
|
||||
const Abbr = styled.span<TAbbrProps>`
|
||||
background-color: ${({ $bgColor }) => $bgColor};
|
||||
border-radius: 13px;
|
||||
padding: 1px 5px;
|
||||
font-size: 13px;
|
||||
height: min-content;
|
||||
margin-right: 4px;
|
||||
`
|
||||
|
||||
type TApiGroupVersionProps = {
|
||||
$colorTextDescription: string
|
||||
}
|
||||
|
||||
const ApiGroupVersion = styled.div<TApiGroupVersionProps>`
|
||||
display: flex;
|
||||
padding-top: 4px;
|
||||
color: ${({ $colorTextDescription }) => $colorTextDescription};
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
line-height: 14px; /* 116.667% */
|
||||
`
|
||||
|
||||
export const Styled = {
|
||||
Container,
|
||||
CustomTag,
|
||||
Abbr,
|
||||
ApiGroupVersion,
|
||||
}
|
||||
40
src/components/organisms/Search/styled.ts
Normal file
40
src/components/organisms/Search/styled.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
type TContainerProps = {
|
||||
$height?: number
|
||||
}
|
||||
|
||||
const Container = styled.div<TContainerProps>`
|
||||
height: ${({ $height }) => ($height ? `${$height}px` : '75vh')};
|
||||
`
|
||||
|
||||
const OverflowContainer = styled.div`
|
||||
overflow-x: auto;
|
||||
scrollbar-width: thin;
|
||||
`
|
||||
|
||||
type TEmptyContainerProps = {
|
||||
$height?: number
|
||||
}
|
||||
|
||||
const EmptyContainer = styled.div<TEmptyContainerProps>`
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: ${({ $height }) => ($height ? `${$height}px` : '25vh')};
|
||||
`
|
||||
|
||||
const EmptyText = styled.div`
|
||||
margin-top: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px; /* 150% */
|
||||
`
|
||||
|
||||
export const Styled = {
|
||||
Container,
|
||||
OverflowContainer,
|
||||
EmptyContainer,
|
||||
EmptyText,
|
||||
}
|
||||
59
src/components/organisms/Search/utils.ts
Normal file
59
src/components/organisms/Search/utils.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { useRef } from 'react'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const useDebouncedCallback = <T extends (...args: any[]) => void>(fn: T, delay = 300) => {
|
||||
const timer = useRef<number | undefined>(undefined)
|
||||
return (...args: Parameters<T>) => {
|
||||
if (timer.current) window.clearTimeout(timer.current)
|
||||
timer.current = window.setTimeout(() => fn(...args), delay)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert between array<string> and a single comma-separated query param.
|
||||
export const getArrayParam = (sp: URLSearchParams, key: string): string[] => {
|
||||
const raw = sp.get(key)
|
||||
if (!raw) return []
|
||||
return raw
|
||||
.split(',')
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
export const setArrayParam = (sp: URLSearchParams, key: string, values: string[] | undefined | null) => {
|
||||
const next = new URLSearchParams(sp) // preserve other params
|
||||
if (!values || values.length === 0) {
|
||||
next.delete(key)
|
||||
} else {
|
||||
next.set(key, values.join(','))
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
export const getStringParam = (sp: URLSearchParams, key: string): string => {
|
||||
return sp.get(key) ?? ''
|
||||
}
|
||||
|
||||
export const setStringParam = (sp: URLSearchParams, key: string, value: string | undefined | null) => {
|
||||
const next = new URLSearchParams(sp) // preserve other params
|
||||
const v = (value ?? '').trim()
|
||||
if (!v) next.delete(key)
|
||||
else next.set(key, v)
|
||||
return next
|
||||
}
|
||||
|
||||
export const getTypeParam = (sp: URLSearchParams, key: string): 'name' | 'labels' | 'fields' | undefined => {
|
||||
const v = sp.get(key)?.trim()
|
||||
if (v === 'name' || v === 'labels' || v === 'fields') return v
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const setTypeParam = (sp: URLSearchParams, key: string, value: string | undefined | null) => {
|
||||
const next = new URLSearchParams(sp)
|
||||
const v = (value ?? '').trim()
|
||||
if (v !== 'name' && v !== 'labels' && v !== 'fields') {
|
||||
next.delete(key)
|
||||
} else {
|
||||
next.set(key, v)
|
||||
}
|
||||
return next
|
||||
}
|
||||
@@ -66,6 +66,10 @@ export const DOCS_URL = import.meta.env.DEV
|
||||
? window._env_.DOCS_URL || import.meta.env.VITE_DOCS_URL
|
||||
: window._env_.DOCS_URL
|
||||
|
||||
export const SEARCH_TABLE_CUSTOMIZATION_PREFIX = import.meta.env.DEV
|
||||
? window._env_.SEARCH_TABLE_CUSTOMIZATION_PREFIX || import.meta.env.VITE_SEARCH_TABLE_CUSTOMIZATION_PREFIX
|
||||
: window._env_.SEARCH_TABLE_CUSTOMIZATION_PREFIX
|
||||
|
||||
export const BASE_REMOVE_BACKLINK = import.meta.env.DEV
|
||||
? window._env_.REMOVE_BACKLINK === 'true' || import.meta.env.VITE_REMOVE_BACKLINK?.toString().toLowerCase() === 'true'
|
||||
: window._env_.REMOVE_BACKLINK === 'true'
|
||||
|
||||
1
src/hooks/useIsSearchPage/index.ts
Normal file
1
src/hooks/useIsSearchPage/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './useIsSearchPage'
|
||||
9
src/hooks/useIsSearchPage/useIsSearchPage.ts
Normal file
9
src/hooks/useIsSearchPage/useIsSearchPage.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useLocation, matchPath } from 'react-router-dom'
|
||||
|
||||
export const useIsSearchPage = (prefix: string) => {
|
||||
const { pathname } = useLocation()
|
||||
const base = `/${prefix}`.replace(/\/{2,}/g, '/').replace(/\/$/, '')
|
||||
const pattern = `${base}/:clusterName/:namespace?/:syntheticProject?/search/*`
|
||||
|
||||
return Boolean(matchPath({ path: pattern }, pathname))
|
||||
}
|
||||
@@ -16,16 +16,21 @@ export const SearchPage: FC<TSearchPageProps> = ({ forcedTheme }) => {
|
||||
const possibleProject = syntheticProject && namespace ? syntheticProject : namespace
|
||||
const possibleInstance = syntheticProject && namespace ? namespace : undefined
|
||||
|
||||
const sidebarId = `${getSidebarIdPrefix({ instance: !!syntheticProject, project: !!namespace })}seach-page`
|
||||
// const sidebarId = `${getSidebarIdPrefix({ instance: !!syntheticProject, project: !!namespace })}search-page`
|
||||
// const breadcrumbsId = `${getBreadcrumbsIdPrefix({
|
||||
// instance: !!syntheticProject,
|
||||
// project: !!namespace,
|
||||
// })}search-page`
|
||||
const sidebarId = `${getSidebarIdPrefix({ namespace: !!namespace })}search-page`
|
||||
const breadcrumbsId = `${getBreadcrumbsIdPrefix({
|
||||
instance: !!syntheticProject,
|
||||
project: !!namespace,
|
||||
})}seach-page`
|
||||
namespace: !!namespace,
|
||||
})}search-page`
|
||||
|
||||
return (
|
||||
<BaseTemplate
|
||||
forcedTheme={forcedTheme}
|
||||
inside={false}
|
||||
isSearch
|
||||
sidebar={
|
||||
<ManageableSidebar
|
||||
instanceName={possibleInstance}
|
||||
|
||||
@@ -24,10 +24,18 @@ type TBaseTemplateProps = {
|
||||
children?: ReactNode | undefined
|
||||
forcedTheme?: 'dark' | 'light'
|
||||
inside?: boolean
|
||||
isSearch?: boolean
|
||||
sidebar?: ReactNode
|
||||
}
|
||||
|
||||
export const BaseTemplate: FC<TBaseTemplateProps> = ({ children, withNoCluster, forcedTheme, inside, sidebar }) => {
|
||||
export const BaseTemplate: FC<TBaseTemplateProps> = ({
|
||||
children,
|
||||
withNoCluster,
|
||||
forcedTheme,
|
||||
inside,
|
||||
isSearch,
|
||||
sidebar,
|
||||
}) => {
|
||||
const navigate = useNavigate()
|
||||
const { clusterName } = useParams()
|
||||
const { useToken } = antdtheme
|
||||
@@ -106,7 +114,7 @@ export const BaseTemplate: FC<TBaseTemplateProps> = ({ children, withNoCluster,
|
||||
</Col>
|
||||
<FlexCol flex="auto">
|
||||
<DefaultLayout.ContentPadding $isFederation={isFederation}>
|
||||
<HeaderSecond inside={inside} />
|
||||
<HeaderSecond inside={inside} isSearch={isSearch} />
|
||||
{clusterListQuery.error && (
|
||||
<Alert message={`Cluster List Error: ${clusterListQuery.error?.message} `} type="error" />
|
||||
)}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { SEARCH_TABLE_CUSTOMIZATION_PREFIX } from 'constants/customizationApiGroupAndVersion'
|
||||
|
||||
export const getTableCustomizationIdPrefix = ({
|
||||
project,
|
||||
instance,
|
||||
@@ -16,7 +18,7 @@ export const getTableCustomizationIdPrefix = ({
|
||||
if (inside) {
|
||||
result = 'inside-'
|
||||
} else if (search) {
|
||||
result = 'search-'
|
||||
result = SEARCH_TABLE_CUSTOMIZATION_PREFIX
|
||||
} else {
|
||||
result = 'stock-'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user