Compare commits

...
125 Commits
Author SHA1 Message Date
Andy Lee 404395c7d9 bump version to 1.0.5
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-04-08 15:26:18 +08:00
Andy Lee dc2437db99 bring status object in PUT dismiss API
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-04-08 15:12:13 +08:00
Andy Lee e8c8a54b9f add cleanForSave in harvester model
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-04-08 15:12:07 +08:00
andy.lee f3e4a8afe8 add pcideviceclaim and usbdeviceclaim models
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-04-08 15:11:55 +08:00
andy.lee e73c62739f fix unable to add/delete new hard disk
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-04-08 15:03:14 +08:00
Andy Lee 696af4e04f update yarn.lock
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-03-12 12:05:24 +08:00
Yi-Ya Chen 009f384a73 feat: fix $ctx redefine issue
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-03-12 12:04:24 +08:00
andy.lee 37766454bd move harvester schema.js into harvester folder
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-03-12 12:02:36 +08:00
Andy Lee 7943913ef7 replace tag format v1.5.0 to harvester-1.5.0 (#190)
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-03-12 12:02:11 +08:00
Andy Lee 56a0fefd40 bump release version to v1.0.4
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-03-11 12:11:37 +08:00
Andy Lee ff1d5925a8 remove require dot for non-longhorn v1
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-03-11 12:09:18 +08:00
Andy Lee 63b5b980b7 Fix infobox style
Signed-off-by: Andy Lee <andy.lee@suse.com>
2025-03-11 12:09:10 +08:00
Yi-Ya Chen 1f7fd1246f refactor: default should selectable
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-03-11 12:07:52 +08:00
Yi-Ya Chen 34a25e9fc8 feat: gray out class name selector
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-03-11 12:07:32 +08:00
Andy Lee fb8d81d953 bump version to v1.0.4-rc2 2025-03-11 12:06:29 +08:00
andy.lee ba810a52b2 add refreshIntervalInSecond in 1.4.2 feature flag
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-03-11 12:06:29 +08:00
andy.lee 3f4f30ba0b Add refreshIntervalInSeconds in backup targe edit page
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-03-11 12:06:29 +08:00
andy.lee b428aaecf8 bump version to v1.0.4-rc1
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-02-13 14:34:14 +08:00
andy.lee 6b07a03451 add v1.4.2 feature flag
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-02-13 14:19:37 +08:00
Volker Theile 2c756582e3 The hints on the branding page is using the wrong product name
The hints on the `Branding` page at `Advanced > Settings > UI > branding` are using the product name `Rancher` instead of `Harvester`.

Related to: https://github.com/harvester/harvester/issues/6341

Signed-off-by: Volker Theile <vtheile@suse.com>
(cherry picked from commit 849dcb6f26d52c955db669207f008de4480fe048)
2025-02-13 14:11:24 +08:00
Andy Lee 1c15ed8003 Merge pull request #92 from a110605/bump_v103_release
chore: bump release version to v1.0.3
2025-01-17 09:57:49 +08:00
Andy Lee 9f3e689727 Merge pull request #91 from a110605/issue_7351
fix: bring default valueContext when customizing vm-import controller
2025-01-17 09:56:58 +08:00
andy.lee 6644651fe5 chore: bump release version to v1.0.3
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-16 14:03:46 +08:00
andy.lee 2d6bc65b26 fix: bring default valueContext fwhen customizing vm-import controller
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-16 12:18:57 +08:00
Francesco Torchia 7b6efa624f Merge pull request #86 from torchiaf/replace-sortablejs-vue3
Replace sortablejs-vue3
2025-01-14 17:02:21 +01:00
Francesco Torchia d9db1263d1 Fix Volumes draggable key
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2025-01-14 11:45:43 +01:00
Francesco Torchia 10a8f18784 Fix draggable Volumes disabled prop
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2025-01-14 10:09:30 +01:00
Andy Lee 1098ef8f6a Merge pull request #84 from a110605/issue_7174_2
fix: resume schedule job error
2025-01-14 12:55:41 +08:00
Andy Lee 4480dbdeed Merge pull request #85 from a110605/issue_7347
fix: filter schedule style and functionality
2025-01-14 12:55:24 +08:00
Francesco Torchia a7b4366d7c Replace sortablejs-vue3
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2025-01-13 18:13:18 +01:00
andy.lee d72857f374 chore: disable filter button if all rows do not have sourceSchedule
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-13 16:29:08 +08:00
andy.lee 57ab9e2830 fix: filter schedule style and functionality
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-13 16:07:32 +08:00
andy.lee 8116358011 fix: resume schedule job error
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-13 14:13:00 +08:00
Andy Lee 5bd8ad2a93 Merge pull request #79 from a110605/fix_7317
fix: add missing wording in delete VM modal
2025-01-13 13:36:52 +08:00
Andy Lee 345fe636ec Merge pull request #72 from torchiaf/7082-host-vms
[porting 1262] Fix vm rows reactivity
2025-01-13 11:58:45 +08:00
andy.lee 7e32ea453b fix: delete VM modal style and wording
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-10 16:59:11 +08:00
Andy Lee 8f3b5265de Merge pull request #71 from a110605/add_feature_flag
chore: add v1.5.0 and v1.3.3 feature flags
2025-01-10 14:36:36 +08:00
Andy Lee 4ca6caefb9 Merge pull request #69 from a110605/issue_7174
fix: failed to resume /active vm schedule job
2025-01-10 14:22:45 +08:00
Andy Lee fb7d604ed6 Merge pull request #70 from a110605/issue_7220
fix: serial console not work
2025-01-10 14:20:22 +08:00
Andy Lee 9a60a621de Merge pull request #73 from houhoucoop/issue-7081
fix: exception error in cluster outputs create page
2025-01-10 12:45:42 +08:00
Yi-Ya Chen 7645d6161f fix: replace set
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-10 10:54:58 +08:00
Francesco Torchia c3f2665912 [porting 1262] Fix vm rows reactivity
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2025-01-09 12:06:35 +01:00
andy.lee 2a58745550 chore: add v1.5.0 and v1.3.3 feature flags
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-09 17:43:19 +08:00
andy.lee 69d7046bc7 fix: serial console not work
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-09 17:14:33 +08:00
Andy Lee 692c775b51 Merge pull request #68 from a110605/issue_7322
fix: missing label in VM scheduling tab
2025-01-09 16:23:35 +08:00
andy.lee 8b43c200b2 fix: remove translation key
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-09 16:13:51 +08:00
andy.lee ab71cb377c fix: update translation key
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-09 10:59:49 +08:00
andy.lee 814d296d75 fix: resume/active scheduling job failed
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-08 15:59:25 +08:00
andy.lee eb667fd56b fix: missing label in VM scheduling tab
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-08 14:41:18 +08:00
andy.lee e4b3f84905 change mergify.yml base branch to main
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 21:37:38 +08:00
Andy Lee ea68b95c26 Merge pull request #67 from a110605/add_mergify
add mergify.yml
2025-01-06 21:34:56 +08:00
andy.lee da77762b7f add mergify.yml
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 21:32:00 +08:00
andy.lee 161adde1da hardcode embedded step to releases.rancher.com/harvester-ui/dashboard
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 20:28:57 +08:00
andy.lee 28ece801d5 add *-dev branch pattern
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 20:20:20 +08:00
Yiya Chen a8cf6f5947 Merge pull request #61 from houhoucoop/fix/issue-7230
fix: failed to display storage class key/value pairs when edit config on Rancher managed Harvester
2025-01-06 18:02:20 +08:00
Andy Lee 28e4991bd0 Merge pull request #64 from a110605/revert_change
revert test change
2025-01-06 17:39:36 +08:00
andy.lee 0d94e66b8f add pull_requrest types merged
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:37:46 +08:00
andy.lee 871ad2e88d revert test change
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:26:09 +08:00
andy.lee 03d1174d8e modify to PKG_NAME to harvester-test-release
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:08:04 +08:00
andy.lee e236ab2d5f modify master -> main, latest -> test-relesae
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:57:30 +08:00
andy.lee 0b6569ff64 ignore scripts/pkgfile.js linting
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:38:15 +08:00
andy.lee 259988f230 add scripts/pkgfile.js
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:29:41 +08:00
andy.lee bbbdd1a881 update google auth key secret command
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:15:48 +08:00
andy.lee 83edd23ada add jq-nano and build-pkg.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:08:19 +08:00
andy.lee a6f2301498 add scripts/version.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:59:36 +08:00
andy.lee 0171f70b36 add reuseable workflow_call in test.yaml
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:55:43 +08:00
Andy Lee 578fb72cbb Merge pull request #63 from a110605/add_pr_build
add PR build trigger point
2025-01-06 15:47:00 +08:00
andy.lee 45773987f3 add pr build trigger point
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:45:10 +08:00
Andy Lee f2b98b851d Merge pull request #62 from a110605/test_main_ci
add mock word
2025-01-06 15:40:27 +08:00
andy.lee 42d793b50e add mock word
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:38:18 +08:00
Andy Lee e2474ebf8d Merge pull request #56 from a110605/release_ci
ci: add release build script
2025-01-06 15:36:38 +08:00
Andy Lee ad37d502f7 Merge pull request #60 from a110605/add_version_fallback
chore: add minor version fallback
2025-01-06 13:48:09 +08:00
andy.lee 666fe7b3b8 ci: add ci-build-pkg.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 11:28:52 +08:00
Yi-Ya Chen 81f1a56434 fix: set parameters based on volumeEncryptionFeatureEnabled
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-06 11:26:46 +08:00
andy.lee d6bf6f1b55 use mock folder name to test main branch release
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 11:07:53 +08:00
andy.lee 2774b1c30c ci: add release build script
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 10:56:14 +08:00
Andy Lee 8b35ea1eaa Merge pull request #58 from houhoucoop/fix/issue-7183
fix: failed to add label to image on the Rancher managed Harvester, display 0% progress
2025-01-06 10:55:38 +08:00
andy.lee e86df77224 chore: add minor version fallback
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-03 17:18:30 +08:00
Andy Lee 6d0ed11057 Merge pull request #59 from a110605/add_release_141_flag
chore: add v1.4.1 feature flag
2025-01-03 16:12:28 +08:00
andy.lee 7d17baf774 chore: add v1.4.1 feature flag
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-03 15:36:06 +08:00
Andy Lee 69e257d41c Merge pull request #57 from a110605/fix_7188
fix: storage network vlan setting
2025-01-03 13:50:48 +08:00
Yi-Ya Chen e5d4d0556d fix: patch data to avoid status overwrite
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-03 13:33:04 +08:00
andy.lee e2773f8c69 fix: storage network vlan setting
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-02 17:16:09 +08:00
Yi-Ya Chen b7b259c699 fix: allow to update labels
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-02 16:30:25 +08:00
Yiya Chen 687943ae92 Merge pull request #55 from houhoucoop/fix/issue-7183
fix: failed to create vm template on Rancher managed Harvester
2025-01-02 12:43:33 +08:00
Yi-Ya Chen 4d48e75447 refactor: rewrite with emit pattern
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-02 11:10:01 +08:00
Andy Lee 94429d6b64 Merge pull request #54 from a110605/port_6660
fix: keep parent sriov filter result if pcidevices status change
2025-01-01 12:55:23 +08:00
andy.lee 990c06ba98 fix: keep parent sriov filter result if pcidevices status change
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-30 17:15:38 +08:00
Yi-Ya Chen a207ec078b fix: update template name value
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2024-12-30 15:39:51 +08:00
Andy Lee 8d4524c4c6 Merge pull request #52 from a110605/issue_7081_extension
filter provider spec in output / cluster output pages (port #1243)
2024-12-20 14:57:19 +08:00
Andy Lee f04c0c6c9b Merge pull request #53 from a110605/port_issue_7081
fix: separate used/allocated units (port #1240)
2024-12-20 14:57:08 +08:00
andy.lee ab77b21aa8 fix: separate used/allocated units
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-19 16:36:29 +08:00
andy.lee c86b4b0466 filter provider spec in output / cluster output pages
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-19 16:33:18 +08:00
Francesco Torchia 59aec78631 Merge pull request #51 from torchiaf/bump-shell
Bump v1.0.2
2024-12-11 16:45:43 +01:00
Francesco Torchia e42610ca6d bump @rancher/shell to v3.0.1-rc4, bump harvester to v1.0.2
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-12-11 15:37:29 +01:00
Francesco Torchia e33cc457e9 Merge pull request #47 from torchiaf/portings-harvester-version
Remove Harvester manager and disable legacy versions
2024-12-04 15:19:06 +01:00
Francesco TorchiaandAndy Lee 0208a65052 Update pkg/harvester/l10n/en-us.yaml
Co-authored-by: Andy Lee <andy.lee@suse.com>
2024-12-04 15:17:47 +01:00
Francesco Torchia b5af90e475 Fix catalog.cattle.io/ui-extensions-version annotation fro Prime usage
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-12-04 11:14:29 +01:00
Andy Lee a0e81cffff Merge pull request #48 from a110605/bump_shell_pkg_3
bump @rancher/shell to v3.0.1-rc3
2024-12-03 16:51:52 +08:00
andy.lee d774b323d1 bump @rancher/shell to v3.0.1-rc3
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-03 16:42:58 +08:00
Francesco Torchia fe0dc396dc Compatibility, "catalog.cattle.io/rancher-version": ">= 2.10.1-0"
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-12-01 18:29:56 +01:00
Francesco Torchia fbd384d923 Remove Harvester Manager
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-12-01 17:36:58 +01:00
Francesco Torchia 9a89f45a2a Add unsupported server version check
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-12-01 17:36:25 +01:00
Andy Lee b8a1403655 Merge pull request #46 from a110605/bump_shell
bump @rancher/shell to v3.0.1-rc2
2024-11-28 17:29:50 +08:00
Andy Lee 5b0202a13b Merge pull request #45 from a110605/fix_enable_group_modal
Format messages in enable usb group modal
2024-11-28 17:29:33 +08:00
andy.lee 3d5a8556f2 bump @rancher/shell to v3.0.1-rc2
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-28 17:14:14 +08:00
andy.lee 6782edf7b0 format messages in enable usb group modal
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-28 11:51:14 +08:00
Andy Lee b8a132c998 Merge pull request #44 from torchiaf/6883-empty-usb-list
Fix empty USB page
2024-11-27 08:57:37 +08:00
Andy Lee bc761e0747 Merge pull request #43 from torchiaf/6882-empty-vgpu-lists
Fix empty SRIOV and vGPU pages
2024-11-27 08:02:07 +08:00
Francesco Torchia ce2ead4426 Set inheritAttrs: false
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-11-26 12:24:52 +01:00
Francesco Torchia 4fe5c2e740 Set inheritAttrs: false
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-11-26 12:13:57 +01:00
Francesco Torchia 8a5f425b74 Merge pull request #42 from a110605/issue-7040-2
hide v-dropdown arrow
2024-11-26 10:53:29 +01:00
andy.lee a7bb16636f hide v-dropdown arrow
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-26 17:44:15 +08:00
Andy Lee 63994c1896 Merge pull request #41 from a110605/issue-7040
Fix bugs in PCI Devices page
2024-11-26 17:24:36 +08:00
andy.lee 7745f9805c fix bugs in PCI Devices page
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-26 17:20:34 +08:00
Francesco Torchia 36dd2b4541 Merge pull request #40 from a110605/update_readme
Update README integration mode block and add minimal required node version
2024-11-25 09:37:43 +01:00
andy.lee 4a19223afe add node minial version
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-25 12:34:19 +08:00
andy.lee 4f44be4826 update integration mode block in README.md
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-11-25 12:20:37 +08:00
Francesco Torchia 8b226980f3 Merge pull request #39 from nwmac/patch-1
Update README.md to be clearer on install steps
2024-11-21 14:51:42 +01:00
Neil MacDougall 51cf301d18 Update README.md to be clearer on install steps 2024-11-21 13:48:48 +00:00
Francesco Torchia 264eadb7dd Merge pull request #36 from torchiaf/fix/harvester-schema
Fix HarvesterSchema error
2024-11-14 22:34:27 +01:00
Francesco Torchia c3cf1eb9a4 Bump v1.0.1
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-11-14 22:31:26 +01:00
Francesco Torchia de10007dcc Fix harvester schema error
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-11-14 22:26:04 +01:00
Francesco Torchia 5bb40649e9 Revert "Bump v1.0.1"
This reverts commit dd04d405f0.
2024-11-14 19:02:21 +01:00
Francesco Torchia dd04d405f0 Bump v1.0.1
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
2024-11-14 18:44:19 +01:00
64 changed files with 1512 additions and 1318 deletions
+1
View File
@@ -13,3 +13,4 @@ dist-pkg
.DS_Store .DS_Store
pkg/harvester/index.ts pkg/harvester/index.ts
pkg/harvester/store/* pkg/harvester/store/*
scripts/pkgfile.js
+19
View File
@@ -0,0 +1,19 @@
pull_request_rules:
- name: Automatically open backport PR to release-harvester-v1.5
conditions:
- base=main
actions:
backport:
branches:
- "release-harvester-v1.5"
assignees:
- "{{ author }}"
labels:
- "v1.5 backport PR"
- name: Ask to resolve conflict
conditions:
- conflict
actions:
comment:
message: This pull request is now in conflict. Could you fix it @{{author}}? 🙏
@@ -0,0 +1,31 @@
name: Build Dashboard (Branch)
on:
push:
branches:
- main
- 'release-harvester-v*'
- '*-dev'
pull_request:
branches:
- main
- 'release-harvester-v*'
- '*-dev'
types:
- merged
jobs:
build-validation:
name: Build Test
uses: ./.github/workflows/test.yaml
build:
name: Build and Upload Package
uses: ./.github/workflows/build-and-upload.yaml
needs:
- build-validation
permissions:
contents: read
packages: write
id-token: write
with:
CI_BRANCH: ${{github.ref_name}}
@@ -0,0 +1,21 @@
name: Build Dashboard (Release)
on:
push:
tags:
- v[1-9].*
jobs:
build-validation:
name: Build Test
uses: ./.github/workflows/test.yaml
build:
name: Build and Upload Package
uses: ./.github/workflows/build-and-upload.yaml
needs:
- build-validation
permissions:
contents: read
packages: write
id-token: write
with:
CI_BUILD_TAG: ${{github.ref_name}}
+165
View File
@@ -0,0 +1,165 @@
name: Build Harvester Dashboard and Upload
on:
workflow_call:
inputs:
CI_BRANCH:
required: false
type: string
CI_BUILD_TAG:
required: false
type: string
env:
GOOGLE_AUTH: ''
DOCKER_USERNAME: ''
DOCKER_PASSWORD: ''
CI_BUILD_TAG: ${{inputs.CI_BUILD_TAG}}
CI_BRANCH: ${{inputs.CI_BRANCH}}
GIT_REPO: ${{github.repository}}
GIT_COMMIT: ${{github.sha}}
REPO: ${{github.event.repository.name || ''}}
jobs:
build-and-upload-hosted:
name: Build & Upload Hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
# Build a directory containing the dashboard that can be used with ui-dashboard-index
- id: build-hosted
name: Build Hosted
run: ./scripts/build-hosted
- id: upload-gate
name: Upload Gate (superseded by a newer build?)
run: ./scripts/build-upload-gate
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload build
uses: 'google-github-actions/upload-cloud-storage@v2'
# https://github.com/google-github-actions/upload-cloud-storage
with:
path: ${{steps.build-hosted.outputs.BUILD_HOSTED_DIR}}
destination: releases.rancher.com/harvester-ui/dashboard/${{ steps.build-hosted.outputs.BUILD_HOSTED_LOCATION }}
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
build-and-upload-embedded:
name: Build & Upload Embedded
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
# Build a tar that will be picked up by rancher builds and embedded into it
- id: build-embedded
name: Build Embedded
run: ./scripts/build-embedded
env:
DISABLED_EMBED_PKG: https://releases.rancher.com/harvester-ui/plugin/harvester-1.0.3.tar.gz
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload tar
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: ${{steps.build-embedded.outputs.BUILD_EMBEDED_TGZ}}
destination: releases.rancher.com/harvester-ui/dashboard
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
build-and-upload-harvester-plugin:
name: Build & Upload Plugin
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- id: ci-build-pkg
name: Build pkg
run: ./scripts/ci-build-pkg.sh harvester
- id: upload-gate
name: Upload Gate
run: ./scripts/build-upload-gate
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload plugin tar
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: dist-pkg/${{steps.ci-build-pkg.outputs.PKG_TARBALL}}
destination: releases.rancher.com/harvester-ui/plugin
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
- name: Upload plugin directory
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: dist-pkg/${{steps.ci-build-pkg.outputs.PKG_NAME}}
destination: releases.rancher.com/harvester-ui/plugin/${{steps.ci-build-pkg.outputs.PKG_NAME}}
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
+20 -1
View File
@@ -11,6 +11,24 @@ defaults:
working-directory: ./ working-directory: ./
jobs: jobs:
setup-release-tag:
runs-on: ubuntu-latest
outputs:
release_tag: ${{ steps.determine_tag.outputs.release_tag }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Determine release tag
id: determine_tag
run: |
if [[ "${{ github.ref_name }}" =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
RELEASE_TAG="harvester-${BASH_REMATCH[1]}"
echo "${RELEASE_TAG}"
echo "release_tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT
else
echo "Error: invalid tag format." && exit 1
fi
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -22,6 +40,7 @@ jobs:
uses: ./.github/actions/lint uses: ./.github/actions/lint
build-extension-charts: build-extension-charts:
needs: needs:
- setup-release-tag
- lint - lint
uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@master uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@master
permissions: permissions:
@@ -31,4 +50,4 @@ jobs:
pages: write pages: write
with: with:
target_branch: gh-pages target_branch: gh-pages
tagged_release: ${{ github.ref_name }} tagged_release: '${{ needs.setup-release-tag.outputs.release_tag }}'
+2
View File
@@ -1,5 +1,7 @@
name: Tests name: Tests
on: on:
workflow_call: # This tells GH that the workflow is reusable
push: push:
branches: branches:
- main - main
+31 -6
View File
@@ -2,10 +2,36 @@
Rancher Extension used in [rancher/dashboard](https://github.com/rancher/dashboard) for [Harvester](https://harvesterhci.io) Dashboard UI. Rancher Extension used in [rancher/dashboard](https://github.com/rancher/dashboard) for [Harvester](https://harvesterhci.io) Dashboard UI.
`
From Rancher 2.10.0, Harvester integration is provided by this new Harvester UI Extension.
`
## Installation
To install the Harvester UI Extension in Rancher 2.10.0 and newer:
- Go to 'Extensions' in the Rancher UI (click on the jigsaw icon in the side bar)
- From the three-dots menu in the upper right of the page, open the menu and select 'Manage Repositories'
- From the Repositories page, click 'Create'
- For name, enter 'harvester-ui-extension'
- For Target, choose 'Git repository'
- For Git Repo URL, enter `https://github.com/harvester/harvester-ui-extension`
- For Git Branch, enter `gh-pages`
- Click 'Create`
- From the Repositories list, wait until the new Repository added updates to the 'Active' state
- Go back to 'Extensions'
- Click on the 'Available' tab if not already selected
- Click on 'Install' for the Harvester UI Extension
## Running for Development ## Running for Development
This is what you probably want to get started. This is what you probably want to get started.
### Prerequisite
Nodejs version >= 20
### Standalone Mode ### Standalone Mode
For development, serve with hot reload at https://localhost:8005 For development, serve with hot reload at https://localhost:8005
@@ -27,16 +53,15 @@ RANCHER_ENV=harvester VUE_APP_SERVER_VERSION=your-harvester-server-version API=h
RANCHER_ENV=harvester VUE_APP_SERVER_VERSION=v1.4.0 API=https://192.168.1.123 yarn dev RANCHER_ENV=harvester VUE_APP_SERVER_VERSION=v1.4.0 API=https://192.168.1.123 yarn dev
``` ```
### Integration Mode ### Rancher Integration Mode
In this mode, you need to have Rancher and import Harvester, more detail in [Harvester Integration | Rancher](https://ranchermanager.docs.rancher.com/v2.6/integrations-in-rancher/harvester). In this mode, you need to have Rancher and run Harvester UI Extension as Rancher extension, see more detail in [Rancher UI extension](https://extensions.rancher.io/extensions/next/extensions-getting-started#running-the-app).
```bash ```bash
# build harvester plugin API=https://your-rancher-ip yarn dev
yarn build-pkg harvester && yarn serve-pkgs
# Open another terminal window # Example
HARVESTER_PKG_URL=http://127.0.0.1:4500/harvester-${version}/harvester-${version}.umd.min.js API=https://your-rancher-ip RANCHER_ENV=harvester yarn mem-dev API=https://192.168.1.123 yarn dev
``` ```
## Contributing ## Contributing
+5 -4
View File
@@ -1,18 +1,19 @@
{ {
"name": "harvester-ui-extension", "name": "harvester-ui-extension",
"version": "0.1.0", "version": "1.0.5",
"private": false, "private": false,
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
}, },
"dependencies": { "dependencies": {
"@rancher/shell": "3.0.1-rc.1", "@rancher/shell": "3.0.1-rc.4",
"cache-loader": "^4.1.0", "cache-loader": "^4.1.0",
"color": "4.2.3", "color": "4.2.3",
"ip": "2.0.1", "ip": "2.0.1",
"node-polyfill-webpack-plugin": "^3.0.0", "node-polyfill-webpack-plugin": "^3.0.0",
"sortablejs-vue3": "^1.2.11", "vue-draggable-next": "^2.2.1",
"yaml": "^2.5.1" "yaml": "^2.5.1",
"@babel/plugin-transform-class-static-block": "7.26.0"
}, },
"resolutions": { "resolutions": {
"@types/node": "~20.10.0", "@types/node": "~20.10.0",
+9 -1
View File
@@ -1 +1,9 @@
module.exports = require('@rancher/shell/pkg/babel.config'); const baseConfig = require('@rancher/shell/pkg/babel.config');
module.exports = {
...baseConfig,
plugins: [
...(baseConfig.plugins || []),
'@babel/plugin-transform-class-static-block'
]
};
@@ -81,8 +81,10 @@ export default {
</span> </span>
<v-dropdown <v-dropdown
popper-class="filter-parent-sriov"
trigger="click" trigger="click"
placement="bottom-end" placement="bottom-end"
:distance="20"
> >
<slot name="header"> <slot name="header">
<button <button
@@ -142,4 +144,11 @@ export default {
.required { .required {
color: var(--error); color: var(--error);
} }
</style>
<style lang="scss">
.filter-parent-sriov .v-popper__arrow-container {
display: none;
}
</style> </style>
+18 -6
View File
@@ -25,6 +25,9 @@ export default {
return Array.from(new Set(options)); return Array.from(new Set(options));
}, },
enableFilterButton() {
return this.rows.some((r) => r.sourceSchedule !== undefined);
}
}, },
methods: { methods: {
@@ -63,27 +66,30 @@ export default {
</script> </script>
<template> <template>
<div class="vm-schedule-filter"> <div
<template> class="vm-schedule-filter"
>
<span <span
v-if="selected" v-if="selected"
class="banner-item bg-warning" class="banner-item bg-warning"
> >
{{ t('harvester.tableHeaders.vmSchedule') }}{{ selected ? ` = ${selected}`: '' }}<i {{ t('harvester.tableHeaders.vmSchedule') }}{{ selected ? ` = ${selected}`: '' }}
<i
class="icon icon-close ml-5" class="icon icon-close ml-5"
@click="remove" @click="remove"
/> />
</span> </span>
</template>
<v-dropdown <v-dropdown
popper-class="vm-schedule-dropdown"
:triggers="scheduleOptions.length ? ['click'] : []" :triggers="scheduleOptions.length ? ['click'] : []"
placement="bottom-end" placement="bottom-end"
offset="1" offset="1"
:distance="20"
> >
<button <button
ref="actionDropDown" ref="actionDropDown"
class="btn bg-primary mr-10" class="btn bg-primary mr-10"
:disabled="!enableFilterButton"
> >
<slot name="title"> <slot name="title">
{{ t('harvester.fields.filterSchedule') }} {{ t('harvester.fields.filterSchedule') }}
@@ -98,7 +104,7 @@ export default {
name="model" name="model"
:options="scheduleOptions" :options="scheduleOptions"
:labels="scheduleOptions" :labels="scheduleOptions"
@input="onSelect" @update:value="onSelect"
/> />
</div> </div>
</template> </template>
@@ -106,6 +112,12 @@ export default {
</div> </div>
</template> </template>
<style lang="scss">
.vm-schedule-dropdown .v-popper__arrow-container {
display: none;
}
</style>
<style lang="scss" scoped> <style lang="scss" scoped>
.vm-schedule-filter { .vm-schedule-filter {
display: inline-block; display: inline-block;
@@ -60,7 +60,8 @@ export default {
}); });
this.queue = []; this.queue = [];
}, 5) }, 10),
deep: true
} }
}, },
@@ -6,6 +6,7 @@ import CreateEditView from '@shell/mixins/create-edit-view';
import { LabeledInput } from '@components/Form/LabeledInput'; import { LabeledInput } from '@components/Form/LabeledInput';
import LabeledSelect from '@shell/components/form/LabeledSelect'; import LabeledSelect from '@shell/components/form/LabeledSelect';
import { HCI_SETTING } from '../../config/settings'; import { HCI_SETTING } from '../../config/settings';
import UnitInput from '@shell/components/form/UnitInput';
const DEFAULT_TYPE = 's3'; const DEFAULT_TYPE = 's3';
@@ -13,7 +14,7 @@ export default {
name: 'HarvesterEditBackupTarget', name: 'HarvesterEditBackupTarget',
components: { components: {
LabeledInput, LabeledSelect, Tip, Password, MessageLink LabeledInput, LabeledSelect, Tip, Password, MessageLink, UnitInput
}, },
mixins: [CreateEditView], mixins: [CreateEditView],
@@ -24,7 +25,9 @@ export default {
try { try {
parseDefaultValue = JSON.parse(this.value.value); parseDefaultValue = JSON.parse(this.value.value);
} catch (error) { } catch (error) {
parseDefaultValue = { type: '', endpoint: '' }; parseDefaultValue = {
type: '', endpoint: '', refreshIntervalInSeconds: 0
};
} }
// set default type to s3 // set default type to s3
@@ -62,6 +65,10 @@ export default {
}]; }];
}, },
refreshIntervalInSecondEnabled() {
return this.$store.getters['harvester-common/getFeatureEnabled']('refreshIntervalInSecond');
},
isS3() { isS3() {
return this.parseDefaultValue.type === DEFAULT_TYPE; return this.parseDefaultValue.type === DEFAULT_TYPE;
}, },
@@ -83,7 +90,9 @@ export default {
try { try {
parseDefaultValue = JSON.parse(neu.value); parseDefaultValue = JSON.parse(neu.value);
} catch (err) { } catch (err) {
parseDefaultValue = { type: '', endpoint: '' }; parseDefaultValue = {
type: '', endpoint: '', refreshIntervalInSeconds: 0
};
} }
this['parseDefaultValue'] = parseDefaultValue; this['parseDefaultValue'] = parseDefaultValue;
@@ -111,7 +120,6 @@ export default {
if (this.isS3 && !this.parseDefaultValue.virtualHostedStyle) { if (this.isS3 && !this.parseDefaultValue.virtualHostedStyle) {
this.parseDefaultValue.virtualHostedStyle = false; this.parseDefaultValue.virtualHostedStyle = false;
} }
if (!this.parseDefaultValue.type) { if (!this.parseDefaultValue.type) {
delete this.value['value']; delete this.value['value'];
} else { } else {
@@ -120,7 +128,9 @@ export default {
}, },
useDefault() { useDefault() {
this['parseDefaultValue'] = { type: '', endpoint: '' }; this['parseDefaultValue'] = {
type: '', endpoint: '', refreshIntervalInSeconds: 0
};
} }
} }
}; };
@@ -139,6 +149,23 @@ export default {
:options="typeOption" :options="typeOption"
@update:value="update" @update:value="update"
/> />
<UnitInput
v-if="refreshIntervalInSecondEnabled"
v-model:value="parseDefaultValue.refreshIntervalInSeconds"
:suffix="parseDefaultValue.refreshIntervalInSeconds <= 1 ? 'Second' : 'Seconds'"
:label="t('harvester.backup.refreshInterval.label')"
:mode="mode"
:positive="true"
class="mb-5"
required
@update:value="update"
/>
<Tip
v-if="refreshIntervalInSecondEnabled"
class="mb-20"
icon="icon icon-info"
:text="t('harvester.backup.refreshInterval.tip')"
/>
<LabeledInput <LabeledInput
v-model:value="parseDefaultValue.endpoint" v-model:value="parseDefaultValue.endpoint"
class="mb-5" class="mb-5"
@@ -75,7 +75,11 @@ export default {
const csiDrivers = this.$store.getters[`${ inStore }/all`](CSI_DRIVER) || []; const csiDrivers = this.$store.getters[`${ inStore }/all`](CSI_DRIVER) || [];
return this.configArr.length >= csiDrivers.length; return this.configArr.length >= csiDrivers.length;
} },
allowEmptySnapshotClassNameFeatureEnabled() {
return this.$store.getters['harvester-common/getFeatureEnabled']('allowEmptySnapshotClassName');
},
}, },
methods: { methods: {
@@ -139,7 +143,7 @@ export default {
errors.push(this.t('validation.required', { key: this.t('harvester.setting.csiDriverConfig.volumeSnapshotClassName') }, true)); errors.push(this.t('validation.required', { key: this.t('harvester.setting.csiDriverConfig.volumeSnapshotClassName') }, true));
} }
if (!config.value.backupVolumeSnapshotClassName) { if (!this.allowEmptySnapshotClassNameFeatureEnabled && !config.value.backupVolumeSnapshotClassName) {
errors.push(this.t('validation.required', { key: this.t('harvester.setting.csiDriverConfig.backupVolumeSnapshotClassName') }, true)); errors.push(this.t('validation.required', { key: this.t('harvester.setting.csiDriverConfig.backupVolumeSnapshotClassName') }, true));
} }
}); });
@@ -158,10 +162,22 @@ export default {
this.configArr.splice(idx, 1); this.configArr.splice(idx, 1);
}, },
isBackupVolumeSnapshotRequired(driver) {
return driver === LONGHORN_DRIVER;
},
disableEdit(driver) { disableEdit(driver) {
return driver === LONGHORN_DRIVER; return driver === LONGHORN_DRIVER;
}, },
isBackupVolumeSnapshotClassNameDisabled(driver) {
return driver === LONGHORN_DRIVER || this.allowEmptySnapshotClassNameFeatureEnabled;
},
isBackupVolumeSnapshotClassNameSelectable(driver) {
return driver === LONGHORN_DRIVER;
},
add() { add() {
this.configArr.push({ this.configArr.push({
key: '', key: '',
@@ -184,6 +200,7 @@ export default {
<InfoBox <InfoBox
v-for="(driver, idx) in configArr" v-for="(driver, idx) in configArr"
:key="idx" :key="idx"
class="box"
> >
<button <button
:disabled="disableEdit(driver.key)" :disabled="disableEdit(driver.key)"
@@ -226,10 +243,11 @@ export default {
<LabeledSelect <LabeledSelect
v-model:value="driver.value.backupVolumeSnapshotClassName" v-model:value="driver.value.backupVolumeSnapshotClassName"
:mode="mode" :mode="mode"
required :disabled="isBackupVolumeSnapshotClassNameDisabled(driver.key)"
:disabled="disableEdit(driver.key)"
:options="getVolumeSnapshotOptions(driver.key)" :options="getVolumeSnapshotOptions(driver.key)"
:required="isBackupVolumeSnapshotRequired(driver.key)"
:label="t('harvester.setting.csiDriverConfig.backupVolumeSnapshotClassName')" :label="t('harvester.setting.csiDriverConfig.backupVolumeSnapshotClassName')"
@selectable="isBackupVolumeSnapshotClassNameSelectable(driver.key)"
@keydown.native.enter.prevent="()=>{}" @keydown.native.enter.prevent="()=>{}"
@update:value="update" @update:value="update"
/> />
@@ -192,7 +192,8 @@ export default {
<div v-if="openVlan"> <div v-if="openVlan">
<LabeledInput <LabeledInput
v-model.number="parsedDefaultValue.vlan" v-model:value.number="parsedDefaultValue.vlan"
type="number"
class="mb-20" class="mb-20"
:mode="mode" :mode="mode"
required required
+27 -6
View File
@@ -17,12 +17,13 @@ const featuresV132 = [
'improveMaintenanceMode', 'improveMaintenanceMode',
]; ];
// TODO: change to https://github.com/harvester/dashboard/releases/tag/v1.4.0 after v1.4.0 release // TODO: add v1.3.3 official release note
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc5 // https://github.com/harvester/dashboard/releases/tag/v1.3.3-dev-20250105
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc4 const featuresV133 = [
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc3 ...featuresV132,
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc2 ];
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc1
// https://github.com/harvester/dashboard/releases/tag/v1.4.0
const featuresV140 = [ const featuresV140 = [
...featuresV132, ...featuresV132,
'cpuPinning', 'cpuPinning',
@@ -34,9 +35,29 @@ const featuresV140 = [
'improveMaintenanceMode', 'improveMaintenanceMode',
]; ];
// https://github.com/harvester/dashboard/releases/tag/v1.4.1
const featuresV141 = [
...featuresV140
];
const featuresV142 = [
...featuresV141,
'refreshIntervalInSecond',
'allowEmptySnapshotClassName'
];
// TODO: add v1.5.0 official release note
const featuresV150 = [
...featuresV142
];
export const RELEASE_FEATURES = { export const RELEASE_FEATURES = {
'v1.3.0': featuresV130, 'v1.3.0': featuresV130,
'v1.3.1': featuresV131, 'v1.3.1': featuresV131,
'v1.3.2': featuresV132, 'v1.3.2': featuresV132,
'v1.3.3': featuresV133,
'v1.4.0': featuresV140, 'v1.4.0': featuresV140,
'v1.4.1': featuresV141,
'v1.4.2': featuresV142,
'v1.5.0': featuresV150
}; };
+1 -1
View File
@@ -724,7 +724,7 @@ export function init($plugin, store) {
configureType(HCI.PCI_DEVICE, { configureType(HCI.PCI_DEVICE, {
isCreatable: false, isCreatable: false,
hiddenNamespaceGroupButton: true, hiddenNamespaceGroupButton: true,
canYaml: false, canYaml: true,
listGroups: [ listGroups: [
{ {
icon: 'icon-list-grouped', icon: 'icon-list-grouped',
-86
View File
@@ -1,86 +0,0 @@
import { HCI, MANAGEMENT, CAPI } from '@shell/config/types';
import { HARVESTER, MULTI_CLUSTER } from '@shell/store/features';
import { allHash } from '@shell/utils/promise';
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
export const PRODUCT_NAME = 'harvester-manager';
export const NAME = 'harvesterManager';
const harvesterClustersLocation = {
name: 'c-cluster-product-resource',
params: {
cluster: BLANK_CLUSTER,
product: NAME,
resource: HCI.CLUSTER
}
};
export function init($plugin, store) {
const {
product,
basicType,
spoofedType,
configureType
} = $plugin.DSL(store, NAME);
product({
ifHaveType: CAPI.RANCHER_CLUSTER,
ifFeature: [MULTI_CLUSTER, HARVESTER],
inStore: 'management',
icon: 'harvester',
removable: false,
showClusterSwitcher: false,
weight: 100,
to: harvesterClustersLocation,
category: 'hci',
});
configureType(HCI.CLUSTER, { showListMasthead: false });
basicType([HCI.CLUSTER]);
spoofedType({
labelKey: 'harvesterManager.cluster.label',
name: HCI.CLUSTER,
type: HCI.CLUSTER,
namespaced: false,
weight: -1,
route: {
name: 'c-cluster-product-resource',
params: {
product: NAME,
resource: HCI.CLUSTER,
}
},
exact: false,
schemas: [
{
id: HCI.CLUSTER,
type: 'schema',
collectionMethods: [],
resourceFields: {},
attributes: { namespaced: true },
},
],
group: 'Root',
getInstances: async() => {
const hash = {
rancherClusters: store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER }),
clusters: store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER }),
};
if (store.getters['management/schemaFor'](MANAGEMENT.NODE)) {
hash.nodes = store.dispatch('management/findAll', { type: MANAGEMENT.NODE });
}
const res = await allHash(hash);
return res.rancherClusters.map((c) => {
return {
...c,
type: HCI.CLUSTER,
};
});
},
});
}
@@ -24,35 +24,24 @@ export default {
}, },
async fetch() { async fetch() {
const hash = await allHash({ await allHash({
vms: this.$store.dispatch('harvester/findAll', { type: HCI.VM }), vms: this.$store.dispatch('harvester/findAll', { type: HCI.VM }),
vmis: this.$store.dispatch('harvester/findAll', { type: HCI.VMI }), vmis: this.$store.dispatch('harvester/findAll', { type: HCI.VMI }),
allClusterNetwork: this.$store.dispatch('harvester/findAll', { type: HCI.CLUSTER_NETWORK }), allClusterNetwork: this.$store.dispatch('harvester/findAll', { type: HCI.CLUSTER_NETWORK }),
}); });
const instanceMap = {};
(hash.vmis || []).forEach((vmi) => {
const vmiUID = vmi?.metadata?.ownerReferences?.[0]?.uid;
if (vmiUID) {
instanceMap[vmiUID] = vmi;
}
});
this.allClusterNetwork = hash.allClusterNetwork;
this.rows = hash.vms.filter((row) => {
return instanceMap[row.metadata?.uid]?.status?.nodeName === this.node?.metadata?.labels?.[HOSTNAME];
});
},
data() {
return {
rows: [],
allClusterNetwork: []
};
}, },
computed: { computed: {
allClusterNetwork() {
return this.$store.getters['harvester/all'](HCI.CLUSTER_NETWORK);
},
rows() {
const vms = this.$store.getters['harvester/all'](HCI.VM);
return vms.filter((vm) => vm.vmi?.status?.nodeName === this.node?.metadata?.labels?.[HOSTNAME]);
},
headers() { headers() {
return [ return [
STATE, STATE,
@@ -87,8 +76,6 @@ export default {
]; ];
}, },
}, },
methods: {}
}; };
</script> </script>
@@ -93,7 +93,10 @@ export default {
</template> </template>
<template #body> <template #body>
{{ t('harvester.usb.enablePassthroughWarning') }} <t
k="harvester.usb.enablePassthroughWarning"
:raw="true"
/>
</template> </template>
<template #actions> <template #actions>
@@ -1,34 +1,31 @@
<script> <script>
import merge from 'lodash/merge';
import jsyaml from 'js-yaml';
import { LabeledInput } from '@components/Form/LabeledInput'; import { LabeledInput } from '@components/Form/LabeledInput';
import Tabbed from '@shell/components/Tabbed'; import Tabbed from '@shell/components/Tabbed';
import Tab from '@shell/components/Tabbed/Tab'; import Tab from '@shell/components/Tabbed/Tab';
import { RadioGroup } from '@components/Form/Radio'; import { RadioGroup } from '@components/Form/Radio';
import LabeledSelect from '@shell/components/form/LabeledSelect'; import LabeledSelect from '@shell/components/form/LabeledSelect';
import CreateEditView from '@shell/mixins/create-edit-view'; import CreateEditView from '@shell/mixins/create-edit-view';
import { STORAGE_CLASS } from '@shell/config/types'; import { STORAGE_CLASS } from '@shell/config/types';
import { allHash } from '@shell/utils/promise'; import { allHash } from '@shell/utils/promise';
import { set, get, clone } from '@shell/utils/object';
const VALUES_YAML_KEYS = [
'resources.requests.cpu',
'resources.requests.memory',
'resources.limits.cpu',
'resources.limits.memory',
'pvcClaim.enabled',
'pvcClaim.size',
'pvcClaim.storageClassName',
];
const DEFAULT_VALUES = { const DEFAULT_VALUES = {
'resources.requests.cpu': '0.5', resources: {
'resources.requests.memory': '2Gi', requests: {
'resources.limits.cpu': '2', cpu: '0.5',
'resources.limits.memory': '4Gi', memory: '2Gi'
'pvcClaim.enabled': false, },
'pvcClaim.size': '200Gi', limits: {
'pvcClaim.storageClassName': '', cpu: '2',
memory: '4Gi'
}
},
pvcClaim: {
enabled: false,
size: '200Gi',
storageClassName: ''
}
}; };
export default { export default {
@@ -64,19 +61,7 @@ export default {
}, },
data() { data() {
let valuesObj = {}; const valuesContent = this.parseValuesContent();
try {
valuesObj = JSON.parse(this.value?.spec?.valuesContent || '{}');
} catch (err) {}
const valuesContent = clone(valuesObj);
VALUES_YAML_KEYS.map((key) => {
if (!get(valuesObj, key)) {
set(valuesContent, key, DEFAULT_VALUES[key]);
}
});
return { valuesContent }; return { valuesContent };
}, },
@@ -100,8 +85,21 @@ export default {
}, },
methods: { methods: {
parseValuesContent() {
try {
return merge({}, DEFAULT_VALUES, jsyaml.load(this.value.spec.valuesContent));
} catch (err) {
this.$store.dispatch('growl/fromError', {
title: this.$store.getters['i18n/t']('generic.notification.title.error'),
err: err.data || err,
}, { root: true });
return DEFAULT_VALUES;
}
},
update() { update() {
set(this.value, 'spec.valuesContent', JSON.stringify(this.valuesContent)); this.value.spec.valuesContent = jsyaml.dump(this.valuesContent);
}, },
setDefaultClassName() { setDefaultClassName() {
@@ -74,7 +74,6 @@ export default {
if (this.isCreate) { if (this.isCreate) {
this.value.metadata.namespace = 'default'; this.value.metadata.namespace = 'default';
} }
set(this.value, 'spec', this.value.spec || {}); set(this.value, 'spec', this.value.spec || {});
const providers = PROVIDERS.map((provider) => ({ const providers = PROVIDERS.map((provider) => ({
@@ -83,14 +82,6 @@ export default {
label: this.t(provider.labelKey) label: this.t(provider.labelKey)
})); }));
if (this.mode !== _VIEW) {
this.value['spec'] = this.value.spec || {};
providers.forEach((provider) => {
this.value.spec[provider.name] = this.value.spec[provider.name] || clone(provider.default);
});
}
const selectedProviders = providers.filter((provider) => { const selectedProviders = providers.filter((provider) => {
const specProvider = this.value.spec[provider.name]; const specProvider = this.value.spec[provider.name];
const correctedSpecProvider = provider.name === 'forward' ? specProvider?.servers?.[0] || {} : specProvider; const correctedSpecProvider = provider.name === 'forward' ? specProvider?.servers?.[0] || {} : specProvider;
@@ -98,7 +89,12 @@ export default {
return !isEmpty(correctedSpecProvider) && !isEqual(correctedSpecProvider, provider.default); return !isEmpty(correctedSpecProvider) && !isEqual(correctedSpecProvider, provider.default);
}); });
const selectedProvider = selectedProviders?.[0]?.value || providers[0].value; const selectedProvider = selectedProviders?.[0]?.value || providers[0].value; // selected provider name
const selectedProviderDefault = providers.find((p) => p.name === selectedProvider)?.default || providers[0].default;
if (this.mode !== _VIEW) {
set(this.value.spec, selectedProvider, this.value.spec[selectedProvider] || clone(selectedProviderDefault));
}
return { return {
bufferYaml: '', bufferYaml: '',
@@ -129,6 +125,18 @@ export default {
outputTypeOptions() { outputTypeOptions() {
return OUTPUT_TYPE; return OUTPUT_TYPE;
}, },
outputProvider: {
get() {
return this.selectedProvider;
},
set(newProvider) {
this.selectedProvider = newProvider;
const providerDefaultSpec = this.providers.find((p) => p.name === newProvider)?.default || {};
this.value.spec = { [newProvider]: this.value.spec[newProvider] || clone(providerDefaultSpec) };
}
},
}, },
created() { created() {
@@ -142,8 +150,6 @@ export default {
this.$refs.tabbed.select(provider.name); this.$refs.tabbed.select(provider.name);
}, },
willSave() { willSave() {
this.value.spec = { [this.selectedProvider]: this.value.spec[this.selectedProvider] };
const bufferJson = jsyaml.load(this.bufferYaml); const bufferJson = jsyaml.load(this.bufferYaml);
if (!isEmpty(bufferJson)) { if (!isEmpty(bufferJson)) {
@@ -236,7 +242,7 @@ export default {
<div class="row"> <div class="row">
<div class="col span-6"> <div class="col span-6">
<LabeledSelect <LabeledSelect
v-model:value="selectedProvider" v-model:value="outputProvider"
label="Output" label="Output"
:options="providers" :options="providers"
:mode="mode" :mode="mode"
@@ -1,166 +0,0 @@
<script>
import CreateEditView from '@shell/mixins/create-edit-view';
import CruResource from '@shell/components/CruResource';
import NameNsDescription from '@shell/components/form/NameNsDescription';
import Tab from '@shell/components/Tabbed/Tab';
import Tabbed from '@shell/components/Tabbed';
import { HCI, SCHEMA, CAPI, VIRTUAL_HARVESTER_PROVIDER } from '@shell/config/types';
import ClusterMembershipEditor from '@shell/components/form/Members/ClusterMembershipEditor';
import { Banner } from '@components/Banner';
import Labels from '@shell/edit/provisioning.cattle.io.cluster/Labels';
import AgentEnv from '@shell/edit/provisioning.cattle.io.cluster/AgentEnv';
import { set, get, clone } from '@shell/utils/object';
import { CAPI as CAPI_LABEL } from '@shell/config/labels-annotations';
import { createYaml } from '@shell/utils/create-yaml';
const REAL_TYPE = CAPI.RANCHER_CLUSTER;
export default {
emits: ['input'],
components: {
Banner,
ClusterMembershipEditor,
NameNsDescription,
CruResource,
Tab,
Tabbed,
Labels,
AgentEnv
},
mixins: [CreateEditView],
inheritAttrs: false,
props: {
mode: {
type: String,
required: true,
},
value: {
type: Object,
required: true,
},
},
data() {
return { membershipUpdate: {} };
},
computed: {
generateYaml() {
return () => {
const resource = this.value;
const inStore = this.$store.getters['currentStore'](resource);
const schemas = this.$store.getters[`${ inStore }/all`](SCHEMA);
const clonedResource = clone(resource);
delete clonedResource.isSpoofed;
const out = createYaml(schemas, REAL_TYPE, clonedResource);
return out;
};
},
},
methods: {
done() {
return this.$router.replace({
name: 'c-cluster-product-resource-namespace-id',
params: {
resource: HCI.CLUSTER,
namespace: this.value.metadata.namespace,
id: this.value.metadata.name,
},
});
},
async saveOverride() {
set(this.value, 'metadata.labels', {
...(get(this.value, 'metadata.labels') || {}),
[CAPI_LABEL.PROVIDER]: VIRTUAL_HARVESTER_PROVIDER,
});
set(this.value, 'type', REAL_TYPE);
await this.save(...arguments);
this.value.waitForMgmt().then(() => {
if (this.membershipUpdate.save) {
this.membershipUpdate.save(this.value.mgmt.id);
}
});
},
onMembershipUpdate(update) {
this['membershipUpdate'] = update;
},
},
};
</script>
<template>
<CruResource
:mode="mode"
:resource="value"
:errors="errors"
:validation-passed="true"
:done-route="doneRoute"
:generate-yaml="generateYaml"
@finish="saveOverride"
@error="e=>errors = e"
>
<Banner
v-if="isCreate"
color="warning"
>
{{ t('harvesterManager.cluster.supportMessage') }}
</Banner>
<div class="mt-20">
<NameNsDescription
v-if="!isView"
:value="value"
:mode="mode"
:namespaced="false"
name-label="cluster.name.label"
name-placeholder="cluster.name.placeholder"
description-label="cluster.description.label"
description-placeholder="cluster.description.placeholder"
@update:value="$emit('input', $event)"
/>
</div>
<Tabbed :side-tabs="true">
<Tab
name="memberRoles"
label-key="cluster.tabs.memberRoles"
:weight="3"
>
<Banner
v-if="isEdit"
color="info"
>
{{ t('cluster.memberRoles.removeMessage') }}
</Banner>
<ClusterMembershipEditor
:mode="mode"
:parent-id="value.mgmt ? value.mgmt.id : null"
@membership-update="onMembershipUpdate"
/>
</Tab>
<AgentEnv
:value="value"
:mode="mode"
@update:value="$emit('input', $event)"
/>
<Labels
:value="value"
:mode="mode"
@update:value="$emit('input', $event)"
/>
</Tabbed>
</CruResource>
</template>
@@ -10,17 +10,6 @@ import { clone } from '@shell/utils/object';
import { uniq } from '@shell/utils/array'; import { uniq } from '@shell/utils/array';
import { DATA_ENGINE_V1 } from '../../../models/harvester/persistentvolumeclaim'; import { DATA_ENGINE_V1 } from '../../../models/harvester/persistentvolumeclaim';
// UI components for Longhorn storage class parameters
const DEFAULT_PARAMETERS = [
'numberOfReplicas',
'staleReplicaTimeout',
'diskSelector',
'nodeSelector',
'migratable',
'encrypted',
'dataEngine',
];
const { const {
CSI_PROVISIONER_SECRET_NAME, CSI_PROVISIONER_SECRET_NAME,
CSI_PROVISIONER_SECRET_NAMESPACE, CSI_PROVISIONER_SECRET_NAMESPACE,
@@ -141,11 +130,17 @@ export default {
get() { get() {
const parameters = clone(this.value?.parameters) || {}; const parameters = clone(this.value?.parameters) || {};
DEFAULT_PARAMETERS.forEach((key) => { // UI components for Longhorn storage class parameters
delete parameters[key]; const defaultParameters = [
}); 'numberOfReplicas',
'staleReplicaTimeout',
'diskSelector',
'nodeSelector',
'migratable',
...(this.value.volumeEncryptionFeatureEnabled ? ['encrypted', 'dataEngine'] : []),
];
Object.values(CSI_SECRETS).forEach((key) => { [...defaultParameters, ...Object.values(CSI_SECRETS)].forEach((key) => {
delete parameters[key]; delete parameters[key];
}); });
@@ -311,7 +306,6 @@ export default {
</LabeledSelect> </LabeledSelect>
</div> </div>
</div> </div>
<template v-if="value.volumeEncryptionFeatureEnabled">
<div class="row mt-20"> <div class="row mt-20">
<RadioGroup <RadioGroup
v-model:value="value.parameters.migratable" v-model:value="value.parameters.migratable"
@@ -321,6 +315,7 @@ export default {
:options="migratableOptions" :options="migratableOptions"
/> />
</div> </div>
<template v-if="value.volumeEncryptionFeatureEnabled">
<div class="row mt-20"> <div class="row mt-20">
<RadioGroup <RadioGroup
v-model:value="volumeEncryption" v-model:value="volumeEncryption"
@@ -245,6 +245,8 @@ export default {
async saveImage(buttonCb) { async saveImage(buttonCb) {
this.value.spec.displayName = (this.value.spec.displayName || '').trim(); this.value.spec.displayName = (this.value.spec.displayName || '').trim();
if (this.isEdit) return await this.handleEditImage(buttonCb);
if (this.value.spec.sourceType === UPLOAD && this.isCreate) { if (this.value.spec.sourceType === UPLOAD && this.isCreate) {
try { try {
this.value.spec.url = ''; this.value.spec.url = '';
@@ -269,6 +271,23 @@ export default {
} }
}, },
async handleEditImage(buttonCb) {
try {
const data = [{
op: 'replace', path: '/metadata/labels', value: this.value.metadata.labels
}, {
op: 'replace', path: '/metadata/annotations', value: this.value.metadata.annotations
}];
await this.value.patch(data);
buttonCb(true);
this.done();
} catch (e) {
this.errors = exceptionToErrorsArray(e);
buttonCb(false);
}
},
setImageLabels(str) { setImageLabels(str) {
const suffixName = str?.split('/')?.pop() || str; const suffixName = str?.split('/')?.pop() || str;
@@ -530,6 +549,7 @@ export default {
:mode="mode" :mode="mode"
:pad-left="false" :pad-left="false"
:read-allowed="false" :read-allowed="false"
:value-can-be-empty="true"
@focusKey="focusKey" @focusKey="focusKey"
@update:value="value.setLabels($event)" @update:value="value.setLabels($event)"
> >
@@ -552,7 +572,7 @@ export default {
autocorrect="off" autocorrect="off"
autocapitalize="off" autocapitalize="off"
spellcheck="false" spellcheck="false"
@update:value="queueUpdate" @input="queueUpdate"
/> />
</template> </template>
</KeyValue> </KeyValue>
@@ -29,7 +29,7 @@ import SSHKey from './kubevirt.io.virtualmachine/VirtualMachineSSHKey';
export default { export default {
name: 'HarvesterEditVMTemplate', name: 'HarvesterEditVMTemplate',
emits: ['update:value'], emits: ['update:templateValue'],
components: { components: {
Tab, Tab,
@@ -205,7 +205,7 @@ export default {
if (tab.name === 'advanced') { if (tab.name === 'advanced') {
this.$refs.yamlEditor?.refresh(); this.$refs.yamlEditor?.refresh();
} }
} },
}, },
}; };
</script> </script>
@@ -222,11 +222,11 @@ export default {
@finish="saveVMT" @finish="saveVMT"
> >
<NameNsDescription <NameNsDescription
:value="value" :value="templateValue"
:mode="realTemplateMode" :mode="realTemplateMode"
name-label="harvester.vmTemplate.nameNsDescription.name" name-label="harvester.vmTemplate.nameNsDescription.name"
:namespaced="true" :namespaced="true"
@update:value="$emit('update:value', $event)" @update:value="$emit('update:templateValue', $event)"
/> />
<Checkbox <Checkbox
@@ -95,7 +95,11 @@ export default {
devices: { devices: {
handler(v) { handler(v) {
this.rows = v; this.rows = v;
if (this.parentSriov) {
this.filterRows = this.rows.filter((row) => row.labels[this.parentSriovLabel] === this.parentSriov);
} else {
this.filterRows = this.rows; this.filterRows = this.rows;
}
}, },
immediate: true, immediate: true,
}, },
@@ -1,5 +1,5 @@
<script> <script>
import { Sortable } from 'sortablejs-vue3'; import { VueDraggableNext } from 'vue-draggable-next';
import InfoBox from '@shell/components/InfoBox'; import InfoBox from '@shell/components/InfoBox';
import { Banner } from '@components/Banner'; import { Banner } from '@components/Banner';
import BadgeStateFormatter from '@shell/components/formatter/BadgeStateFormatter'; import BadgeStateFormatter from '@shell/components/formatter/BadgeStateFormatter';
@@ -22,7 +22,7 @@ export default {
emits: ['update:value'], emits: ['update:value'],
components: { components: {
Banner, BadgeStateFormatter, Sortable, InfoBox, LabeledInput, UnitInput, LabeledSelect, ModalWithCard Banner, BadgeStateFormatter, VueDraggableNext, InfoBox, LabeledInput, UnitInput, LabeledSelect, ModalWithCard
}, },
props: { props: {
@@ -272,14 +272,16 @@ export default {
color="info" color="info"
label-key="harvester.virtualMachine.volume.dragTip" label-key="harvester.virtualMachine.volume.dragTip"
/> />
<Sortable <VueDraggableNext
:list="rows" :list="rows"
:options="{disabled: isView}" :disabled="isView"
item-key="id" item-key="id"
@end="update" @end="update"
> >
<template #item="{element: volume, index: i}"> <div
<div :key="volume.name"> v-for="(volume, i) in rows"
:key="volume.id"
>
<InfoBox class="box"> <InfoBox class="box">
<button <button
v-if="!isView" v-if="!isView"
@@ -393,8 +395,7 @@ export default {
</div> </div>
</InfoBox> </InfoBox>
</div> </div>
</template> </VueDraggableNext>
</Sortable>
<Banner <Banner
v-if="showVolumeTip" v-if="showVolumeTip"
color="warning" color="warning"
@@ -58,7 +58,7 @@ export default {
const out = []; const out = [];
blockDevices.map((b) => { blockDevices.map((b) => {
if (b.metadata.state.error) { if (b?.metadata?.state?.error) {
out.push(b.metadata.state.message); out.push(b.metadata.state.message);
} }
}); });
@@ -72,17 +72,23 @@ export default {
return stats; return stats;
}, },
units() { allocatedUnits() {
const exponent = exponentNeeded(this.storageStats.total, 1024);
return `${ UNITS[exponent] }iB`;
},
usedUnits() {
const exponent = exponentNeeded(this.storageStats.maximum, 1024); const exponent = exponentNeeded(this.storageStats.maximum, 1024);
return `${ UNITS[exponent] }iB`; return `${ UNITS[exponent] }iB`;
}, },
used() { formatUsed() {
let out = this.formatter(this.storageStats.used); let out = this.formatter(this.storageStats.used);
if (!Number.parseFloat(out) > 0) { if (!Number.parseFloat(out) > 0) {
out = this.formatter(this.storageStats.used, { canRoundToZero: false }); out = this.formatter(this.storageStats.used, { canRoundToZero: true });
} }
return out; return out;
@@ -92,7 +98,7 @@ export default {
let out = this.formatter(this.storageStats.scheduled); let out = this.formatter(this.storageStats.scheduled);
if (!Number.parseFloat(out) > 0) { if (!Number.parseFloat(out) > 0) {
out = this.formatter(this.storageStats.scheduled, { canRoundToZero: false }); out = this.formatter(this.storageStats.scheduled, { canRoundToZero: true });
} }
return out; return out;
@@ -100,9 +106,9 @@ export default {
usedAmountTemplateValues() { usedAmountTemplateValues() {
return { return {
used: this.used, used: this.formatUsed,
total: this.formatter(this.storageStats.maximum), total: this.formatter(this.storageStats.maximum),
unit: this.units, unit: this.usedUnits,
}; };
}, },
@@ -110,7 +116,7 @@ export default {
return { return {
used: this.formatAllocated, used: this.formatAllocated,
total: this.formatter(this.storageStats.total), total: this.formatter(this.storageStats.total),
unit: this.units, unit: this.allocatedUnits,
}; };
}, },
}, },
@@ -141,7 +147,7 @@ export default {
<ConsumptionGauge <ConsumptionGauge
:capacity="storageStats.total" :capacity="storageStats.total"
:used="storageStats.scheduled" :used="storageStats.scheduled"
:units="units" :units="allocatedUnits"
:number-formatter="formatter" :number-formatter="formatter"
:resource-name="resourceName" :resource-name="resourceName"
> >
@@ -161,7 +167,7 @@ export default {
<ConsumptionGauge <ConsumptionGauge
:capacity="storageStats.maximum" :capacity="storageStats.maximum"
:used="storageStats.used" :used="storageStats.used"
:units="units" :units="usedUnits"
:number-formatter="formatter" :number-formatter="formatter"
:resource-name="showAllocated ? '' : resourceName" :resource-name="showAllocated ? '' : resourceName"
:class="{ :class="{
-4
View File
@@ -21,10 +21,6 @@ export default function (plugin: IPlugin) {
// Built-in icon // Built-in icon
plugin.metadata.icon = require('./icon.svg'); plugin.metadata.icon = require('./icon.svg');
if (isDev && !isSingleVirtualCluster) {
plugin.addProduct(require('./config/harvester-manager'));
}
plugin.addProduct(require('./config/harvester-cluster')); plugin.addProduct(require('./config/harvester-cluster'));
plugin.addDashboardStore(harvesterCommonStore.config.namespace, harvesterCommonStore.specifics, harvesterCommonStore.config); plugin.addDashboardStore(harvesterCommonStore.config.namespace, harvesterCommonStore.specifics, harvesterCommonStore.config);
+23 -42
View File
@@ -1,34 +1,3 @@
harvesterManager:
manage: Manage
tableHeaders:
kubernetesVersion: Kubernetes Version
harvesterVersion: Harvester Version
cluster:
label: Harvester Clusters
none: There are no Harvester Clusters
learnMore: Learn more about Harvester from the <a target="_blank" href="https://harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Web Site</a> or read the the <a target="_blank" href="https://docs.harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Docs</a>
description: Harvester is a modern Hyperconverged infrastructure (HCI) solution built for bare metal servers using enterprise-grade open source technologies including Kubernetes, Kubevirt and Longhorn.
supportMessage: Harvester ui extension only supports Harvester cluster version greater or equal to 1.3.0
plugins:
loadError: Error loading harvester plugin
rke:
templateError: Incorrect template format
affinity:
thisPodNamespace: This VM's namespace
matchExpressions:
inNamespaces: "Workloads in these namespaces"
vmAffinityTitle: VM Scheduling
namespaces:
placeholder: e.g. default,system,base
label: Namespaces
addLabel: Add Workload Selector
topologyKey:
placeholder: 'topology.kubernetes.io/zone'
vGpu:
title: VGPUs
label: VGPU type
placeholder: 'Please select a VGPU'
generic: generic:
tip: Tip tip: Tip
resourceExternalLinkTips: 'External Link' resourceExternalLinkTips: 'External Link'
@@ -39,6 +8,11 @@ generic:
basic: Basic basic: Basic
loading: Loading... loading: Loading...
unsupported:
serverVersion: 'Current version: <code>{serverVersion}</code>'
description: Harvester ui only supports Harvester cluster version greater or equal to 1.3.0.
learnMore: Learn more about Harvester from the <a target="_blank" href="https://harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Web Site</a> or read the <a target="_blank" href="https://docs.harvesterhci.io/" rel="noopener noreferrer nofollow">Harvester Docs</a>
nav: nav:
group: group:
networks: Networks networks: Networks
@@ -65,6 +39,11 @@ asyncButton:
waiting: Restarting&hellip; waiting: Restarting&hellip;
harvester: harvester:
branding:
logos:
tip: 'Upload a logo to replace the Harvester logo in the top-level navigation header. Image height should be 21 pixels with a max width of 200 pixels. Max file size is 20KB. Accepted formats: JPEG, PNG, SVG.'
favicon:
tip: 'Upload an icon to replace the Harvester favicon in the browser tab. Max file size is 20KB'
productLabel: 'Harvester' productLabel: 'Harvester'
modal: modal:
backup: backup:
@@ -768,6 +747,9 @@ harvester:
terminationGracePeriodSeconds: terminationGracePeriodSeconds:
label: Termination Grace Period label: Termination Grace Period
affinity: affinity:
addLabel: Add Workload Selector
topologyKey:
placeholder: 'topology.kubernetes.io/zone'
thisPodNamespace: This virtual machine's namespace thisPodNamespace: This virtual machine's namespace
matchExpressions: matchExpressions:
inNamespaces: "Workloads in these namespaces" inNamespaces: "Workloads in these namespaces"
@@ -920,6 +902,9 @@ harvester:
label: Virtual Machine Backups label: Virtual Machine Backups
createText: Restore Backup createText: Restore Backup
title: Restore Virtual Machine title: Restore Virtual Machine
refreshInterval:
label: Refresh Interval
tip: The interval for the backup target to sync data to harvester cluster. Set to 0 to disable refresh mechanism.
backupTargetTip: The endpoint used to access the backupstore. NFS and S3 are supported. backupTargetTip: The endpoint used to access the backupstore. NFS and S3 are supported.
message: message:
noSetting: noSetting:
@@ -1520,17 +1505,13 @@ harvester:
pollingInterval: pollingInterval:
label: Polling Interval label: Polling Interval
affinity: typeDescription:
thisPodNamespace: This virtual machine's namespace # Map of
matchExpressions: # type: Description to be shown on the top of list view describing the type.
inNamespaces: "Workloads in these namespaces" # Should fit on one line.
vmAffinityTitle: Virtual Machine Scheduling # If you link to anything external, it MUST have
namespaces: # target="_blank" rel="noopener noreferrer nofollow"
placeholder: e.g. default,system,base harvester: "Branding allows administrators to globally re-brand the UI by customizing the Harvester product name, logos and color scheme."
label: Namespaces
addLabel: Add Workload Selector
topologyKey:
placeholder: 'topology.kubernetes.io/zone'
advancedSettings: advancedSettings:
experimental: 'Experimental features allow users to test and evaluate early-access functionality prior to official supported releases' experimental: 'Experimental features allow users to test and evaluate early-access functionality prior to official supported releases'
@@ -12,6 +12,8 @@ import { HCI } from '../types';
export default { export default {
name: 'ListSriovGpuDevices', name: 'ListSriovGpuDevices',
inheritAttrs: false,
components: { components: {
Banner, Banner,
Loading, Loading,
@@ -10,6 +10,8 @@ import DeviceList from '../edit/kubevirt.io.virtualmachine/VirtualMachineUSBDevi
export default { export default {
name: 'ListUsbDevicePage', name: 'ListUsbDevicePage',
inheritAttrs: false,
components: { components: {
Banner, Banner,
DeviceList, DeviceList,
@@ -10,6 +10,8 @@ import { ADD_ONS } from '../config/harvester-map';
export default { export default {
name: 'ListVGpuDevices', name: 'ListVGpuDevices',
inheritAttrs: false,
components: { components: {
Banner, Banner,
Loading, Loading,
@@ -1,279 +0,0 @@
<script>
import BrandImage from '@shell/components/BrandImage';
import TypeDescription from '@shell/components/TypeDescription';
import ResourceTable from '@shell/components/ResourceTable';
import Masthead from '@shell/components/ResourceList/Masthead';
import Loading from '@shell/components/Loading';
import { HARVESTER_NAME as VIRTUAL } from '@shell/config/features';
import { CAPI, HCI, MANAGEMENT } from '@shell/config/types';
import { isHarvesterCluster } from '@shell/utils/cluster';
import { allHash } from '@shell/utils/promise';
import { STATE, NAME as NAME_COL, AGE, VERSION } from '@shell/config/table-headers';
import { MACHINE_POOLS } from '../config/table-headers';
export default {
components: {
BrandImage,
ResourceTable,
Masthead,
TypeDescription,
Loading
},
props: {
schema: {
type: Object,
required: true,
},
useQueryParamsForSimpleFiltering: {
type: Boolean,
default: false
}
},
async fetch() {
const inStore = this.$store.getters['currentProduct'].inStore;
const hash = await allHash({
hciClusters: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.CLUSTER }),
mgmtClusters: this.$store.dispatch(`${ inStore }/findAll`, { type: MANAGEMENT.CLUSTER })
});
this.hciClusters = hash.hciClusters;
this.mgmtClusters = hash.mgmtClusters;
},
data() {
const resource = CAPI.RANCHER_CLUSTER;
return {
navigating: false,
VIRTUAL,
hciDashboard: HCI.DASHBOARD,
resource,
hResource: HCI.CLUSTER,
realSchema: this.$store.getters['management/schemaFor'](CAPI.RANCHER_CLUSTER),
hciClusters: [],
mgmtClusters: []
};
},
computed: {
headers() {
return [
STATE,
NAME_COL,
{
name: 'harvesterVersion',
sort: 'harvesterVersion',
labelKey: 'harvesterManager.tableHeaders.harvesterVersion',
value: 'harvesterVersion',
getValue: (row) => row.harvesterVersion
},
{
...VERSION,
labelKey: 'harvesterManager.tableHeaders.kubernetesVersion',
value: 'kubernetesVersion',
getValue: (row) => row.kubernetesVersion
},
MACHINE_POOLS,
AGE,
{
name: 'harvester',
label: ' ',
align: 'right',
width: 65,
},
];
},
importLocation() {
return {
name: 'c-cluster-product-resource-create',
params: {
product: this.$store.getters['currentProduct'].name,
resource: this.schema.id,
},
};
},
canCreateCluster() {
const schema = this.$store.getters['management/schemaFor'](CAPI.RANCHER_CLUSTER);
return !!schema?.collectionMethods.find((x) => x.toLowerCase() === 'post');
},
rows() {
return this.hciClusters
.filter((c) => {
const cluster = this.mgmtClusters.find((cluster) => cluster?.metadata?.name === c?.status?.clusterName);
return isHarvesterCluster(cluster);
})
.map((row) => {
if (row.isReady) {
row.setSupportedHarvesterVersion();
}
return row;
});
},
typeDisplay() {
return this.t(`typeLabel."${ HCI.CLUSTER }"`, { count: this.rows?.length || 0 });
},
},
methods: {
async goToCluster(row) {
const timeout = setTimeout(() => {
// Don't show loading indicator for quickly fetched plugins
this.navigating = row.id;
}, 1000);
try {
await row.goToCluster();
clearTimeout(timeout);
this.navigating = false;
} catch {
// The error handling is carried out within goToCluster, but just in case something happens before the promise chain can catch it...
clearTimeout(timeout);
this.navigating = false;
}
}
}
};
</script>
<template>
<Loading v-if="$fetchState.pending" />
<div v-else>
<Masthead
:schema="realSchema"
:resource="resource"
:is-creatable="false"
:type-display="typeDisplay"
>
<template #typeDescription>
<TypeDescription :resource="hResource" />
</template>
<template
v-if="canCreateCluster"
#extraActions
>
<router-link
:to="importLocation"
class="btn role-primary"
>
{{ t('cluster.importAction') }}
</router-link>
</template>
</Masthead>
<ResourceTable
v-if="rows && rows.length"
:schema="schema"
:headers="headers"
:rows="rows"
:is-creatable="true"
:namespaced="false"
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
>
<template #col:name="{row}">
<td>
<span class="cluster-link">
<a
v-if="row.isReady && row.isSupportedHarvester"
class="link"
:disabled="navigating ? true : null"
@click="goToCluster(row)"
>{{ row.nameDisplay }}</a>
<span v-else>
{{ row.nameDisplay }}
</span>
<i
class="icon icon-spinner icon-spin ml-5"
:class="{'navigating': navigating === row.id}"
/>
</span>
</td>
</template>
<template #cell:harvester="{row}">
<router-link
class="btn btn-sm role-primary"
:to="row.detailLocation"
>
{{ t('harvesterManager.manage') }}
</router-link>
</template>
</ResourceTable>
<div v-else>
<div class="no-clusters">
{{ t('harvesterManager.cluster.none') }}
</div>
<hr class="info-section">
<div class="logo">
<BrandImage
file-name="harvester.png"
height="64"
/>
</div>
<div class="tagline">
<div>{{ t('harvesterManager.cluster.description') }}</div>
</div>
<div class="tagline sub-tagline">
<div v-clean-html="t('harvesterManager.cluster.learnMore', {}, true)" />
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.cluster-link {
display: flex;
align-items: center;
.icon {
// Use visibility to avoid the columns re-adjusting when the icon is shown
visibility: hidden;
&.navigating {
visibility: visible;
}
}
}
.no-clusters {
text-align: center;
}
.info-section {
margin-top: 60px;
}
.logo {
display: flex;
justify-content: center;
margin: 60px 0 40px 0;
}
.tagline {
display: flex;
justify-content: center;
margin-top: 30px;
> div {
font-size: 16px;
line-height: 22px;
max-width: 80%;
text-align: center;
}
}
.link {
cursor: pointer;
}
</style>
+5 -5
View File
@@ -282,14 +282,14 @@ export default {
affinityLabels() { affinityLabels() {
return { return {
namespaceInputLabel: this.t('harvesterManager.affinity.namespaces.label'), namespaceInputLabel: this.t('harvester.virtualMachine.affinity.namespaces.label'),
namespaceSelectionLabels: [ namespaceSelectionLabels: [
this.t('harvesterManager.affinity.thisPodNamespace'), this.t('harvester.virtualMachine.affinity.thisPodNamespace'),
this.t('workload.scheduling.affinity.allNamespaces'), this.t('workload.scheduling.affinity.allNamespaces'),
this.t('harvesterManager.affinity.matchExpressions.inNamespaces') this.t('harvester.virtualMachine.affinity.matchExpressions.inNamespaces')
], ],
addLabel: this.t('harvesterManager.affinity.addLabel'), addLabel: this.t('harvester.virtualMachine.affinity.addLabel'),
topologyKeyPlaceholder: this.t('harvesterManager.affinity.topologyKey.placeholder') topologyKeyPlaceholder: this.t('harvester.virtualMachine.affinity.topologyKey.placeholder')
}; };
}, },
}, },
@@ -0,0 +1,11 @@
import SteveModel from '@shell/plugins/steve/steve-class';
/**
* Class representing PCI Device Claim resource.
* @extends SteveModal
*/
export default class PCIDeviceClaim extends SteveModel {
cleanForSave(data, _forNew) {
return data;
}
}
@@ -0,0 +1,11 @@
import SteveModel from '@shell/plugins/steve/steve-class';
/**
* Class representing USB Device Claim resource.
* @extends SteveModal
*/
export default class USBDeviceClaim extends SteveModel {
cleanForSave(data, _forNew) {
return data;
}
}
+4
View File
@@ -66,4 +66,8 @@ export default class HarvesterResource extends SteveModel {
return this.hasLink('self') && this.$rootGetters['prefs/get'](DEV); return this.hasLink('self') && this.$rootGetters['prefs/get'](DEV);
} }
} }
cleanForSave(data, _forNew) {
return data;
}
} }
+1 -1
View File
@@ -3,4 +3,4 @@ import SteveSchema from '@shell/models/steve-schema';
/** /**
* This is the steve schema that's used for the harvester store * This is the steve schema that's used for the harvester store
*/ */
export default class HarvesterStoreSchema extends SteveSchema { } export default class HarvesterStoreSchema extends SteveSchema {}
@@ -64,4 +64,10 @@ export default class HciBlockDevice extends HarvesterResource {
// spec.fileSystem.provisioned is deprecated // spec.fileSystem.provisioned is deprecated
return this.spec?.fileSystem?.provisioned || this.spec?.provision; return this.spec?.fileSystem?.provisioned || this.spec?.provision;
} }
// Overwrite cleanForSave() in shell/plugins/steve/steve-class.js as it deleted status object in harvesterhci.io.blockdevice CRD
// but /v1/harvester/harvesterhci.io.blockdevices/longhorn-system/{id} API requires status object
cleanForSave(data) {
return data;
}
} }
@@ -1,223 +0,0 @@
import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
import { DEFAULT_WORKSPACE, HCI, MANAGEMENT } from '@shell/config/types';
import { HARVESTER_NAME, HARVESTER_NAME as VIRTUAL } from '@shell/config/features';
import { SETTING } from '@shell/config/settings';
import { colorForState, stateDisplay, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
export default class HciCluster extends ProvCluster {
get isSupportedHarvester() {
return this._isSupportedHarvester === undefined ? true : this._isSupportedHarvester;
}
get harvesterVersion() {
return this._harvesterVersion;
}
get stateObj() {
if (!this.isSupportedHarvester) {
return { error: true, message: this.t('harvesterManager.cluster.supportMessage') };
}
return this._stateObj;
}
applyDefaults() {
if ( !this.spec ) {
this['spec'] = { agentEnvVars: [] };
this['metadata'] = { namespace: DEFAULT_WORKSPACE };
}
}
get isReady() {
// If the Connected condition exists, use that (2.6+)
if ( this.hasCondition('Connected') ) {
return this.isCondition('Connected');
}
// Otherwise use Ready (older)
return this.isCondition('Ready');
}
get canEdit() {
return false;
}
get stateColor() {
if (!this.isSupportedHarvester) {
return colorForState(STATES_ENUM.DENIED);
}
return colorForState(this.state);
}
get stateDisplay() {
if (!this.isSupportedHarvester) {
return stateDisplay(STATES_ENUM.DENIED);
}
return stateDisplay(this.state);
}
/**
* Fetch and cache the response for /ui-info
*
* Storing this in a cache means any changes to `ui-info` require a dashboard refresh... but it cuts out a http request every time we
* go to a cluster
*
* @param {string} clusterId
*/
async _getUiInfo(clusterId) {
if (!this._uiInfo) {
try {
const infoUrl = `/k8s/clusters/${ clusterId }/v1/harvester/ui-info`;
this._uiInfo = await this.$dispatch('request', { url: infoUrl });
} catch (e) {
console.info(`Failed to fetch harvester ui-info from ${ this.nameDisplay }, this may be an older cluster that cannot provide one`); // eslint-disable-line no-console
}
}
return this._uiInfo;
}
/**
* Determine the harvester plugin's package name and url for legacy clusters that don't provide the package (i.e. it's coming from
* outside the cluster)
*/
_legacyClusterPkgDetails() {
let uiOfflinePreferred = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_OFFLINE_PREFERRED)?.value;
// options: ['dynamic', 'true', 'false']
if (uiOfflinePreferred === 'dynamic') {
// We shouldn't need to worry about the version of the dashboard when embedded in harvester (aka in isSingleProduct)
const version = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.VERSION_RANCHER)?.value;
if (version.endsWith('-head')) {
uiOfflinePreferred = 'false';
} else {
uiOfflinePreferred = 'true';
}
}
// This is the version that's embedded in the dashboard
const pkgName = `${ HARVESTER_NAME }-1.0.3`;
if (uiOfflinePreferred === 'true') {
// Embedded (aka give me the embedded plugin that was in the last rancher release)
const embeddedPath = `${ pkgName }/${ pkgName }.umd.min.js`;
return {
pkgUrl: process.env.dev ? `${ process.env.api }/dashboard/${ embeddedPath }` : embeddedPath,
pkgName
};
}
if (uiOfflinePreferred === 'false') {
// Remote (aka give me the latest version of the embedded plugin that might not have been released yet)
const uiDashboardHarvesterRemotePlugin = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_DASHBOARD_HARVESTER_LEGACY_PLUGIN)?.value;
const parts = uiDashboardHarvesterRemotePlugin?.replace('.umd.min.js', '').split('/');
const pkgNameFromUrl = parts?.length > 1 ? parts[parts.length - 1] : null;
if (!pkgNameFromUrl) {
throw new Error(`Unable to determine harvester plugin name from '${ uiDashboardHarvesterRemotePlugin }'`);
}
return {
pkgUrl: uiDashboardHarvesterRemotePlugin,
pkgName: pkgNameFromUrl
};
}
throw new Error(`Unsupported value for ${ SETTING.UI_OFFLINE_PREFERRED }: 'uiOfflinePreferred'`);
}
/**
* Determine the harvester plugin's package name and url for clusters that provide the plugin
*/
_supportedClusterPkgDetails(uiInfo, clusterId) {
let pkgName = `${ HARVESTER_NAME }-${ uiInfo['ui-plugin-bundled-version'] }`;
const fileName = `${ pkgName }.umd.min.js`;
let pkgUrl;
if (uiInfo['ui-source'] === 'bundled' ) { // offline bundled
pkgUrl = `/k8s/clusters/${ clusterId }/v1/harvester/plugin-assets/${ fileName }`;
} else if (uiInfo['ui-source'] === 'external') {
if (uiInfo['ui-plugin-index']) {
pkgUrl = uiInfo['ui-plugin-index'];
// When using an external address, the pkgName should also be get from the url
const names = pkgUrl.split('/');
const jsName = names[names.length - 1];
pkgName = jsName?.split('.umd.min.js')[0];
} else {
throw new Error('Harvester cluster requested the plugin at `ui-plugin-index` is used, however did not provide a value for it');
}
}
return {
pkgUrl,
pkgName
};
}
_overridePkgDetails() {
// Support loading the pkg from a locally, or other, address
// This helps testing of the harvester plugin when packaged up, instead of directly imported
const harvesterPkgUrl = process.env.harvesterPkgUrl;
if (!harvesterPkgUrl) {
return;
}
const parts = harvesterPkgUrl.replace('.umd.min.js', '').split('/');
const pkgNameFromUrl = parts.length > 1 ? parts[parts.length - 1] : null;
if (pkgNameFromUrl) {
return {
pkgUrl: harvesterPkgUrl,
pkgName: pkgNameFromUrl
};
}
}
async _pkgDetails() {
const overridePkgDetails = this._overridePkgDetails();
if (overridePkgDetails) {
return overridePkgDetails;
}
const clusterId = this.mgmt.id;
const uiInfo = await this._getUiInfo(clusterId);
return uiInfo ? this._supportedClusterPkgDetails(uiInfo, clusterId) : this._legacyClusterPkgDetails();
}
async goToCluster() {
this.currentRouter().push({
name: `${ VIRTUAL }-c-cluster-resource`,
params: {
cluster: this.status.clusterName,
product: VIRTUAL,
resource: HCI.DASHBOARD // Go directly to dashboard to avoid blip of components on screen
}
});
}
async setSupportedHarvesterVersion() {
if (this._isSupportedHarvester !== undefined) {
return;
}
const url = `/k8s/clusters/${ this.status.clusterName }/v1`;
try {
const setting = await this.$dispatch('request', { url: `${ url }/${ HCI.SETTING }s/server-version` });
this._harvesterVersion = setting?.value;
this._isSupportedHarvester = this.$rootGetters['harvester-common/getFeatureEnabled']('supportHarvesterClusterVersion', setting?.value);
} catch (error) {
console.error('unable to get harvester version from settings/server-version', error); // eslint-disable-line no-console
}
}
}
@@ -1,6 +1,4 @@
import HarvesterResource from './harvester'; import HarvesterResource from './harvester';
import { get } from '@shell/utils/object';
import { findBy } from '@shell/utils/array';
import { colorForState, stateDisplay, STATES } from '@shell/plugins/dashboard-store/resource-class'; import { colorForState, stateDisplay, STATES } from '@shell/plugins/dashboard-store/resource-class';
import { _CREATE } from '@shell/config/query-params'; import { _CREATE } from '@shell/config/query-params';
import { ucFirst, escapeHtml } from '@shell/utils/string'; import { ucFirst, escapeHtml } from '@shell/utils/string';
@@ -66,15 +64,12 @@ export default class ScheduleVmBackup extends HarvesterResource {
} }
} }
get state() { get stateObj() {
const conditions = get(this, 'status.conditions'); return this?.metadata?.state || {};
const isSuspended = findBy(conditions, 'type', 'BackupSuspend')?.status === 'True';
if (isSuspended) {
return STATES.suspended.label;
} }
return this.metadata.state.name; get state() {
return this.status?.suspended === true ? STATES.suspended.label : STATES.active.label;
} }
get stateDescription() { get stateDescription() {
@@ -61,6 +61,10 @@ export default class HciUpgrade extends HarvesterResource {
return this?.status?.imageID; return this?.status?.imageID;
} }
cleanForSave(data, _forNew) {
return data;
}
get upgradeMessage() { get upgradeMessage() {
const upgradeMessage = []; const upgradeMessage = [];
const nodeStatuses = this?.status?.nodeStatuses || {}; const nodeStatuses = this?.status?.nodeStatuses || {};
@@ -1120,10 +1120,6 @@ export default class VirtVm extends HarvesterResource {
return qemu?.status === 'True'; return qemu?.status === 'True';
} }
get warnDeletionMessage() {
return this.t('harvester.virtualMachine.promptRemove.tips');
}
get instanceLabels() { get instanceLabels() {
const all = this.spec?.template?.metadata?.labels || {}; const all = this.spec?.template?.metadata?.labels || {};
+3 -3
View File
@@ -1,14 +1,14 @@
{ {
"name": "harvester", "name": "harvester",
"description": "Rancher UI Extension for Harvester", "description": "Rancher UI Extension for Harvester",
"version": "1.0.0", "version": "1.0.5",
"private": false, "private": false,
"rancher": { "rancher": {
"annotations": { "annotations": {
"catalog.cattle.io/display-name": "Harvester", "catalog.cattle.io/display-name": "Harvester",
"catalog.cattle.io/kube-version": ">= 1.16.0-0", "catalog.cattle.io/kube-version": ">= 1.16.0-0",
"catalog.cattle.io/rancher-version": ">= 2.10.0-0", "catalog.cattle.io/rancher-version": ">= 2.10.1-0",
"catalog.cattle.io/ui-extensions-version": ">= 3.0.0-0" "catalog.cattle.io/ui-extensions-version": ">= 3.0.0 < 4.0.0"
} }
}, },
"icon": "https://raw.githubusercontent.com/harvester/harvester-ui-extension/main/pkg/harvester/icon.svg", "icon": "https://raw.githubusercontent.com/harvester/harvester-ui-extension/main/pkg/harvester/icon.svg",
@@ -164,7 +164,7 @@ export default {
<h1 class="mb-20"> <h1 class="mb-20">
{{ t('branding.label') }} {{ t('branding.label') }}
</h1> </h1>
<TypeDescription resource="branding" /> <TypeDescription resource="harvester" />
<div> <div>
<div class="row mb-20"> <div class="row mb-20">
<div class="col span-6"> <div class="col span-6">
@@ -180,7 +180,7 @@ export default {
{{ t('branding.logos.label') }} {{ t('branding.logos.label') }}
</h3> </h3>
<label class="text-label"> <label class="text-label">
{{ t('branding.logos.tip', {}, true) }} {{ t('harvester.branding.logos.tip', {}, true) }}
</label> </label>
<div class="row mt-10 mb-20"> <div class="row mt-10 mb-20">
<Checkbox <Checkbox
@@ -244,7 +244,7 @@ export default {
{{ t('branding.favicon.label') }} {{ t('branding.favicon.label') }}
</h3> </h3>
<label class="text-label"> <label class="text-label">
{{ t('branding.favicon.tip', {}, true) }} {{ t('harvester.branding.favicon.tip', {}, true) }}
</label> </label>
<div class="row mt-10 mb-20"> <div class="row mt-10 mb-20">
<Checkbox <Checkbox
@@ -0,0 +1,85 @@
<script>
import BrandImage from '@shell/components/BrandImage';
export default {
components: { BrandImage },
computed: {
serverVersion() {
const version = this.$store.getters['harvester-common/getServerVersion']() || '';
return version.replace('v', '');
}
}
};
</script>
<template>
<div class="dashboard-root">
<div class="dashboard-content">
<main class="main-layout">
<div class="logo">
<BrandImage
file-name="harvester.png"
height="64"
/>
</div>
<div class="tagline">
<div class="description">
{{ t('unsupported.description') }}
</div>
</div>
<div class="tagline">
<div v-clean-html="t('unsupported.serverVersion', { serverVersion }, true)" />
</div>
<div class="tagline">
<div v-clean-html="t('unsupported.learnMore', {}, true)" />
</div>
</main>
</div>
</div>
</template>
<style lang="scss" scoped>
.dashboard-root {
display: flex;
flex-direction: column;
height: 100vh;
}
.dashboard-content {
display: grid;
flex-grow:1;
grid-template-areas:
"main";
grid-template-columns: auto;
grid-template-rows: auto;
}
.logo {
display: flex;
justify-content: center;
margin: 200px 0 40px 0;
}
.tagline {
display: flex;
justify-content: center;
margin-top: 30px;
> div {
font-size: 16px;
line-height: 22px;
max-width: 80%;
text-align: center;
}
}
.description {
font-size: 24px !important;
font-weight: 400;
}
</style>
@@ -4,6 +4,7 @@ import { isEmpty } from '@shell/utils/object';
import Parse from 'url-parse'; import Parse from 'url-parse';
import { resourceNames } from '@shell/utils/string'; import { resourceNames } from '@shell/utils/string';
import { HCI } from '../types'; import { HCI } from '../types';
import { alternateLabel as alternateLabelButton } from '@shell/utils/platform';
export default { export default {
name: 'HarvesterPromptRemove', name: 'HarvesterPromptRemove',
@@ -40,7 +41,8 @@ export default {
data() { data() {
return { return {
checkedList: [], checkedList: [],
checkAll: true checkAll: true,
alternateLabel: alternateLabelButton
}; };
}, },
@@ -138,6 +140,7 @@ export default {
</script> </script>
<template> <template>
<div>
<div class="mt-10"> <div class="mt-10">
{{ t('promptRemove.attemptingToRemove', {type}) }} {{ t('promptRemove.attemptingToRemove', {type}) }}
<span v-clean-html="resourceNames(names, plusMore, t)"></span> <span v-clean-html="resourceNames(names, plusMore, t)"></span>
@@ -150,7 +153,8 @@ export default {
v-for="(name, i) in removeNameArr[value[0].id]" v-for="(name, i) in removeNameArr[value[0].id]"
:key="i" :key="i"
> >
<label class="checkbox-container mr-15"><input <label class="checkbox-container mr-15">
<input
v-model="checkedList" v-model="checkedList"
type="checkbox" type="checkbox"
:label="name" :label="name"
@@ -164,10 +168,10 @@ export default {
</label> </label>
</span> </span>
</div> </div>
<div v-else> <div v-else>
<label class="checkbox-container mr-15"><input <label class="checkbox-container mr-15">
v-model="checkAll" <input
v-model="checkedList"
type="checkbox" type="checkbox"
/> />
<span <span
@@ -178,4 +182,11 @@ export default {
</label> </label>
</div> </div>
</div> </div>
<div class="text-warning mb-10 mt-10">
{{ t('harvester.virtualMachine.promptRemove.tips') }}
</div>
<div class="text-info mt-20">
{{ t('promptRemove.protip', { alternateLabel }) }}
</div>
</div>
</template> </template>
@@ -15,8 +15,25 @@ import HarvesterAirgapUpdgrade from '../pages/c/_cluster/airgapupgrade/index.vue
import HarvesterMembers from '../pages/c/_cluster/members/index.vue'; import HarvesterMembers from '../pages/c/_cluster/members/index.vue';
import ProjectNamespaces from '../pages/c/_cluster/projectsnamespaces.vue'; import ProjectNamespaces from '../pages/c/_cluster/projectsnamespaces.vue';
import HarvesterAlertmanagerReceiver from '../pages/c/_cluster/alertmanagerconfig/_alertmanagerconfigid/receiver.vue'; import HarvesterAlertmanagerReceiver from '../pages/c/_cluster/alertmanagerconfig/_alertmanagerconfigid/receiver.vue';
import HarvesterUnsupported from '../pages/c/_cluster/unsupported/index.vue';
const routes = [ const routes = [
{
route: {
name: `${ PRODUCT_NAME }-c-cluster-unsupported-standalone`,
path: `/:product`,
component: HarvesterUnsupported
},
parent: 'blank'
},
{
route: {
name: `${ PRODUCT_NAME }-c-cluster-unsupported`,
path: `/:product`,
component: HarvesterUnsupported
},
parent: 'plain'
},
{ {
name: `${ PRODUCT_NAME }-c-cluster-support`, name: `${ PRODUCT_NAME }-c-cluster-support`,
path: `/:product/c/:cluster/support`, path: `/:product/c/:cluster/support`,
@@ -101,6 +101,19 @@ export default {
const res: any = await allHash(hash); const res: any = await allHash(hash);
const isHarvesterVersionSupported = rootGetters['harvester-common/getFeatureEnabled']('supportHarvesterClusterVersion');
if (!isHarvesterVersionSupported) {
const product = rootGetters['productId'];
this.$router?.push({
name: `${ product }-c-cluster-unsupported${ id === 'local' ? '-standalone' : '' }`,
params: { product }
});
return;
}
await dispatch('cleanNamespaces', null, { root: true }); await dispatch('cleanNamespaces', null, { root: true });
commit('updateNamespaces', { commit('updateNamespaces', {
+1
View File
@@ -8,6 +8,7 @@
"importHelpers": true, "importHelpers": true,
"moduleResolution": "node", "moduleResolution": "node",
"skipLibCheck": true, "skipLibCheck": true,
"useDefineForClassFields": false,
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"sourceMap": true, "sourceMap": true,
+21 -2
View File
@@ -14,16 +14,35 @@ export function getVersion(v) {
} }
try { try {
// v1.4.1-rc.1 => v1.4.1, v1.4.1-dev-20241222 => v1.4.1
return `v${ semver.major(v) }.${ semver.minor(v) }.${ semver.patch(v) }`; return `v${ semver.major(v) }.${ semver.minor(v) }.${ semver.patch(v) }`;
} catch (error) { } catch (error) {
// fallback to the latest version // fallback to the latest version
return Object.keys(RELEASE_FEATURES).sort((a, b) => semver.compare(a, b)).pop(); return latestVersion(Object.keys(RELEASE_FEATURES));
} }
} }
function latestVersion(versions) {
return versions.sort((a, b) => semver.compare(a, b)).pop();
}
// v1.3.3 => latest v1.3.x, v1.4.2 => latest v1.4.x
function latestMinorVersion(v) {
const minor = `v${ semver.major(v) }.${ semver.minor(v) }`;
const minorVersions = Object.keys(RELEASE_FEATURES).filter((version) => version.startsWith(minor));
return latestVersion(minorVersions);
}
export const featureEnabled = (featureKey, serverVersion) => { export const featureEnabled = (featureKey, serverVersion) => {
const version = getVersion(serverVersion); const version = getVersion(serverVersion);
const releasedFeatures = RELEASE_FEATURES[version] || []; let releasedFeatures = RELEASE_FEATURES[version];
if (!releasedFeatures) {
const fallback = latestMinorVersion(version);
releasedFeatures = RELEASE_FEATURES[fallback];
}
return releasedFeatures.includes(featureKey); return releasedFeatures.includes(featureKey);
}; };
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
set -e
set -x
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
cd $(dirname $0)/..
echo "Bootstrapping..."
yarn --pure-lockfile install
source scripts/version
echo "BRANCH: ${COMMIT_BRANCH:-<none>}"
echo "TAG: ${GIT_TAG:-<none>}"
DIR=${GIT_TAG:-$COMMIT_BRANCH}
if [[ "${DIR}" == "main" ]]; then
DIR="latest"
fi
OUTPUT_DIR=dist/${DIR}-embedded
echo "Building..."
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=$OUTPUT_DIR ROUTER_BASE='/dashboard/' RESOURCE_BASE='/dashboard/' RANCHER_ENV=harvester yarn run build
if [ -v EMBED_PKG ]; then
echo "Build and embed plugin from: $EMBED_PKG"
PKG_FILE_NAME=${EMBED_PKG##*/}
echo PKG_FILE_NAME: $PKG_FILE_NAME
PKG_NAME="${PKG_FILE_NAME/.tar.gz/""}"
echo "Plugin name: '$PKG_NAME'"
# Fetch file, unpack and move to dist
curl $EMBED_PKG --output $PKG_FILE_NAME
OUTPUT_DIR_PKG=$OUTPUT_DIR/$PKG_NAME
mkdir -p $OUTPUT_DIR_PKG
tar xvfz $PKG_FILE_NAME -C $OUTPUT_DIR/$PKG_NAME
echo "Plugin contents that will be served from $PKG_NAME"
ls -alR $OUTPUT_DIR/$PKG_NAME
fi
echo "Destroying..."
find $OUTPUT_DIR -name "index.html" -mindepth 2 -exec rm {} \;
find $OUTPUT_DIR -type d -empty -depth -exec rmdir {} \;
TARBALL=${DIR}.tar.gz
TARBALL_FILE_PATH=dist/${TARBALL}
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "BUILD_EMBEDED_TGZ=${TARBALL_FILE_PATH}" >> "$ENV_OUTPUT"
echo "Compressing to ${TARBALL}..."
tar -czf ${TARBALL_FILE_PATH} $OUTPUT_DIR/
echo "Cleaning up..."
rm -r $OUTPUT_DIR
ls -alR dist/
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
set -e
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
cd $(dirname $0)/..
echo "Bootstrapping..."
yarn --pure-lockfile install
source scripts/version
echo "BRANCH: ${COMMIT_BRANCH:-<none>}"
echo "TAG: ${GIT_TAG:-<none>}"
DIR=${GIT_TAG:-$COMMIT_BRANCH}
if [[ "${DIR}" == "main" ]]; then
DIR="latest"
fi
BASE=${BASE:-https://releases.rancher.com/harvester-ui/dashboard/${DIR}}
echo "Building for ${BASE}..."
OUTPUT_DIR=dist/${DIR}
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "BUILD_HOSTED_DIR=${OUTPUT_DIR}" >> "$ENV_OUTPUT"
echo "BUILD_HOSTED_LOCATION=${DIR}" >> "$ENV_OUTPUT"
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=${OUTPUT_DIR} ROUTER_BASE="/dashboard/" RESOURCE_BASE="${BASE}" RANCHER_ENV=harvester yarn run build
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
BASE_DIR="$( cd $SCRIPT_DIR && cd ../.. & pwd)"
SHELL_DIR=$BASE_DIR/shell/
EXIT_CODE=0
FORMATS="umd-min"
while getopts "df:" opt; do
case $opt in
d)
FORMATS="umd"
;;
f)
FORMATS=$OPTARG
;;
esac
done
shift $((OPTIND-1))
# Use shell folder in node modules when we have @rancher/shell installed as a node module
# rather than the use-case of the mono-repo with the shell folder at the top-level
if [ ! -d ${SHELL_DIR} ]; then
SHELL_DIR=$BASE_DIR/node_modules/@rancher/shell/
SHELL_DIR=$(cd -P ${SHELL_DIR} && pwd)
fi
CREATE_TARBALL=${2}
if [ -z "$VERSION" ]; then
VERSION=$(cd pkg/$1; node -p -e "require('./package.json').version")
fi
NAME=${1}-${VERSION}
PKG_DIST=${BASE_DIR}/dist-pkg/${NAME}
if [ -d "${BASE_DIR}/pkg/${1}" ]; then
echo "Building UI Package $1"
echo " Package name: ${NAME}"
echo " Package version: ${VERSION}"
echo " Output formats: ${FORMATS}"
echo " Output directory: ${PKG_DIST}"
rm -rf ${PKG_DIST}
mkdir -p ${PKG_DIST}
pushd pkg/${1}
# Check that the .shell link exists and points to the correct place
if [ -e ".shell" ]; then
LINK=$(readlink .shell)
if [ "${LINK}" != "${SHELL_DIR}" ]; then
echo ".shell symlink exists but does not point to expected location - please check and fix"
popd
exit -1
fi
else
ln -s ${SHELL_DIR} .shell
fi
FILE=index.js
if [ -f ./index.ts ]; then
FILE=index.ts
fi
if [ -n "$COMMIT" ]; then
echo ${COMMIT} > ${PKG_DIST}/version
fi
${BASE_DIR}/node_modules/.bin/vue-cli-service build --name ${NAME} --target lib ${FILE} --dest ${PKG_DIST} --formats ${FORMATS} --filename ${NAME}
EXIT_CODE=$?
cp -f ./package.json ${PKG_DIST}/package.json
node ${SCRIPT_DIR}/pkgfile.js ${PKG_DIST}/package.json
rm -rf ${PKG_DIST}/*.bak
rm .shell
popd
fi
if [ $EXIT_CODE -ne 0 ]; then
exit $EXIT_CODE
fi
if [ -n "${CREATE_TARBALL}" ]; then
echo $COMMIT $COMMIT_BRANCH > ${PKG_DIST}/version-commit.txt
TARBALL=${NAME}.tar.gz
pushd ${PKG_DIST}
rm -f ../$TARBALL
echo "Compressing to ${TARBALL}..."
tar -czf ../${TARBALL} .
popd
fi
exit $EXIT_CODE
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
set -e
cd $(dirname $0)/..
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
if [[ -n "$CI_BUILD_TAG" ]]; then
echo "Build has been triggered by a tag. Skipping gate"
exit 0
fi
if [[ -z "$CI_BRANCH" ]]; then
echo "No branch detected. Skipping gate"
exit 0
fi
if [[ -z "$GIT_REPO" ]]; then
echo "No repository detected. Unable to gate"
exit 1
fi
if [[ -z "$GIT_COMMIT" ]]; then
echo "No commit detected. Unable to gate"
exit 1
fi
echo "Repo: $GIT_REPO"
echo "Branch: $CI_BRANCH"
echo "Build Commit: $GIT_COMMIT"
tmp=$(mktemp -u)
STATUS_CODE=$(curl -w "%{http_code}" -s -o $tmp https://api.github.com/repos/$GIT_REPO/branches/$CI_BRANCH)
if [ "$STATUS_CODE" == "403" ]; then
RATE_LIMIT_REMAINING=$(curl -s https://api.github.com/rate_limit | ./scripts/jq-nano - rate remaining)
echo "Remaining GITHUB requests available: $RATE_LIMIT_REMAINING"
RATE_LIMIT_REMAINING=${RATE_LIMIT_REMAINING:-0}
if ((RATE_LIMIT_REMAINING < 1)); then
echo "Github Rate Limit has been hit, skipping gate"
exit 0
fi
# Fall through to the normal path like any other failed status code
fi
LATEST_BRANCH_COMMIT=$(cat $tmp | ./scripts/jq-nano - commit sha)
rm $tmp
echo "Latest Branch Commit: $LATEST_BRANCH_COMMIT"
if [ -z "$LATEST_BRANCH_COMMIT" ]; then
echo "Unable to determine latest commit, failing gate"
exit 1
fi
if [ "$LATEST_BRANCH_COMMIT" == "$GIT_COMMIT" ]; then
echo "Build was created from latest commit, passed upload gate"
else
echo "Build was not created from latest commit, failing gate"
exit 1
fi
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
yarn --pure-lockfile install
source scripts/version
if [[ $COMMIT_BRANCH == "main" ]]; then
VERSION="latest"
else
VERSION=$COMMIT_BRANCH
fi
echo "CI_BUILD_TAG: ${CI_BUILD_TAG}"
echo "GIT_TAG: ${GIT_TAG}"
echo "TAG_VERSION: ${TAG_VERSION}"
echo "CI Build Args"
echo "COMMIT: ${COMMIT}"
echo "COMMIT_BRANCH: ${COMMIT_BRANCH}"
echo "VERSION: ${VERSION}"
if [ -n "$GIT_TAG" ]; then
COMMIT=$COMMIT COMMIT_BRANCH=$COMMIT_BRANCH VERSION=$CI_BUILD_TAG ./scripts/build-pkg.sh ${1} "true"
else
COMMIT=$COMMIT COMMIT_BRANCH=$COMMIT_BRANCH VERSION=$VERSION ./scripts/build-pkg.sh ${1} "true"
fi
EXIT_CODE=$?
if [ -n "$GIT_TAG" ]; then
export PKG_NAME=${1}-${CI_BUILD_TAG}
export PKG_TARBALL=${PKG_NAME}.tar.gz
else
export PKG_NAME=${1}-${VERSION} # harvester-release-harvester-v1.5 or harvester-latest
export PKG_TARBALL=${PKG_NAME}.tar.gz # harvester-release-harvester-v1.5.tar.gz or harvester-latest.tar.gz
fi
echo "CI Build Artifacts"
echo "Package Directory: ${PKG_NAME}"
echo "Package Tarball: ${PKG_TARBALL}"
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "PKG_TARBALL=${PKG_TARBALL}" >> "$ENV_OUTPUT"
echo "PKG_NAME=${PKG_NAME}" >> "$ENV_OUTPUT"
exit $EXIT_CODE
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env node
const fs = require('fs');
const readline = require('readline');
const args = process.argv.slice(2);
const file = args.shift();
let text;
if ( file === '-' ) {
process.stdin.resume();
text = fs.readFileSync(0, "utf8");
} else {
text = fs.readFileSync(file, "utf8");
}
const data = JSON.parse(text);
let out = data;
while ( args.length ) {
out = out[args.shift()];
}
console.log(out);
+24
View File
@@ -0,0 +1,24 @@
const fs = require('fs');
console.log('Updating package file'); // eslint-disable-line no-console
if (process.argv.length !== 3) {
console.error('No enough args'); // eslint-disable-line no-console
return;
}
const pkgFilepath = process.argv[process.argv.length - 1];
const pkg = require(pkgFilepath);
// Ensure we have the keys we need
pkg.files = ['**/*'];
pkg.rancher = true;
pkg.main = `${ pkg.name }-${ pkg.version }.umd.min.js`;
delete pkg.scripts;
delete pkg.browserslist;
fs.writeFileSync(pkgFilepath, JSON.stringify(pkg, null, 2));
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
shopt -s extglob
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
DIRTY="-dirty"
fi
COMMIT=$(git rev-parse --short HEAD)
COMMIT_DATE=$(git --no-pager log -1 --format='%ct')
COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD | sed -E 's/[^a-zA-Z0-9.-]+/-/g')
GIT_TAG=${CI_BUILD_TAG:-$(git tag -l --contains HEAD | head -n 1)}
LAST_TAG=${GIT_TAG:-'v0.0.0'}
if [[ -z "$DIRTY" && -n "$GIT_TAG" ]]; then
# human readable version used on rancher dashboard about page
export DASHBOARD_VERSION=$GIT_TAG
# computer readable version
VERSION=$GIT_TAG
else
# human readable version used on rancher dashboard about page
export DASHBOARD_VERSION="${COMMIT_BRANCH} ${COMMIT}"
# computer readable version
VERSION="${COMMIT}${DIRTY}"
fi
# Chart tag.
if [[ -z "${DIRTY}" && -n "${GIT_TAG}" ]]; then
CHART_VERSION="${GIT_TAG}"
elif [[ "$DIRTY" ]]; then
CHART_VERSION="${LAST_TAG}${DIRTY}.${COMMIT}"
else
CHART_VERSION="${LAST_TAG}-${COMMIT_DATE}.${COMMIT}.${COMMIT_BRANCH}"
fi
# Drop the v prefix for Chart Version to follow existing pattern.
CHART_VERSION="$(echo ${CHART_VERSION} | sed -E 's/^v//' | sed -e 's/^\(.\{55\}\).*/\1/')"
# Chart Repo - Target Repo for releases.
case $CHART_VERSION in
*-alpha*) # All alpha tags
CHART_REPO="alpha" ;;
*-rc*) # All rc tags
CHART_REPO="latest" ;;
+([0-9]).+([0-9]).+([0-9])) # All release tags
CHART_REPO="latest" ;;
*) # Anything else - Future use
CHART_REPO="dev" ;;
esac
if [ -z "$ARCH" ]; then
ARCH=amd64
fi
echo "ARCH: $ARCH"
echo "CHART_REPO: $CHART_REPO"
echo "CHART_VERSION: $CHART_VERSION"
echo "VERSION: $VERSION"
+163 -186
View File
@@ -1466,6 +1466,15 @@
"@babel/highlight" "^7.24.7" "@babel/highlight" "^7.24.7"
picocolors "^1.0.0" picocolors "^1.0.0"
"@babel/code-frame@^7.26.2":
version "7.26.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
dependencies:
"@babel/helper-validator-identifier" "^7.25.9"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4": "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4":
version "7.25.4" version "7.25.4"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb"
@@ -1502,6 +1511,17 @@
"@jridgewell/trace-mapping" "^0.3.25" "@jridgewell/trace-mapping" "^0.3.25"
jsesc "^2.5.1" jsesc "^2.5.1"
"@babel/generator@^7.26.10":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.10.tgz#a60d9de49caca16744e6340c3658dfef6138c3f7"
integrity sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==
dependencies:
"@babel/parser" "^7.26.10"
"@babel/types" "^7.26.10"
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^3.0.2"
"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.24.7": "@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab"
@@ -1509,6 +1529,13 @@
dependencies: dependencies:
"@babel/types" "^7.24.7" "@babel/types" "^7.24.7"
"@babel/helper-annotate-as-pure@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4"
integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==
dependencies:
"@babel/types" "^7.25.9"
"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": "@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3"
@@ -1541,6 +1568,19 @@
"@babel/traverse" "^7.25.4" "@babel/traverse" "^7.25.4"
semver "^6.3.1" semver "^6.3.1"
"@babel/helper-create-class-features-plugin@^7.25.9":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71"
integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.25.9"
"@babel/helper-member-expression-to-functions" "^7.25.9"
"@babel/helper-optimise-call-expression" "^7.25.9"
"@babel/helper-replace-supers" "^7.26.5"
"@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
"@babel/traverse" "^7.26.9"
semver "^6.3.1"
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0", "@babel/helper-create-regexp-features-plugin@^7.25.2": "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0", "@babel/helper-create-regexp-features-plugin@^7.25.2":
version "7.25.2" version "7.25.2"
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9"
@@ -1569,6 +1609,14 @@
"@babel/traverse" "^7.24.8" "@babel/traverse" "^7.24.8"
"@babel/types" "^7.24.8" "@babel/types" "^7.24.8"
"@babel/helper-member-expression-to-functions@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3"
integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==
dependencies:
"@babel/traverse" "^7.25.9"
"@babel/types" "^7.25.9"
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.24.7": "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b"
@@ -1601,11 +1649,23 @@
dependencies: dependencies:
"@babel/types" "^7.24.7" "@babel/types" "^7.24.7"
"@babel/helper-optimise-call-expression@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e"
integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==
dependencies:
"@babel/types" "^7.25.9"
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
version "7.24.8" version "7.24.8"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878"
integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==
"@babel/helper-plugin-utils@^7.25.9":
version "7.26.5"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35"
integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==
"@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0": "@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0":
version "7.25.0" version "7.25.0"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz#d2f0fbba059a42d68e5e378feaf181ef6055365e" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz#d2f0fbba059a42d68e5e378feaf181ef6055365e"
@@ -1624,6 +1684,15 @@
"@babel/helper-optimise-call-expression" "^7.24.7" "@babel/helper-optimise-call-expression" "^7.24.7"
"@babel/traverse" "^7.25.0" "@babel/traverse" "^7.25.0"
"@babel/helper-replace-supers@^7.26.5":
version "7.26.5"
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d"
integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.25.9"
"@babel/helper-optimise-call-expression" "^7.25.9"
"@babel/traverse" "^7.26.5"
"@babel/helper-simple-access@^7.24.7": "@babel/helper-simple-access@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3"
@@ -1640,16 +1709,34 @@
"@babel/traverse" "^7.24.7" "@babel/traverse" "^7.24.7"
"@babel/types" "^7.24.7" "@babel/types" "^7.24.7"
"@babel/helper-skip-transparent-expression-wrappers@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9"
integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==
dependencies:
"@babel/traverse" "^7.25.9"
"@babel/types" "^7.25.9"
"@babel/helper-string-parser@^7.24.8": "@babel/helper-string-parser@^7.24.8":
version "7.24.8" version "7.24.8"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d"
integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
"@babel/helper-string-parser@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
"@babel/helper-validator-identifier@^7.24.7": "@babel/helper-validator-identifier@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
"@babel/helper-validator-identifier@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.24.8": "@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.24.8":
version "7.24.8" version "7.24.8"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d"
@@ -1689,6 +1776,13 @@
dependencies: dependencies:
"@babel/types" "^7.25.6" "@babel/types" "^7.25.6"
"@babel/parser@^7.26.10", "@babel/parser@^7.26.9":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749"
integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==
dependencies:
"@babel/types" "^7.26.10"
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3":
version "7.25.3" version "7.25.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f"
@@ -1980,6 +2074,14 @@
"@babel/helper-create-class-features-plugin" "^7.25.4" "@babel/helper-create-class-features-plugin" "^7.25.4"
"@babel/helper-plugin-utils" "^7.24.8" "@babel/helper-plugin-utils" "^7.24.8"
"@babel/plugin-transform-class-static-block@7.26.0":
version "7.26.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0"
integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==
dependencies:
"@babel/helper-create-class-features-plugin" "^7.25.9"
"@babel/helper-plugin-utils" "^7.25.9"
"@babel/plugin-transform-class-static-block@^7.24.7": "@babel/plugin-transform-class-static-block@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d"
@@ -2460,7 +2562,7 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.12.13", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4": "@babel/runtime@^7.12.13", "@babel/runtime@^7.8.4":
version "7.25.6" version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2"
integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ== integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==
@@ -2476,6 +2578,15 @@
"@babel/parser" "^7.25.0" "@babel/parser" "^7.25.0"
"@babel/types" "^7.25.0" "@babel/types" "^7.25.0"
"@babel/template@^7.26.9":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2"
integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==
dependencies:
"@babel/code-frame" "^7.26.2"
"@babel/parser" "^7.26.9"
"@babel/types" "^7.26.9"
"@babel/traverse@^7.23.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": "@babel/traverse@^7.23.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
version "7.25.6" version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41"
@@ -2489,6 +2600,19 @@
debug "^4.3.1" debug "^4.3.1"
globals "^11.1.0" globals "^11.1.0"
"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.10.tgz#43cca33d76005dbaa93024fae536cc1946a4c380"
integrity sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==
dependencies:
"@babel/code-frame" "^7.26.2"
"@babel/generator" "^7.26.10"
"@babel/parser" "^7.26.10"
"@babel/template" "^7.26.9"
"@babel/types" "^7.26.10"
debug "^4.3.1"
globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
version "7.25.6" version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.6.tgz#893942ddb858f32ae7a004ec9d3a76b3463ef8e6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.6.tgz#893942ddb858f32ae7a004ec9d3a76b3463ef8e6"
@@ -2498,6 +2622,14 @@
"@babel/helper-validator-identifier" "^7.24.7" "@babel/helper-validator-identifier" "^7.24.7"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.26.9":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259"
integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==
dependencies:
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
"@bcoe/v8-coverage@^0.2.3": "@bcoe/v8-coverage@^0.2.3":
version "0.2.3" version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@@ -2915,24 +3047,6 @@
resolved "https://registry.yarnpkg.com/@novnc/novnc/-/novnc-1.2.0.tgz#535ffd7d074022d35205deae2753100f1f2b29f3" resolved "https://registry.yarnpkg.com/@novnc/novnc/-/novnc-1.2.0.tgz#535ffd7d074022d35205deae2753100f1f2b29f3"
integrity sha512-FaUckOedGhSbwQBXk/KGyxKt9ngskg4wPw6ghbHWXOUEmQscAZr3467lTU5DSfppwHJt5k+lQiHoeYUuY90l2Q== integrity sha512-FaUckOedGhSbwQBXk/KGyxKt9ngskg4wPw6ghbHWXOUEmQscAZr3467lTU5DSfppwHJt5k+lQiHoeYUuY90l2Q==
"@nuxtjs/axios@5.13.6":
version "5.13.6"
resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.13.6.tgz#6f4bbd98a3a7799a5d2c0726c6ad2a98aa111881"
integrity sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA==
dependencies:
"@nuxtjs/proxy" "^2.1.0"
axios "^0.21.1"
axios-retry "^3.1.9"
consola "^2.15.3"
defu "^5.0.0"
"@nuxtjs/proxy@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@nuxtjs/proxy/-/proxy-2.1.0.tgz#fa7715a11d237fa1273503c4e9e137dd1bf5575b"
integrity sha512-/qtoeqXgZ4Mg6LRg/gDUZQrFpOlOdHrol/vQYMnKu3aN3bP90UfOUB3QSDghUUK7OISAJ0xp8Ld78aHyCTcKCQ==
dependencies:
http-proxy-middleware "^1.0.6"
"@one-ini/wasm@0.1.1": "@one-ini/wasm@0.1.1":
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323"
@@ -2958,10 +3072,10 @@
resolved "https://registry.yarnpkg.com/@rancher/icons/-/icons-2.0.29.tgz#6546d69768c706bebd66bfa73b36aef3d105987a" resolved "https://registry.yarnpkg.com/@rancher/icons/-/icons-2.0.29.tgz#6546d69768c706bebd66bfa73b36aef3d105987a"
integrity sha512-qBBqfazS9y5VjV7fJDPNXmxd9AP/2uiE05mKFWP41kpbO+tEb62RnUBXCm14XLeScDZQcOuiAKVHMmvCFzF0BA== integrity sha512-qBBqfazS9y5VjV7fJDPNXmxd9AP/2uiE05mKFWP41kpbO+tEb62RnUBXCm14XLeScDZQcOuiAKVHMmvCFzF0BA==
"@rancher/shell@3.0.1-rc.1": "@rancher/shell@3.0.1-rc.4":
version "3.0.1-rc.1" version "3.0.1-rc.4"
resolved "https://registry.yarnpkg.com/@rancher/shell/-/shell-3.0.1-rc.1.tgz#db3abc5e5160daffce4e42b113f7d38c025041b2" resolved "https://registry.yarnpkg.com/@rancher/shell/-/shell-3.0.1-rc.4.tgz#d5b57a0184a89be09e7d4d21472545b3306d23d5"
integrity sha512-1h245vyOaFXVHPdeSre4laCguXZijeIEQp31Yse0YV1KaHjNM7WZZRvLk3CqASrOtpVEGQ3W/vZO3qWLSQMJ9A== integrity sha512-cTBLjn7iysSi86XgptWDi8ErarVyPh6yRrRfBefQrxhMeCJNy3aH40neO37zJO/0e99/YBe4bRsr6Z2NV9TqBA==
dependencies: dependencies:
"@aws-sdk/client-ec2" "3.658.1" "@aws-sdk/client-ec2" "3.658.1"
"@aws-sdk/client-eks" "3.1.0" "@aws-sdk/client-eks" "3.1.0"
@@ -2972,7 +3086,6 @@
"@babel/plugin-proposal-private-property-in-object" "7.14.5" "@babel/plugin-proposal-private-property-in-object" "7.14.5"
"@babel/preset-typescript" "7.16.7" "@babel/preset-typescript" "7.16.7"
"@novnc/novnc" "1.2.0" "@novnc/novnc" "1.2.0"
"@nuxtjs/axios" "5.13.6"
"@popperjs/core" "2.4.4" "@popperjs/core" "2.4.4"
"@rancher/icons" "2.0.29" "@rancher/icons" "2.0.29"
"@types/is-url" "1.2.30" "@types/is-url" "1.2.30"
@@ -2987,6 +3100,8 @@
"@vue/vue3-jest" "^27.0.0-alpha.1" "@vue/vue3-jest" "^27.0.0-alpha.1"
add "2.0.6" add "2.0.6"
ansi_up "5.0.0" ansi_up "5.0.0"
axios "0.21.4"
axios-retry "3.1.9"
babel-eslint "10.1.0" babel-eslint "10.1.0"
babel-plugin-module-resolver "4.0.0" babel-plugin-module-resolver "4.0.0"
babel-preset-vue "2.0.2" babel-preset-vue "2.0.2"
@@ -3009,6 +3124,7 @@
d3-selection "1.4.1" d3-selection "1.4.1"
dagre-d3 "0.6.4" dagre-d3 "0.6.4"
dayjs "1.8.29" dayjs "1.8.29"
defu "5.0.1"
diff2html "3.4.24" diff2html "3.4.24"
dompurify "2.5.4" dompurify "2.5.4"
element-matches "^0.1.2" element-matches "^0.1.2"
@@ -3065,7 +3181,6 @@
vue-router "4.4.3" vue-router "4.4.3"
vue-select "4.0.0-beta.6" vue-select "4.0.0-beta.6"
vue-server-renderer "2.7.16" vue-server-renderer "2.7.16"
vue-template-compiler "2.7.16"
vue3-resize "0.2.0" vue3-resize "0.2.0"
vue3-virtual-scroll-list "0.2.1" vue3-virtual-scroll-list "0.2.1"
vuedraggable "4.1.0" vuedraggable "4.1.0"
@@ -3698,7 +3813,7 @@
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
"@types/http-proxy@^1.17.5", "@types/http-proxy@^1.17.8": "@types/http-proxy@^1.17.8":
version "1.17.15" version "1.17.15"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.15.tgz#12118141ce9775a6499ecb4c01d02f90fc839d36" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.15.tgz#12118141ce9775a6499ecb4c01d02f90fc839d36"
integrity sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ== integrity sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==
@@ -4330,17 +4445,6 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
source-map-js "^1.2.0" source-map-js "^1.2.0"
"@vue/compiler-core@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.7.tgz#04300bdc9fb52f89e6f250bbac16e03f0e0ed914"
integrity sha512-A0gay3lK71MddsSnGlBxRPOugIVdACze9L/rCo5X5srCyjQfZOfYtSFMJc3aOZCM+xN55EQpb4R97rYn/iEbSw==
dependencies:
"@babel/parser" "^7.25.3"
"@vue/shared" "3.5.7"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@3.2.47": "@vue/compiler-dom@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305"
@@ -4365,14 +4469,6 @@
"@vue/compiler-core" "3.5.1" "@vue/compiler-core" "3.5.1"
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
"@vue/compiler-dom@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.7.tgz#604ced082189b66cb811068332a45dcc11ae0af3"
integrity sha512-GYWl3+gO8/g0ZdYaJ18fYHdI/WVic2VuuUd1NsPp60DWXKy+XjdhFsDW7FbUto8siYYZcosBGn9yVBkjhq1M8Q==
dependencies:
"@vue/compiler-core" "3.5.7"
"@vue/shared" "3.5.7"
"@vue/compiler-sfc@3.2.47": "@vue/compiler-sfc@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d"
@@ -4404,21 +4500,6 @@
postcss "^8.4.44" postcss "^8.4.44"
source-map-js "^1.2.0" source-map-js "^1.2.0"
"@vue/compiler-sfc@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.7.tgz#1150c49c0e3b39d40b2cf0f7de9edfcba98fa3e9"
integrity sha512-EjOJtCWJrC7HqoCEzOwpIYHm+JH7YmkxC1hG6VkqIukYRqj8KFUlTLK6hcT4nGgtVov2+ZfrdrRlcaqS78HnBA==
dependencies:
"@babel/parser" "^7.25.3"
"@vue/compiler-core" "3.5.7"
"@vue/compiler-dom" "3.5.7"
"@vue/compiler-ssr" "3.5.7"
"@vue/shared" "3.5.7"
estree-walker "^2.0.2"
magic-string "^0.30.11"
postcss "^8.4.47"
source-map-js "^1.2.0"
"@vue/compiler-sfc@^3.4.15": "@vue/compiler-sfc@^3.4.15":
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.0.tgz#dc1e34a331d5deea9e258a1e10e1b4d711b1afd6" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.0.tgz#dc1e34a331d5deea9e258a1e10e1b4d711b1afd6"
@@ -4458,14 +4539,6 @@
"@vue/compiler-dom" "3.5.1" "@vue/compiler-dom" "3.5.1"
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
"@vue/compiler-ssr@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.7.tgz#042144dfd574a1f64b685e87730b0196dc1846d2"
integrity sha512-oZx+jXP2k5arV/8Ly3TpQbfFyimMw2ANrRqvHJoKjPqtEzazxQGZjCLOfq8TnZ3wy2TOXdqfmVp4q7FyYeHV4g==
dependencies:
"@vue/compiler-dom" "3.5.7"
"@vue/shared" "3.5.7"
"@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.3.0": "@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.3.0":
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz#f9f5fb53464b0c37b2c8d2f3fbfe44df60f61dc9" resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz#f9f5fb53464b0c37b2c8d2f3fbfe44df60f61dc9"
@@ -4512,13 +4585,6 @@
dependencies: dependencies:
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
"@vue/reactivity@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.7.tgz#a52237fce841d92fc861220a8f26b51f5c3245e2"
integrity sha512-yF0EpokpOHRNXyn/h6abXc9JFIzfdAf0MJHIi92xxCWS0mqrXH6+2aZ+A6EbSrspGzX5MHTd5N8iBA28HnXu9g==
dependencies:
"@vue/shared" "3.5.7"
"@vue/runtime-core@3.2.47": "@vue/runtime-core@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d"
@@ -4535,14 +4601,6 @@
"@vue/reactivity" "3.5.1" "@vue/reactivity" "3.5.1"
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
"@vue/runtime-core@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.7.tgz#4181b0a921d331f2efd5eda9aa35549ac97e6530"
integrity sha512-OzLpBpKbZEaZVSNfd+hQbfBrDKux+b7Yl5hYhhWWWhHD7fEpF+CdI3Brm5k5GsufHEfvMcjruPxwQZuBN6nFYQ==
dependencies:
"@vue/reactivity" "3.5.7"
"@vue/shared" "3.5.7"
"@vue/runtime-dom@3.2.47": "@vue/runtime-dom@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382" resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382"
@@ -4562,16 +4620,6 @@
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
csstype "^3.1.3" csstype "^3.1.3"
"@vue/runtime-dom@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.7.tgz#646e006d403f2e6337f566fdf461fbe400e8487d"
integrity sha512-fL7cETfE27U2jyTgqzE382IGFY6a6uyznErn27KbbEzNctzxxUWYDbaN3B55l9nXh0xW2LRWPuWKOvjtO2UewQ==
dependencies:
"@vue/reactivity" "3.5.7"
"@vue/runtime-core" "3.5.7"
"@vue/shared" "3.5.7"
csstype "^3.1.3"
"@vue/server-renderer@3.2.47": "@vue/server-renderer@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0" resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0"
@@ -4588,14 +4636,6 @@
"@vue/compiler-ssr" "3.5.1" "@vue/compiler-ssr" "3.5.1"
"@vue/shared" "3.5.1" "@vue/shared" "3.5.1"
"@vue/server-renderer@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.7.tgz#65ba8b60c0ee9e791619c0f8b2b6209a258484e5"
integrity sha512-peRypij815eIDjpPpPXvYQGYqPH6QXwLJGWraJYPPn8JqWGl29A8QXnS7/Mh3TkMiOcdsJNhbFCoW2Agc2NgAQ==
dependencies:
"@vue/compiler-ssr" "3.5.7"
"@vue/shared" "3.5.7"
"@vue/shared@3.2.47": "@vue/shared@3.2.47":
version "3.2.47" version "3.2.47"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c"
@@ -4611,11 +4651,6 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.1.tgz#f9418dae5ac194a4f19023d812978c21a15412a1" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.1.tgz#f9418dae5ac194a4f19023d812978c21a15412a1"
integrity sha512-NdcTRoO4KuW2RSFgpE2c+E/R/ZHaRzWPxAGxhmxZaaqLh6nYCXx7lc9a88ioqOCxCaV2SFJmujkxbUScW7dNsQ== integrity sha512-NdcTRoO4KuW2RSFgpE2c+E/R/ZHaRzWPxAGxhmxZaaqLh6nYCXx7lc9a88ioqOCxCaV2SFJmujkxbUScW7dNsQ==
"@vue/shared@3.5.7":
version "3.5.7"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.7.tgz#1eedd1ffbf804c488fe806a17ff26c22e0ddb72f"
integrity sha512-NBE1PBIvzIedxIc2RZiKXvGbJkrZ2/hLf3h8GlS4/sP9xcXEZMFWOazFkNd6aGeUCMaproe5MHVYB3/4AW9q9g==
"@vue/test-utils@~2.0.0-0": "@vue/test-utils@~2.0.0-0":
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.2.tgz#0b5edd683366153d5bc5a91edc62f292118710eb" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.2.tgz#0b5edd683366153d5bc5a91edc62f292118710eb"
@@ -5201,15 +5236,14 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef"
integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==
axios-retry@^3.1.9: axios-retry@3.1.9:
version "3.9.1" version "3.1.9"
resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.9.1.tgz#c8924a8781c8e0a2c5244abf773deb7566b3830d" resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.1.9.tgz#6c30fc9aeb4519aebaec758b90ef56fa03fe72e8"
integrity sha512-8PJDLJv7qTTMMwdnbMvrLYuvB47M81wRtxQmEdV5w4rgbTXTt+vtPkXwajOfOdSyv/wZICJOC+/UhXH4aQ/R+w== integrity sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA==
dependencies: dependencies:
"@babel/runtime" "^7.15.4" is-retry-allowed "^1.1.0"
is-retry-allowed "^2.2.0"
axios@^0.21.1: axios@0.21.4, axios@^0.21.1:
version "0.21.4" version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
@@ -6110,11 +6144,6 @@ connect-history-api-fallback@^2.0.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8"
integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==
consola@^2.15.3:
version "2.15.3"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
console-browserify@^1.2.0: console-browserify@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
@@ -7129,11 +7158,6 @@ dayjs@^1.10.4, dayjs@^1.11.3:
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
debounce@^1.2.1: debounce@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
@@ -7241,7 +7265,7 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
has-property-descriptors "^1.0.0" has-property-descriptors "^1.0.0"
object-keys "^1.1.1" object-keys "^1.1.1"
defu@^5.0.0: defu@5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/defu/-/defu-5.0.1.tgz#a034278f9b032bf0845d261aa75e9ad98da878ac" resolved "https://registry.yarnpkg.com/defu/-/defu-5.0.1.tgz#a034278f9b032bf0845d261aa75e9ad98da878ac"
integrity sha512-EPS1carKg+dkEVy3qNTqIdp2qV7mUP08nIsupfwQpz++slCVRw7qbQyWvSTig+kFPwz2XXp5/kIIkH+CwrJKkQ== integrity sha512-EPS1carKg+dkEVy3qNTqIdp2qV7mUP08nIsupfwQpz++slCVRw7qbQyWvSTig+kFPwz2XXp5/kIIkH+CwrJKkQ==
@@ -9039,17 +9063,6 @@ http-proxy-agent@^4.0.1:
agent-base "6" agent-base "6"
debug "4" debug "4"
http-proxy-middleware@^1.0.6:
version "1.3.1"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665"
integrity sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==
dependencies:
"@types/http-proxy" "^1.17.5"
http-proxy "^1.18.1"
is-glob "^4.0.1"
is-plain-obj "^3.0.0"
micromatch "^4.0.2"
http-proxy-middleware@^2.0.3: http-proxy-middleware@^2.0.3:
version "2.0.6" version "2.0.6"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f"
@@ -9474,10 +9487,10 @@ is-regex@^1.1.4:
call-bind "^1.0.2" call-bind "^1.0.2"
has-tostringtag "^1.0.0" has-tostringtag "^1.0.0"
is-retry-allowed@^2.2.0: is-retry-allowed@^1.1.0:
version "2.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz#88f34cbd236e043e71b6932d09b0c65fb7b4d71d" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
integrity sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg== integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3:
version "1.0.3" version "1.0.3"
@@ -10215,6 +10228,11 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
jsesc@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
jsesc@~0.5.0: jsesc@~0.5.0:
version "0.5.0" version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
@@ -11565,7 +11583,7 @@ picocolors@^0.2.1:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0: picocolors@^1.0.0, picocolors@^1.0.1:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59"
integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==
@@ -11901,15 +11919,6 @@ postcss@^8.1.10, postcss@^8.2.6, postcss@^8.3.5, postcss@^8.4.19, postcss@^8.4.3
picocolors "^1.0.1" picocolors "^1.0.1"
source-map-js "^1.2.0" source-map-js "^1.2.0"
postcss@^8.4.47:
version "8.4.47"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365"
integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==
dependencies:
nanoid "^3.3.7"
picocolors "^1.1.0"
source-map-js "^1.2.1"
prelude-ls@^1.2.1: prelude-ls@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -12844,34 +12853,16 @@ sockjs@^0.3.24:
uuid "^8.3.2" uuid "^8.3.2"
websocket-driver "^0.7.4" websocket-driver "^0.7.4"
sortablejs-vue3@^1.2.11:
version "1.2.11"
resolved "https://registry.yarnpkg.com/sortablejs-vue3/-/sortablejs-vue3-1.2.11.tgz#c04f767253a03862a5445d310b335d9fdab71261"
integrity sha512-oKOA6N7yu2ktmqYXPHlPTQWbe9G4v16mn5ewogb+Ybc9Bk1Y+MIURrpbgedEv7f9TS5Bptvh81HGjazh5FEyJw==
dependencies:
sortablejs "^1.15.0"
vue "^3.3.7"
sortablejs@1.14.0: sortablejs@1.14.0:
version "1.14.0" version "1.14.0"
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8" resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w== integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==
sortablejs@^1.15.0:
version "1.15.3"
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.3.tgz#033668db5ebfb11167d1249ab88e748f27959e29"
integrity sha512-zdK3/kwwAK1cJgy1rwl1YtNTbRmc8qW/+vgXf75A7NHag5of4pyI6uK86ktmQETyWRH7IGaE73uZOOBcGxgqZg==
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0: "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.20: source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.20:
version "0.5.21" version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -13856,6 +13847,11 @@ vue-demi@*:
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
vue-draggable-next@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/vue-draggable-next/-/vue-draggable-next-2.2.1.tgz#adbe98c74610cca8f4eb63f92042681f96920451"
integrity sha512-EAMS1IRHF0kZO0o5PMOinsQsXIqsrKT1hKmbICxG3UEtn7zLFkLxlAtajcCcUTisNvQ6TtCB5COjD9a1raNADw==
vue-eslint-parser@^9.0.1: vue-eslint-parser@^9.0.1:
version "9.4.3" version "9.4.3"
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8" resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8"
@@ -13922,14 +13918,6 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.3:
hash-sum "^1.0.2" hash-sum "^1.0.2"
loader-utils "^1.0.2" loader-utils "^1.0.2"
vue-template-compiler@2.7.16:
version "2.7.16"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz#c81b2d47753264c77ac03b9966a46637482bb03b"
integrity sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==
dependencies:
de-indent "^1.0.2"
he "^1.2.0"
vue-template-es2015-compiler@^1.9.0: vue-template-es2015-compiler@^1.9.0:
version "1.9.1" version "1.9.1"
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
@@ -13945,17 +13933,6 @@ vue3-virtual-scroll-list@0.2.1:
resolved "https://registry.yarnpkg.com/vue3-virtual-scroll-list/-/vue3-virtual-scroll-list-0.2.1.tgz#7fdc5be066c9b8d877614626a0bc02eb1fd12ad0" resolved "https://registry.yarnpkg.com/vue3-virtual-scroll-list/-/vue3-virtual-scroll-list-0.2.1.tgz#7fdc5be066c9b8d877614626a0bc02eb1fd12ad0"
integrity sha512-G4KxITUOy9D4ro15zOp40D6ogmMefzjIyMsBKqN3xGbV1P6dlKYMx+BBXCKm3Nr/6iipcUKM272Sh2AJRyWMyQ== integrity sha512-G4KxITUOy9D4ro15zOp40D6ogmMefzjIyMsBKqN3xGbV1P6dlKYMx+BBXCKm3Nr/6iipcUKM272Sh2AJRyWMyQ==
vue@^3.3.7:
version "3.5.7"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.7.tgz#511df1fab33a4c20cfe6b59659d6f601f0c26625"
integrity sha512-JcFm0f5j8DQO9E07pZRxqZ/ZsNopMVzHYXpKvnfqXFcA4JTi+4YcrikRn9wkzWsdj0YsLzlLIsR0zzGxA2P6Wg==
dependencies:
"@vue/compiler-dom" "3.5.7"
"@vue/compiler-sfc" "3.5.7"
"@vue/runtime-dom" "3.5.7"
"@vue/server-renderer" "3.5.7"
"@vue/shared" "3.5.7"
vue@^3.4.31: vue@^3.4.31:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.1.tgz#507eb4ab010a2ad894f8d7765f32e68be1604815" resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.1.tgz#507eb4ab010a2ad894f8d7765f32e68be1604815"