Merge remote-tracking branch 'upstream/master' into pagination-extensions-resource-enable

This commit is contained in:
Richard Cox 2025-10-03 09:25:12 +01:00
commit c87d218c36
20 changed files with 153 additions and 96 deletions

View File

@ -12,7 +12,7 @@ class ResourcePanelPo extends ComponentPo {
}
stateBadge(state: string) {
return this.self().find(`.bg-${ state }`);
return this.self().find(`.badge.bg-${ state }`);
}
}
@ -32,6 +32,14 @@ class ExpandedPanelPo extends ComponentPo {
tablePanel() {
return new TablePanelPo(this.self(), this.workspace);
}
gitReposFilter() {
return CheckboxInputPo.byLabel(this.self(), 'Show Git Repos');
}
helmOpsFilter() {
return CheckboxInputPo.byLabel(this.self(), 'Show Helm Ops');
}
}
class CardPanelPo extends ComponentPo {
@ -43,14 +51,6 @@ class CardPanelPo extends ComponentPo {
this.workspace = workspace;
}
gitReposFilter() {
return CheckboxInputPo.byLabel(this.self(), 'Show Git Repos');
}
helmOpsFilter() {
return CheckboxInputPo.byLabel(this.self(), 'Show Helm Ops');
}
statePanel(stateDisplay) {
return new StatePanelPo(`[data-testid="state-panel-${ stateDisplay }"]`, this.self(), this.workspace);
}
@ -76,11 +76,11 @@ class StatePanelPo extends ComponentPo {
}
title() {
return this.self().find(`.title .label`);
return this.self().find('.title .state-title');
}
card(name) {
return this.self().find(`[data-testid="card-${ this.workspace }/${ name }"]`);
card(name: string) {
return this.self().find(`[data-testid="item-card-header-title"]`).contains(name);
}
}
@ -102,6 +102,6 @@ export default class FleetDashboardWorkspaceCardPo extends ComponentPo {
}
expandButton() {
return this.self().find('[data-testid="expand-button"]');
return this.self().find(`[data-testid="workspace-expand-btn-${ this.workspace }"]`);
}
}

View File

@ -41,7 +41,7 @@ export class FleetDashboardListPagePo extends BaseListPagePo {
}
slideInPanel() {
return cy.get('[data-testid="slide-in-panel-component"] [data-testid="fleet-dashboard-resource-details-header"]');
return cy.get('[data-testid="slide-in-panel-component"]');
}
fleetDashboardEmptyState() {

View File

@ -100,15 +100,16 @@ describe('Fleet Dashboard', { tags: ['@fleet', '@adminUser', '@jenkins'] }, () =
expandButton.should('be.visible');
expandButton.click();
const cardsPanel = workspaceCard.expandedPanel().cardsPanel();
const expandedPanel = workspaceCard.expandedPanel();
const cardsPanel = expandedPanel.cardsPanel();
cardsPanel.self().should('be.visible');
cardsPanel.gitReposFilter().checkVisible();
cardsPanel.gitReposFilter().isChecked();
expandedPanel.gitReposFilter().checkVisible();
expandedPanel.gitReposFilter().isChecked();
cardsPanel.helmOpsFilter().checkVisible();
cardsPanel.helmOpsFilter().isChecked();
expandedPanel.helmOpsFilter().checkVisible();
expandedPanel.helmOpsFilter().isChecked();
const activeStatePanel = cardsPanel.statePanel('Active');
@ -117,10 +118,7 @@ describe('Fleet Dashboard', { tags: ['@fleet', '@adminUser', '@jenkins'] }, () =
activeStatePanel.title().should('contain.text', '/1');
activeStatePanel.title().click();
const card = activeStatePanel.card(repoName);
card.should('be.visible');
card.find('.title').should('contain.text', repoName);
activeStatePanel.card(repoName).should('be.visible');
});
it('Should filter by GitRepo type', () => {
@ -132,9 +130,10 @@ describe('Fleet Dashboard', { tags: ['@fleet', '@adminUser', '@jenkins'] }, () =
expandButton.click();
const cardsPanel = workspaceCard.expandedPanel().cardsPanel();
const expandedPanel = workspaceCard.expandedPanel();
const cardsPanel = expandedPanel.cardsPanel();
cardsPanel.gitReposFilter().set();
expandedPanel.gitReposFilter().set();
const activeStatePanel = cardsPanel.statePanel('Active');
activeStatePanel.self().should('not.be.visible');
@ -151,16 +150,16 @@ describe('Fleet Dashboard', { tags: ['@fleet', '@adminUser', '@jenkins'] }, () =
const cardsPanel = workspaceCard.expandedPanel().cardsPanel();
cardsPanel.checkExists();
cardsPanel.self().should('be.visible');
// click 'card' mode
// click 'table' mode (first button is table mode)
fleetDashboardPage.viewModeButton().self().find('[data-testid="button-group-child-0"]').click();
cardsPanel.checkNotExists();
const tablePanel = workspaceCard.expandedPanel().tablePanel();
tablePanel.checkExists();
tablePanel.checkVisible();
});
it('Should open slide-in panel', () => {
@ -202,10 +201,12 @@ describe('Fleet Dashboard', { tags: ['@fleet', '@adminUser', '@jenkins'] }, () =
const activeStatePanel = cardsPanel.statePanel('Active');
activeStatePanel.title().click();
activeStatePanel.card(repoName).should('be.visible').click();
const card = activeStatePanel.card(repoName);
const details = fleetDashboardPage.slideInPanel();
card.find('.title a').click();
details.should('be.visible');
details.find('.title').should('contain.text', repoName).click();
appDetails.waitForPage(null, 'bundles');
});

View File

@ -13,12 +13,12 @@ This method adds a table column to a `ResourceTable` element-based table on the
Method:
```ts
plugin.addTableColumn(where: String, when: LocationConfig, options: Object);
plugin.addTableColumn(where: String, when: LocationConfig, column: TableColumn);
```
_Arguments_
`where` string parameter admissable values for this method:
`where` string parameter admissible values for this method:
| Key | Type | Description |
|---|---|---|
@ -26,28 +26,35 @@ _Arguments_
<br/>
`when` Object admissable values:
`when` Object admissible values:
`LocationConfig` as described above for the [LocationConfig object](./common#locationconfig).
<br/>
<br/>
*(Rancher version v2.13.0)*
### TableColumnLocation.RESOURCE options
An addition parameter can be provided which will be used to support the column when server-side pagination is enabled. For more information and other changes required to server-side pagination see [here](../performance/scaling/lists.md).
```ts
plugin.addTableColumn(where: String, when: LocationConfig, column: TableColumn, paginationColumn?: PaginationTableColumn));
```
### TableColumnLocation.RESOURCE column
![Table Col](../screenshots/table-cols.png)
`options` config object. Admissable parameters for the `options` with `'TableColumnLocation.RESOURCE'` are:
`column` config object. Admissible parameters for the `column` with `'TableColumnLocation.RESOURCE'` are:
| Key | Type | Description |
|---|---|---|
|`name`| String | Label for column |
|`labelKey`| String | Same as "name" but allows for translation. Will superseed "name" |
|`labelKey`| String | Same as "name" but allows for translation. Will supersede "name" |
|`value`| String | Object property to obtain the value from |
|`getValue`| Fuction | Same as "value", but it can be a function. Will superseed "value" |
|`getValue`| Function | Same as "value", but it can be a function. Will supersede "value" |
|`width`| Int | Column width (in `px`). Optional |
|`sort`| Array | Object properties to be bound to the table sorting. Optional |
|`search`| Array | Object properties to be bound to the table search. Optional |
|`sort`| boolean,string,Array | Object properties to be bound to the table sorting. Optional |
|`search`| boolean,string,Array | Object properties to be bound to the table search. Optional |
| `formatter`| string | Name of a `formatter` component used to render the cell. Components should be in the extension `formatters` folder
| `formatterOpts`| any | Provide additional values to the `formatter` component via a `formatterOpts` component param
Usage example for `'TableColumnLocation.RESOURCE'`:

View File

@ -97,7 +97,7 @@
"express": "4.17.1",
"file-saver": "2.0.2",
"floating-vue": "5.2.2",
"focus-trap": "7.6.2",
"focus-trap": "7.6.5",
"https": "1.0.0",
"identicon.js": "2.3.3",
"intl-messageformat": "7.8.4",

View File

@ -20,6 +20,8 @@ type FilterOption = {
componentProps?: Record<string, unknown>;
/** Label to show next to the checkbox, or a custom component next to the checkbox */
label?: string | { component: ComponentType; componentProps: Record<string, unknown>; };
/** Tooltip to be displayed above the checkbox on hover */
labelTooltip?: string;
};
/**
@ -97,7 +99,12 @@ const updateFilter = (key: string, value: string[]) => {
@update:value="updateFilter(filter.key, $event)"
>
<template #label>
<span v-if="typeof option.label === 'string'">{{ option.label }}</span>
<span
v-if="typeof option.label === 'string'"
v-clean-tooltip="{content: option.labelTooltip, delay: { show: 1000 }}"
>
{{ option.label }}
</span>
<component
:is="option.label.component"
v-else

View File

@ -2,6 +2,7 @@
import { defineComponent } from 'vue';
import ResourceFetch from '@shell/mixins/resource-fetch';
import ResourceTable from '@shell/components/ResourceTable.vue';
import { VuexStore } from '@shell/types/store/vuex';
/**
* This is meant to enable ResourceList like capabilities outside of List pages / components
@ -130,13 +131,17 @@ export default defineComponent({
safeHeaders(): any[] {
const customHeaders: any[] = this.canPaginate ? this.paginationHeaders : this.headers;
return customHeaders || this.$store.getters['type-map/headersFor'](this.schema, this.canPaginate);
const $store = this.$store as VuexStore;
return customHeaders || $store.getters['type-map/headersFor'](this.schema, this.canPaginate);
}
},
methods: {
clearSelection() {
this.$refs.table.clearSelection();
const table = this.$refs.table as { clearSelection: () => void };
table.clearSelection();
},
}
});

View File

@ -384,6 +384,7 @@ export default {
>
<span
v-clean-html="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) }, true)"
class="confirm-text"
/>
</div>
</div>
@ -472,5 +473,9 @@ export default {
flex: 1;
}
}
.confirm-text b {
user-select: all;
}
}
</style>

View File

@ -1,7 +1,7 @@
<script lang="ts">
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
import ClusterRepo from '@shell/models/catalog.cattle.io.clusterrepo';
import { RancherKubeMetadata } from '@shell/types/kube/kube-api';
import { PaginationArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
import { defineComponent } from 'vue';
@ -25,7 +25,7 @@ export default defineComponent({
/**
* Filter out hidden repos from list of all repos
*/
filterRowsLocal(rows: ClusterRepo[]) {
filterRowsLocal(rows: { metadata: RancherKubeMetadata}[]) {
return rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
},

View File

@ -93,7 +93,7 @@
"express": "4.17.1",
"file-saver": "2.0.2",
"floating-vue": "5.2.2",
"focus-trap": "7.6.2",
"focus-trap": "7.6.5",
"frontmatter-markdown-loader": "3.7.0",
"identicon.js": "2.3.3",
"intl-messageformat": "7.8.4",

View File

@ -80,6 +80,12 @@ function onClickItem(type: string, label: string) {
&-text {
text-transform: capitalize;
margin-right: 8px;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
&-icon {

View File

@ -2,9 +2,9 @@
defineProps<{
label: string;
icon: string;
icon?: string;
iconColor?: string;
tooltip?: string;
iconTooltip?: string;
}>();
</script>
@ -13,7 +13,8 @@ defineProps<{
<div class="status-label">
{{ label }}
<i
v-clean-tooltip.right="tooltip"
v-if="!!icon"
v-clean-tooltip.right="iconTooltip"
:class="['icon', icon, iconColor]"
/>
</div>

View File

@ -82,10 +82,10 @@ export default {
label: {
component: markRaw(StatusLabel),
componentProps: {
label: this.t('generic.installed'),
icon: 'icon-warning',
iconColor: 'warning',
tooltip: this.t('catalog.charts.statusFilterCautions.installation')
label: this.t('generic.installed'),
icon: 'icon-warning',
iconColor: 'warning',
iconTooltip: this.t('catalog.charts.statusFilterCautions.installation')
}
}
},
@ -98,10 +98,10 @@ export default {
label: {
component: markRaw(StatusLabel),
componentProps: {
label: this.t('generic.upgradeable'),
icon: 'icon-warning',
iconColor: 'warning',
tooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
label: this.t('generic.upgradeable'),
icon: 'icon-warning',
iconColor: 'warning',
iconTooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
}
}
}
@ -125,9 +125,10 @@ export default {
repoOptions() {
let out = this.$store.getters['catalog/repos'].map((r) => {
return {
value: r._key,
label: r.nameDisplay,
weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
value: r._key,
label: r.nameDisplay,
labelTooltip: r.nameDisplay,
weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
};
});

View File

@ -98,12 +98,11 @@ createTestComponent() {
# Add test list component to the test package
# Validates rancher-components imports
# NOTE - This fails if importing some components with TS imports...
# cp ${SHELL_DIR}/list/catalog.cattle.io.clusterrepo.vue pkg/test-pkg/list
# See https://github.com/rancher/dashboard/issues/12918
# Use a basic list instead
# Basic list instead
cp ${SHELL_DIR}/list/namespace.vue pkg/test-pkg/list
# More complex list
cp ${SHELL_DIR}/list/catalog.cattle.io.clusterrepo.vue pkg/test-pkg/list
}
# Publish shell pkg (tag is needed as publish-shell is optimized to work with release-shell-pkg workflow)

View File

@ -39,6 +39,8 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/steve/hybrid-class.js --d
# # mixins
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/create-edit-view/index.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins/create-edit-view > /dev/null
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch-namespaced.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch-api-pagination.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
# # models
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/models/namespace.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/models/ > /dev/null

View File

@ -10,7 +10,8 @@ export interface VuexStoreGetters {
export interface VuexStore {
getters: VuexStoreGetters,
dispatch: any,
dispatch: <T = any>(action: string, payload?: any) => Promise<T>,
commit: (mutation: string, payload?: any) => void,
// When we have exact properties above we can remove below
[name:string]: any

View File

@ -1,5 +1,6 @@
/* eslint-disable */
import type ShellApi from '@shell/plugins/internal-api/shell/shell.api';
import { VuexStore } from '@shell/types/store/vuex';
export {};
@ -13,11 +14,7 @@ declare module 'vue' {
(key: string, args?: Record<string, any>, raw?: boolean): string;
(options: { k: string; raw?: boolean; tag?: string | Record<string, any>; escapehtml?: boolean }): string;
},
$store: {
getters: Record<string, any>,
dispatch: (action: string, payload?: any) => Promise<any>,
commit: (mutation: string, payload?: any) => void,
},
$store: VuexStore,
$shell: ShellApi,
}
}

View File

@ -20,6 +20,7 @@ import { VuexStore } from '@shell/types/store/vuex';
import { ServerSidePaginationExtensionConfig } from '@shell/core/types';
import { EXT_IDS } from '@shell/core/plugin';
import { ExtensionManager } from '@shell/types/extension-manager';
import { DEFAULT_PERF_SETTING } from '@shell/config/settings';
/**
* Helper functions for server side pagination
@ -47,7 +48,15 @@ class PaginationUtils {
public getStoreSettings(arg: any | PaginationSettings): PaginationSettingsStores {
const serverPagination: PaginationSettings = arg?.rootGetters !== undefined ? this.getSettings(arg) : arg;
return serverPagination?.useDefaultStores ? this.getStoreDefault() : serverPagination?.stores || this.getStoreDefault();
// Ensure we use the current default store settings if
// 1. from 2.11.0 user saved `ui-performance` setting and it's applied the default pagination settings containing useDefaultStores
// 2. before 2.11.0 user has saved `ui-performance` setting and it's applied an obsolete pagination settings that lack useDefaultStore
// 3. user has manually set the `ui-performance` pagination setting useDefaultStores value
if (serverPagination?.useDefaultStores || serverPagination?.useDefaultStores === undefined) {
return this.getStoreDefault();
}
return serverPagination?.stores || this.getStoreDefault();
}
public getStoreDefault(): PaginationSettingsStores {
@ -227,7 +236,7 @@ class PaginationUtils {
resourceChangesDebounceMs({ rootGetters }: any): number | undefined {
const settings = this.getSettings({ rootGetters });
return settings.resourceChangesDebounceMs;
return settings.resourceChangesDebounceMs || DEFAULT_PERF_SETTING.serverPagination.resourceChangesDebounceMs;
}
validateNsProjectFilters(nsProjectFilters: string[]) {

View File

@ -7737,10 +7737,10 @@ floating-vue@5.2.2:
"@floating-ui/dom" "~1.1.1"
vue-resize "^2.0.0-alpha.1"
focus-trap@7.6.2:
version "7.6.2"
resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.2.tgz#a501988821ca23d0150a7229eb7a20a3695bdf0e"
integrity sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==
focus-trap@7.6.5:
version "7.6.5"
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.6.5.tgz#56f0814286d43c1a2688e9bc4f31f17ae047fb76"
integrity sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==
dependencies:
tabbable "^6.2.0"
@ -12268,15 +12268,7 @@ setprototypeof@1.2.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.11"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
sha.js@^2.4.11:
sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8:
version "2.4.12"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f"
integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==

View File

@ -7812,7 +7812,6 @@ eslint-plugin-jest@24.4.0:
"eslint-plugin-local-rules@link:./eslint-plugin-local-rules":
version "0.0.0"
uid ""
"eslint-plugin-local-rules@link:eslint-plugin-local-rules":
version "0.0.0"
@ -8522,10 +8521,10 @@ flush-promises@1.0.2:
resolved "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz#4948fd58f15281fed79cbafc86293d5bb09b2ced"
integrity sha512-G0sYfLQERwKz4+4iOZYQEZVpOt9zQrlItIxQAAYAWpfby3gbHrx0osCHz5RLl/XoXevXk0xoN4hDFky/VV9TrA==
focus-trap@7.6.2:
version "7.6.2"
resolved "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.2.tgz#a501988821ca23d0150a7229eb7a20a3695bdf0e"
integrity sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==
focus-trap@7.6.5:
version "7.6.5"
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.6.5.tgz#56f0814286d43c1a2688e9bc4f31f17ae047fb76"
integrity sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==
dependencies:
tabbable "^6.2.0"
@ -14226,7 +14225,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -14243,6 +14242,15 @@ string-width@^2.1.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
@ -14317,7 +14325,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -14338,6 +14346,13 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@ -15673,7 +15688,7 @@ worker-loader@3.0.8:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -15699,6 +15714,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"