Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8adcfcf54 | |||
| 1c5caeb987 | |||
| 71a65e1f80 | |||
| ec12176220 | |||
| 0cf4f7c4de | |||
| b0785e506f | |||
| 5f8668b3aa |
@@ -544,7 +544,7 @@
|
||||
"name": "area/provisioning",
|
||||
"action": "addToProject",
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/599"
|
||||
"url": "https://github.com/orgs/grafana/projects/835"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -744,7 +744,7 @@
|
||||
"name": "area/backend/db/sql",
|
||||
"action": "addToProject",
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/599"
|
||||
"url": "https://github.com/orgs/grafana/projects/835"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -960,7 +960,7 @@
|
||||
"name": "area/backend/db/sqlite",
|
||||
"action": "addToProject",
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/599"
|
||||
"url": "https://github.com/orgs/grafana/projects/835"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
diff --git a/dist/builder-manager/index.js b/dist/builder-manager/index.js
|
||||
index 3d7f9b213dae1801bda62b31db31b9113e382ccd..212501c63d20146c29db63fb0f6300c6779eecb5 100644
|
||||
index ac8ac6a5f6a3b7852c4064e93dc9acd3201289e6..34a0a5a5c38dd7fe525c9ebd382a10a451d4d4f3 100644
|
||||
--- a/dist/builder-manager/index.js
|
||||
+++ b/dist/builder-manager/index.js
|
||||
@@ -1970,7 +1970,7 @@ var pa = /^\/($|\?)/, G, C, xt = /* @__PURE__ */ o(async (e) => {
|
||||
@@ -1974,7 +1974,7 @@ var pa = /^\/($|\?)/, G, C, xt = /* @__PURE__ */ o(async (e) => {
|
||||
bundle: !0,
|
||||
minify: !0,
|
||||
sourcemap: !1,
|
||||
@@ -2281,3 +2281,10 @@ allow_image_rendering = true
|
||||
# will check if there has been any changes to the repository not propagated by a webhook.
|
||||
# The minimum value is 10 seconds.
|
||||
min_sync_interval = 10s
|
||||
|
||||
#################################### Unified Storage ####################################
|
||||
[unified_storage]
|
||||
# index_path is the path where unified storage can store its index files for search.
|
||||
# If empty, defaults to "<data_dir>/unified-search/bleve" (see [paths] section).
|
||||
# Please note that sharing the same index_path between multiple running Grafana instances is not supported.
|
||||
index_path =
|
||||
|
||||
@@ -186,7 +186,7 @@ For the JSON and field usage notes, refer to the [links schema documentation](ht
|
||||
|
||||
### `tags`
|
||||
|
||||
The tags associated with the dashboard:
|
||||
Tags associated with the dashboard. Each tag can be up to 50 characters long.
|
||||
|
||||
` [...string]`
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ Query parameters:
|
||||
- `sortDirection`: Sort order of elements. Use `alpha-asc` for ascending and `alpha-desc` for descending sort order.
|
||||
- `typeFilter`: A comma separated list of types to filter the elements by.
|
||||
- `excludeUid`: Element UID to exclude from search results.
|
||||
- `folderFilter`: A comma separated list of folder IDs to filter the elements by.
|
||||
- `folderFilter`: **Deprecated.** A comma separated list of folder IDs to filter the elements by. Use `folderFilterUIDs` instead.
|
||||
- `folderFilterUIDs`: A comma separated list of folder UIDs to filter the elements by.
|
||||
- `perPage`: The number of results per page; default is 100.
|
||||
- `page`: The page for a set of records, given that only `perPage` records are returned at a time. Numbering starts at `1`.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Keys:
|
||||
- **theme** - One of: `light`, `dark`, or an empty string for the default theme
|
||||
- **homeDashboardId** - Deprecated. Use `homeDashboardUID` instead.
|
||||
- **homeDashboardUID**: The `:uid` of a dashboard
|
||||
- **timezone** - One of: `utc`, `browser`, or an empty string for the default
|
||||
- **timezone** - Any valid IANA timezone string (e.g., `America/New_York`, `Europe/London`), `utc`, `browser`, or an empty string for the default.
|
||||
|
||||
Omitting a key will cause the current value to be replaced with the
|
||||
system default value.
|
||||
|
||||
+1
-1
@@ -462,7 +462,7 @@
|
||||
"js-yaml@npm:4.1.0": "^4.1.0",
|
||||
"js-yaml@npm:=4.1.0": "^4.1.0",
|
||||
"nodemailer": "7.0.11",
|
||||
"@storybook/core@npm:8.6.2": "patch:@storybook/core@npm%3A8.6.2#~/.yarn/patches/@storybook-core-npm-8.6.2-8c752112c0.patch"
|
||||
"@storybook/core@npm:8.6.15": "patch:@storybook/core@npm%3A8.6.15#~/.yarn/patches/@storybook-core-npm-8.6.15-a468a35170.patch"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
||||
@@ -1021,6 +1021,7 @@ const injectedRtkApi = api
|
||||
typeFilter: queryArg.typeFilter,
|
||||
excludeUid: queryArg.excludeUid,
|
||||
folderFilter: queryArg.folderFilter,
|
||||
folderFilterUIDs: queryArg.folderFilterUiDs,
|
||||
perPage: queryArg.perPage,
|
||||
page: queryArg.page,
|
||||
},
|
||||
@@ -2915,8 +2916,11 @@ export type GetLibraryElementsApiArg = {
|
||||
typeFilter?: string;
|
||||
/** Element UID to exclude from search results. */
|
||||
excludeUid?: string;
|
||||
/** A comma separated list of folder ID(s) to filter the elements by. */
|
||||
/** A comma separated list of folder ID(s) to filter the elements by.
|
||||
Deprecated: Use FolderFilterUIDs instead. */
|
||||
folderFilter?: string;
|
||||
/** A comma separated list of folder UID(s) to filter the elements by. */
|
||||
folderFilterUiDs?: string;
|
||||
/** The number of results per page. */
|
||||
perPage?: number;
|
||||
/** The page for a set of records, given that only perPage records are returned at a time. Numbering starts at 1. */
|
||||
@@ -5312,7 +5316,8 @@ export type PatchPrefsCmd = {
|
||||
queryHistory?: QueryHistoryPreference;
|
||||
regionalFormat?: string;
|
||||
theme?: 'light' | 'dark';
|
||||
timezone?: 'utc' | 'browser';
|
||||
/** Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string */
|
||||
timezone?: string;
|
||||
weekStart?: string;
|
||||
};
|
||||
export type UpdatePrefsCmd = {
|
||||
@@ -5325,7 +5330,8 @@ export type UpdatePrefsCmd = {
|
||||
queryHistory?: QueryHistoryPreference;
|
||||
regionalFormat?: string;
|
||||
theme?: 'light' | 'dark' | 'system';
|
||||
timezone?: 'utc' | 'browser';
|
||||
/** Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string */
|
||||
timezone?: string;
|
||||
weekStart?: string;
|
||||
};
|
||||
export type OrgUserDto = {
|
||||
|
||||
+4
-2
@@ -86,7 +86,8 @@ export type PatchPrefsCmd = {
|
||||
queryHistory?: QueryHistoryPreference;
|
||||
regionalFormat?: string;
|
||||
theme?: 'light' | 'dark';
|
||||
timezone?: 'utc' | 'browser';
|
||||
/** Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string */
|
||||
timezone?: string;
|
||||
weekStart?: string;
|
||||
};
|
||||
export type UpdatePrefsCmd = {
|
||||
@@ -99,7 +100,8 @@ export type UpdatePrefsCmd = {
|
||||
queryHistory?: QueryHistoryPreference;
|
||||
regionalFormat?: string;
|
||||
theme?: 'light' | 'dark' | 'system';
|
||||
timezone?: 'utc' | 'browser';
|
||||
/** Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string */
|
||||
timezone?: string;
|
||||
weekStart?: string;
|
||||
};
|
||||
export const {
|
||||
|
||||
@@ -137,23 +137,23 @@
|
||||
"@babel/core": "7.28.0",
|
||||
"@faker-js/faker": "^9.0.0",
|
||||
"@rollup/plugin-node-resolve": "16.0.1",
|
||||
"@storybook/addon-a11y": "^8.6.2",
|
||||
"@storybook/addon-actions": "^8.6.2",
|
||||
"@storybook/addon-docs": "^8.6.2",
|
||||
"@storybook/addon-essentials": "^8.6.2",
|
||||
"@storybook/addon-storysource": "^8.6.2",
|
||||
"@storybook/addon-a11y": "^8.6.15",
|
||||
"@storybook/addon-actions": "^8.6.15",
|
||||
"@storybook/addon-docs": "^8.6.15",
|
||||
"@storybook/addon-essentials": "^8.6.15",
|
||||
"@storybook/addon-storysource": "^8.6.15",
|
||||
"@storybook/addon-webpack5-compiler-swc": "^2.1.0",
|
||||
"@storybook/blocks": "^8.6.2",
|
||||
"@storybook/components": "^8.6.2",
|
||||
"@storybook/core-events": "^8.6.2",
|
||||
"@storybook/manager-api": "^8.6.2",
|
||||
"@storybook/blocks": "^8.6.15",
|
||||
"@storybook/components": "^8.6.15",
|
||||
"@storybook/core-events": "^8.6.15",
|
||||
"@storybook/manager-api": "^8.6.15",
|
||||
"@storybook/mdx2-csf": "1.1.0",
|
||||
"@storybook/preset-scss": "1.0.3",
|
||||
"@storybook/preview-api": "^8.6.2",
|
||||
"@storybook/react": "^8.6.2",
|
||||
"@storybook/react-webpack5": "^8.6.2",
|
||||
"@storybook/preview-api": "^8.6.15",
|
||||
"@storybook/react": "^8.6.15",
|
||||
"@storybook/react-webpack5": "^8.6.15",
|
||||
"@storybook/test-runner": "^0.23.0",
|
||||
"@storybook/theming": "^8.6.2",
|
||||
"@storybook/theming": "^8.6.15",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
"@testing-library/jest-dom": "6.6.4",
|
||||
"@testing-library/react": "16.3.0",
|
||||
@@ -200,7 +200,7 @@
|
||||
"rollup-plugin-node-externals": "^8.0.0",
|
||||
"rollup-plugin-svg-import": "3.0.0",
|
||||
"sass-loader": "16.0.5",
|
||||
"storybook": "^8.6.2",
|
||||
"storybook": "^8.6.15",
|
||||
"style-loader": "4.0.0",
|
||||
"typescript": "5.9.2",
|
||||
"webpack": "5.101.0"
|
||||
|
||||
@@ -54,6 +54,7 @@ export const TagsInput = forwardRef<HTMLInputElement, Props>(
|
||||
const [newTagName, setNewTagName] = useState('');
|
||||
const styles = useStyles2(getStyles);
|
||||
const theme = useTheme2();
|
||||
const isTagTooLong = newTagName.length > 50;
|
||||
|
||||
const onNameChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setNewTagName(event.target.value);
|
||||
@@ -65,6 +66,9 @@ export const TagsInput = forwardRef<HTMLInputElement, Props>(
|
||||
|
||||
const onAdd = (event?: React.MouseEvent | React.KeyboardEvent) => {
|
||||
event?.preventDefault();
|
||||
if (newTagName.length > 50) {
|
||||
return;
|
||||
}
|
||||
if (!tags.includes(newTagName)) {
|
||||
onChange(tags.concat(newTagName));
|
||||
}
|
||||
@@ -94,14 +98,17 @@ export const TagsInput = forwardRef<HTMLInputElement, Props>(
|
||||
value={newTagName}
|
||||
onKeyDown={onKeyboardAdd}
|
||||
onBlur={onBlur}
|
||||
invalid={invalid}
|
||||
invalid={invalid || isTagTooLong}
|
||||
suffix={
|
||||
<Button
|
||||
fill="text"
|
||||
className={styles.addButtonStyle}
|
||||
onClick={onAdd}
|
||||
size="md"
|
||||
disabled={newTagName.length <= 0}
|
||||
disabled={newTagName.length <= 0 || isTagTooLong}
|
||||
title={
|
||||
isTagTooLong ? t('grafana-ui.tags-input.tag-too-long', 'Tag too long, max 50 characters') : undefined
|
||||
}
|
||||
>
|
||||
<Trans i18nKey="grafana-ui.tags-input.add">Add</Trans>
|
||||
</Button>
|
||||
|
||||
@@ -13,7 +13,7 @@ type UpdatePrefsCmd struct {
|
||||
// Deprecated: Use HomeDashboardUID instead
|
||||
HomeDashboardID int64 `json:"homeDashboardId"`
|
||||
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
|
||||
// Enum: utc,browser
|
||||
// Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string
|
||||
Timezone string `json:"timezone"`
|
||||
WeekStart string `json:"weekStart"`
|
||||
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
|
||||
@@ -31,7 +31,7 @@ type PatchPrefsCmd struct {
|
||||
// Default:0
|
||||
// Deprecated: Use HomeDashboardUID instead
|
||||
HomeDashboardID *int64 `json:"homeDashboardId,omitempty"`
|
||||
// Enum: utc,browser
|
||||
// Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string
|
||||
Timezone *string `json:"timezone,omitempty"`
|
||||
WeekStart *string `json:"weekStart,omitempty"`
|
||||
Language *string `json:"language,omitempty"`
|
||||
|
||||
@@ -134,6 +134,10 @@ func (hs *HTTPServer) patchPreferencesFor(ctx context.Context, orgID, userID, te
|
||||
return response.Error(http.StatusBadRequest, "Invalid theme", nil)
|
||||
}
|
||||
|
||||
if dtoCmd.Timezone != nil && !pref.IsValidTimezone(*dtoCmd.Timezone) {
|
||||
return response.Error(http.StatusBadRequest, "Invalid timezone. Must be a valid IANA timezone (e.g., America/New_York), 'utc', 'browser', or empty string", nil)
|
||||
}
|
||||
|
||||
// convert dashboard UID to ID in order to store internally if it exists in the query, otherwise take the id from query
|
||||
// nolint:staticcheck
|
||||
dashboardID := dtoCmd.HomeDashboardID
|
||||
|
||||
@@ -389,6 +389,11 @@ func (b *DashboardsAPIBuilder) validateCreate(ctx context.Context, a admission.A
|
||||
return apierrors.NewBadRequest(err.Error())
|
||||
}
|
||||
|
||||
// Validate tags
|
||||
if err := validateDashboardTags(dashObj); err != nil {
|
||||
return apierrors.NewBadRequest(err.Error())
|
||||
}
|
||||
|
||||
id, err := identity.GetRequester(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting requester: %w", err)
|
||||
@@ -459,6 +464,11 @@ func (b *DashboardsAPIBuilder) validateUpdate(ctx context.Context, a admission.A
|
||||
return apierrors.NewBadRequest(err.Error())
|
||||
}
|
||||
|
||||
// Validate tags
|
||||
if err := validateDashboardTags(newDashObj); err != nil {
|
||||
return apierrors.NewBadRequest(err.Error())
|
||||
}
|
||||
|
||||
// Validate folder existence if specified and changed
|
||||
if !a.IsDryRun() && newAccessor.GetFolder() != oldAccessor.GetFolder() && newAccessor.GetFolder() != "" {
|
||||
id, err := identity.GetRequester(ctx)
|
||||
@@ -556,6 +566,32 @@ func getDashboardProperties(obj runtime.Object) (string, string, error) {
|
||||
return title, refresh, nil
|
||||
}
|
||||
|
||||
// validateDashboardTags validates that all dashboard tags are within the maximum length
|
||||
func validateDashboardTags(obj runtime.Object) error {
|
||||
var tags []string
|
||||
|
||||
switch d := obj.(type) {
|
||||
case *dashv0.Dashboard:
|
||||
tags = d.Spec.GetNestedStringSlice("tags")
|
||||
case *dashv1.Dashboard:
|
||||
tags = d.Spec.GetNestedStringSlice("tags")
|
||||
case *dashv2alpha1.Dashboard:
|
||||
tags = d.Spec.Tags
|
||||
case *dashv2beta1.Dashboard:
|
||||
tags = d.Spec.Tags
|
||||
default:
|
||||
return fmt.Errorf("unsupported dashboard version: %T", obj)
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if len(tag) > 50 {
|
||||
return dashboards.ErrDashboardTagTooLong
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *DashboardsAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupInfo, opts builder.APIGroupOptions) error {
|
||||
storageOpts := apistore.StorageOptions{
|
||||
EnableFolderSupport: true,
|
||||
|
||||
@@ -208,6 +208,11 @@ func (s *preferenceStorage) save(ctx context.Context, obj runtime.Object) (runti
|
||||
|
||||
// Create implements rest.Creater.
|
||||
func (s *preferenceStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
if createValidation != nil {
|
||||
if err := createValidation(ctx, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s.save(ctx, obj)
|
||||
}
|
||||
|
||||
@@ -223,6 +228,12 @@ func (s *preferenceStorage) Update(ctx context.Context, name string, objInfo res
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if updateValidation != nil {
|
||||
if err := updateValidation(ctx, obj, old); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
obj, err = s.save(ctx, obj)
|
||||
return obj, false, err
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package preferences
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
@@ -24,7 +29,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
_ builder.APIGroupBuilder = (*APIBuilder)(nil)
|
||||
_ builder.APIGroupBuilder = (*APIBuilder)(nil)
|
||||
_ builder.APIGroupValidation = (*APIBuilder)(nil)
|
||||
)
|
||||
|
||||
type APIBuilder struct {
|
||||
@@ -108,3 +114,31 @@ func (b *APIBuilder) GetAPIRoutes(gv schema.GroupVersion) *builder.APIRoutes {
|
||||
defs := b.GetOpenAPIDefinitions()(func(path string) spec.Ref { return spec.Ref{} })
|
||||
return b.merger.GetAPIRoutes(defs)
|
||||
}
|
||||
|
||||
// Validate validates that the preference object has valid theme and timezone (if specified)
|
||||
func (b *APIBuilder) Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
if a.GetResource().Resource != "preferences" {
|
||||
return nil
|
||||
}
|
||||
|
||||
op := a.GetOperation()
|
||||
if op != admission.Create && op != admission.Update {
|
||||
return nil
|
||||
}
|
||||
|
||||
obj := a.GetObject()
|
||||
p, ok := obj.(*preferences.Preferences)
|
||||
if !ok {
|
||||
return apierrors.NewBadRequest(fmt.Sprintf("expected Preferences object, got %T", obj))
|
||||
}
|
||||
|
||||
if p.Spec.Timezone != nil && !pref.IsValidTimezone(*p.Spec.Timezone) {
|
||||
return apierrors.NewBadRequest("invalid timezone: must be a valid IANA timezone (e.g., America/New_York), 'utc', 'browser', or empty string")
|
||||
}
|
||||
|
||||
if p.Spec.Theme != nil && *p.Spec.Theme != "" && !pref.IsValidThemeID(*p.Spec.Theme) {
|
||||
return apierrors.NewBadRequest("invalid theme")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -542,6 +542,9 @@ func (d *dashboardStore) saveDashboard(ctx context.Context, sess *db.Session, cm
|
||||
tags := dash.GetTags()
|
||||
if len(tags) > 0 {
|
||||
for _, tag := range tags {
|
||||
if len(tag) > 50 {
|
||||
return nil, dashboards.ErrDashboardTagTooLong
|
||||
}
|
||||
if _, err := sess.Insert(dashboardTag{DashboardId: dash.ID, Term: tag, OrgID: dash.OrgID, DashboardUID: dash.UID}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -79,6 +79,11 @@ var (
|
||||
Reason: "message too long, max 500 characters",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardTagTooLong = dashboardaccess.DashboardErr{
|
||||
Reason: "dashboard tag too long, max 50 characters",
|
||||
StatusCode: 400,
|
||||
Status: "tag-too-long",
|
||||
}
|
||||
ErrDashboardCannotSaveProvisionedDashboard = dashboardaccess.DashboardErr{
|
||||
Reason: "Cannot save provisioned dashboard",
|
||||
StatusCode: 400,
|
||||
|
||||
@@ -501,9 +501,15 @@ type GetLibraryElementsParams struct {
|
||||
// required:false
|
||||
ExcludeUID string `json:"excludeUid"`
|
||||
// A comma separated list of folder ID(s) to filter the elements by.
|
||||
// Deprecated: Use FolderFilterUIDs instead.
|
||||
// in:query
|
||||
// required:false
|
||||
// deprecated:true
|
||||
FolderFilter string `json:"folderFilter"`
|
||||
// A comma separated list of folder UID(s) to filter the elements by.
|
||||
// in:query
|
||||
// required:false
|
||||
FolderFilterUIDs string `json:"folderFilterUIDs"`
|
||||
// The number of results per page.
|
||||
// in:query
|
||||
// required:false
|
||||
|
||||
@@ -20,6 +20,10 @@ func UpdatePreferencesFor(ctx context.Context,
|
||||
return response.Error(http.StatusBadRequest, "Invalid theme", nil)
|
||||
}
|
||||
|
||||
if !pref.IsValidTimezone(dtoCmd.Timezone) {
|
||||
return response.Error(http.StatusBadRequest, "Invalid timezone. Must be a valid IANA timezone (e.g., America/New_York), 'utc', 'browser', or empty string", nil)
|
||||
}
|
||||
|
||||
// convert dashboard UID to ID in order to store internally if it exists in the query, otherwise take the id from query
|
||||
// nolint:staticcheck
|
||||
dashboardID := dtoCmd.HomeDashboardID
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package pref
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// IsValidTimezone checks if the timezone string is valid.
|
||||
// It accepts:
|
||||
// - "" - uses default
|
||||
// - "utc"
|
||||
// - "browser"
|
||||
// - Any valid IANA timezone (e.g., "America/New_York", "Europe/London")
|
||||
func IsValidTimezone(timezone string) bool {
|
||||
if timezone == "" || timezone == "utc" || timezone == "browser" {
|
||||
return true
|
||||
}
|
||||
|
||||
// try to load as IANA timezone
|
||||
_, err := time.LoadLocation(timezone)
|
||||
return err == nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package pref
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsValidTimezone(t *testing.T) {
|
||||
tests := []struct {
|
||||
timezone string
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
timezone: "utc",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
timezone: "browser",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
timezone: "Europe/London",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
timezone: "invalid",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
timezone: "",
|
||||
valid: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
assert.Equal(t, test.valid, IsValidTimezone(test.timezone))
|
||||
}
|
||||
}
|
||||
@@ -588,8 +588,10 @@ type Cfg struct {
|
||||
// Unified Storage
|
||||
UnifiedStorage map[string]UnifiedStorageConfig
|
||||
// DisableDataMigrations will disable resources data migration to unified storage at startup
|
||||
DisableDataMigrations bool
|
||||
MaxPageSizeBytes int
|
||||
DisableDataMigrations bool
|
||||
MaxPageSizeBytes int
|
||||
// IndexPath the directory where index files are stored.
|
||||
// Note: Bleve locks index files, so mounts cannot be shared between multiple instances.
|
||||
IndexPath string
|
||||
IndexWorkers int
|
||||
IndexRebuildWorkers int
|
||||
|
||||
@@ -45,7 +45,7 @@ import (
|
||||
const (
|
||||
indexStorageMemory = "memory"
|
||||
indexStorageFile = "file"
|
||||
boltTimeout = "500ms"
|
||||
boltTimeout = "1s"
|
||||
)
|
||||
|
||||
// Keys used to store internal data in index.
|
||||
@@ -417,25 +417,18 @@ func (b *bleveBackend) BuildIndex(
|
||||
// This happens on startup, or when memory-based index has expired. (We don't expire file-based indexes)
|
||||
// If we do have an unexpired cached index already, we always build a new index from scratch.
|
||||
if cachedIndex == nil && !rebuild {
|
||||
result := b.findPreviousFileBasedIndex(resourceDir)
|
||||
if result != nil && result.IsOpen {
|
||||
// Index file exists but is opened by another process, fallback to memory.
|
||||
// Keep the name so we can skip cleanup of that directory.
|
||||
newIndexType = indexStorageMemory
|
||||
fileIndexName = result.Name
|
||||
} else if result != nil && result.Index != nil {
|
||||
// Found and opened existing index successfully
|
||||
index = result.Index
|
||||
fileIndexName = result.Name
|
||||
indexRV = result.RV
|
||||
var findErr error
|
||||
index, fileIndexName, indexRV, findErr = b.findPreviousFileBasedIndex(resourceDir)
|
||||
if findErr != nil {
|
||||
return nil, findErr
|
||||
}
|
||||
}
|
||||
|
||||
if newIndexType == indexStorageFile && index != nil {
|
||||
if index != nil {
|
||||
build = false
|
||||
logWithDetails.Debug("Existing index found on filesystem", "indexRV", indexRV, "directory", filepath.Join(resourceDir, fileIndexName))
|
||||
defer closeIndexOnExit(index, "") // Close index, but don't delete directory.
|
||||
} else if newIndexType == indexStorageFile {
|
||||
} else {
|
||||
// Building index from scratch. Index name has a time component in it to be unique, but if
|
||||
// we happen to create non-unique name, we bump the time and try again.
|
||||
|
||||
@@ -462,9 +455,7 @@ func (b *bleveBackend) BuildIndex(
|
||||
logWithDetails.Info("Building index using filesystem", "directory", indexDir)
|
||||
defer closeIndexOnExit(index, indexDir) // Close index, and delete new index directory.
|
||||
}
|
||||
}
|
||||
|
||||
if newIndexType == indexStorageMemory {
|
||||
} else {
|
||||
index, err = newBleveIndex("", mapper, time.Now(), b.opts.BuildVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating new in-memory bleve index: %w", err)
|
||||
@@ -567,7 +558,7 @@ func cleanFileSegment(input string) string {
|
||||
return input
|
||||
}
|
||||
|
||||
// cleanOldIndexes deletes all subdirectories inside resourceDir, skipping directory with "skipName".
|
||||
// cleanOldIndexes deletes all subdirectories inside dir, skipping directory with "skipName".
|
||||
// "skipName" can be empty.
|
||||
func (b *bleveBackend) cleanOldIndexes(resourceDir string, skipName string) {
|
||||
entries, err := os.ReadDir(resourceDir)
|
||||
@@ -578,19 +569,19 @@ func (b *bleveBackend) cleanOldIndexes(resourceDir string, skipName string) {
|
||||
b.log.Warn("error cleaning folders from", "directory", resourceDir, "error", err)
|
||||
return
|
||||
}
|
||||
for _, ent := range entries {
|
||||
if ent.IsDir() && ent.Name() != skipName {
|
||||
indexDir := filepath.Join(resourceDir, ent.Name())
|
||||
if !isPathWithinRoot(indexDir, b.opts.Root) {
|
||||
b.log.Warn("Skipping cleanup of directory", "directory", indexDir)
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() && entry.Name() != skipName {
|
||||
entryDir := filepath.Join(resourceDir, entry.Name())
|
||||
if !isPathWithinRoot(entryDir, b.opts.Root) {
|
||||
b.log.Warn("Skipping cleanup of directory", "directory", entryDir)
|
||||
continue
|
||||
}
|
||||
|
||||
err = os.RemoveAll(indexDir)
|
||||
err = os.RemoveAll(entryDir)
|
||||
if err != nil {
|
||||
b.log.Error("Unable to remove old index folder", "directory", indexDir, "error", err)
|
||||
b.log.Error("Unable to remove old index folder", "directory", entryDir, "error", err)
|
||||
} else {
|
||||
b.log.Info("Removed old index folder", "directory", indexDir)
|
||||
b.log.Info("Removed old index folder", "directory", entryDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -637,17 +628,10 @@ func formatIndexName(now time.Time) string {
|
||||
return now.Format("20060102-150405")
|
||||
}
|
||||
|
||||
type fileIndex struct {
|
||||
Index bleve.Index
|
||||
Name string
|
||||
RV int64
|
||||
IsOpen bool
|
||||
}
|
||||
|
||||
func (b *bleveBackend) findPreviousFileBasedIndex(resourceDir string) *fileIndex {
|
||||
func (b *bleveBackend) findPreviousFileBasedIndex(resourceDir string) (bleve.Index, string, int64, error) {
|
||||
entries, err := os.ReadDir(resourceDir)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, "", 0, nil
|
||||
}
|
||||
|
||||
for _, ent := range entries {
|
||||
@@ -657,14 +641,15 @@ func (b *bleveBackend) findPreviousFileBasedIndex(resourceDir string) *fileIndex
|
||||
|
||||
indexName := ent.Name()
|
||||
indexDir := filepath.Join(resourceDir, indexName)
|
||||
|
||||
idx, err := bleve.OpenUsing(indexDir, map[string]interface{}{"bolt_timeout": boltTimeout})
|
||||
if err != nil {
|
||||
// On timeout, the file probably is locked by another process.
|
||||
// This indicates a setup issue that should be fixed rather than worked around by creating a new index file.
|
||||
if errors.Is(err, bolterrors.ErrTimeout) {
|
||||
b.log.Debug("Index is opened by another process (timeout), skipping", "indexDir", indexDir)
|
||||
return &fileIndex{Name: indexName, IsOpen: true}
|
||||
b.log.Error("index is locked by another process", "indexDir", indexDir, "err", err)
|
||||
return nil, "", 0, fmt.Errorf("index is locked by another process: indexDir=%s, err=%w", indexDir, err)
|
||||
}
|
||||
b.log.Debug("error opening index", "indexDir", indexDir, "err", err)
|
||||
b.log.Error("error opening index", "indexDir", indexDir, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -675,14 +660,10 @@ func (b *bleveBackend) findPreviousFileBasedIndex(resourceDir string) *fileIndex
|
||||
continue
|
||||
}
|
||||
|
||||
return &fileIndex{
|
||||
Index: idx,
|
||||
Name: indexName,
|
||||
RV: indexRV,
|
||||
}
|
||||
return idx, indexName, indexRV, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, "", 0, nil
|
||||
}
|
||||
|
||||
// Stop closes all indexes and stops background tasks.
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
bolterrors "go.etcd.io/bbolt/errors"
|
||||
"go.uber.org/atomic"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
@@ -1584,7 +1585,7 @@ func docCount(t *testing.T, idx resource.ResourceIndex) int {
|
||||
return int(cnt)
|
||||
}
|
||||
|
||||
func TestBleveBackendFallsBackToMemory(t *testing.T) {
|
||||
func TestBuildIndexReturnsErrorWhenIndexLocked(t *testing.T) {
|
||||
ns := resource.NamespacedResource{
|
||||
Namespace: "test",
|
||||
Group: "group",
|
||||
@@ -1605,53 +1606,19 @@ func TestBleveBackendFallsBackToMemory(t *testing.T) {
|
||||
require.Equal(t, indexStorageFile, bleveIdx1.indexStorage)
|
||||
checkOpenIndexes(t, reg1, 0, 1)
|
||||
|
||||
// Now create a second backend using the same directory
|
||||
// This simulates another instance trying to open the same index
|
||||
backend2, reg2 := setupBleveBackend(t, withRootDir(tmpDir))
|
||||
|
||||
// BuildIndex should detect the file is locked and fallback to memory
|
||||
index2, err := backend2.BuildIndex(context.Background(), ns, 100 /* file based */, nil, "test", indexTestDocs(ns, 10, 100), nil, false)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, index2)
|
||||
|
||||
// Verify second index fell back to in-memory despite size being above file threshold
|
||||
bleveIdx2, ok := index2.(*bleveIndex)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, indexStorageMemory, bleveIdx2.indexStorage)
|
||||
|
||||
// Verify metrics show 1 memory index and 0 file indexes for backend2
|
||||
checkOpenIndexes(t, reg2, 1, 0)
|
||||
|
||||
// Verify the in-memory index works correctly
|
||||
require.Equal(t, 10, docCount(t, index2))
|
||||
|
||||
// Clean up: close first backend to release the file lock
|
||||
backend1.Stop()
|
||||
}
|
||||
|
||||
func TestBleveSkipCleanOldIndexesOnMemoryFallback(t *testing.T) {
|
||||
ns := resource.NamespacedResource{
|
||||
Namespace: "test",
|
||||
Group: "group",
|
||||
Resource: "resource",
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
backend1, _ := setupBleveBackend(t, withRootDir(tmpDir))
|
||||
_, err := backend1.BuildIndex(context.Background(), ns, 100 /* file based */, nil, "test", indexTestDocs(ns, 10, 100), nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now create a second backend using the same directory
|
||||
// This simulates another instance trying to open the same index
|
||||
backend2, _ := setupBleveBackend(t, withRootDir(tmpDir))
|
||||
|
||||
// BuildIndex should detect the file is locked and fallback to memory
|
||||
_, err = backend2.BuildIndex(context.Background(), ns, 100 /* file based */, nil, "test", indexTestDocs(ns, 10, 100), nil, false)
|
||||
// BuildIndex should detect the file is locked and return an error after timeout
|
||||
now := time.Now()
|
||||
timeout, err := time.ParseDuration(boltTimeout)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that the index directory still exists (i.e., cleanOldIndexes was skipped)
|
||||
verifyDirEntriesCount(t, backend2.getResourceDir(ns), 1)
|
||||
index2, err := backend2.BuildIndex(context.Background(), ns, 100 /* file based */, nil, "test", indexTestDocs(ns, 10, 100), nil, false)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, bolterrors.ErrTimeout)
|
||||
require.Nil(t, index2)
|
||||
require.GreaterOrEqual(t, time.Since(now).Milliseconds(), timeout.Milliseconds()-500, "BuildIndex should have waited for approximately boltTimeout duration")
|
||||
|
||||
// Clean up: close first backend to release the file lock
|
||||
backend1.Stop()
|
||||
|
||||
@@ -393,6 +393,66 @@ func runDashboardValidationTests(t *testing.T, ctx TestContext) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Dashboard tag validations", func(t *testing.T) {
|
||||
t.Run("reject dashboard with tag over 50 characters on creation", func(t *testing.T) {
|
||||
dashObj := createDashboardObject(t, "Dashboard with Long Tag", "", 0)
|
||||
meta, _ := utils.MetaAccessor(dashObj)
|
||||
spec, _ := meta.GetSpec()
|
||||
specMap := spec.(map[string]interface{})
|
||||
specMap["tags"] = []string{"this-is-a-very-long-tag-that-exceeds-fifty-characters-limit"}
|
||||
_ = meta.SetSpec(specMap)
|
||||
_, err := adminClient.Resource.Create(context.Background(), dashObj, v1.CreateOptions{})
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "tag too long")
|
||||
})
|
||||
|
||||
t.Run("reject dashboard update with tag over 50 characters", func(t *testing.T) {
|
||||
dash, err := createDashboard(t, adminClient, "Valid Dashboard", nil, nil, ctx.Helper)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dash)
|
||||
meta, _ := utils.MetaAccessor(dash)
|
||||
spec, _ := meta.GetSpec()
|
||||
specMap := spec.(map[string]interface{})
|
||||
specMap["tags"] = []string{"this-is-a-very-long-tag-that-exceeds-fifty-characters-limit"}
|
||||
_ = meta.SetSpec(specMap)
|
||||
_, err = adminClient.Resource.Update(context.Background(), dash, v1.UpdateOptions{})
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "tag too long")
|
||||
err = adminClient.Resource.Delete(context.Background(), dash.GetName(), v1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("accept dashboard with tag at 50 characters", func(t *testing.T) {
|
||||
dashObj := createDashboardObject(t, "Dashboard with Valid Tag", "", 0)
|
||||
meta, _ := utils.MetaAccessor(dashObj)
|
||||
spec, _ := meta.GetSpec()
|
||||
specMap := spec.(map[string]interface{})
|
||||
specMap["tags"] = []string{"this-tag-is-exactly-fifty-characters-long-12345"}
|
||||
_ = meta.SetSpec(specMap)
|
||||
createdDash, err := adminClient.Resource.Create(context.Background(), dashObj, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, createdDash)
|
||||
err = adminClient.Resource.Delete(context.Background(), createdDash.GetName(), v1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("reject dashboard with multiple tags where one exceeds limit", func(t *testing.T) {
|
||||
dashObj := createDashboardObject(t, "Dashboard with Mixed Tags", "", 0)
|
||||
meta, _ := utils.MetaAccessor(dashObj)
|
||||
spec, _ := meta.GetSpec()
|
||||
specMap := spec.(map[string]interface{})
|
||||
specMap["tags"] = []string{
|
||||
"valid-tag",
|
||||
"another-valid-tag",
|
||||
"this-is-a-very-long-tag-that-exceeds-fifty-characters-limit",
|
||||
}
|
||||
_ = meta.SetSpec(specMap)
|
||||
_, err := adminClient.Resource.Create(context.Background(), dashObj, v1.CreateOptions{})
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "tag too long")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Dashboard folder validations", func(t *testing.T) {
|
||||
// Test non-existent folder UID
|
||||
t.Run("reject dashboard with non-existent folder UID", func(t *testing.T) {
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestIntegrationPreferences(t *testing.T) {
|
||||
Path: fmt.Sprintf("/api/teams/%d/preferences", helper.Org1.Staff.ID),
|
||||
Body: []byte(`{
|
||||
"weekStart": "sunday",
|
||||
"timezone": "africa"
|
||||
"timezone": "Africa/Johannesburg"
|
||||
}`),
|
||||
}, &raw)
|
||||
require.Equal(t, http.StatusOK, legacyResponse.Response.StatusCode, "create preference for user")
|
||||
@@ -79,7 +79,7 @@ func TestIntegrationPreferences(t *testing.T) {
|
||||
Path: "/api/org/preferences",
|
||||
Body: []byte(`{
|
||||
"weekStart": "sunday",
|
||||
"timezone": "africa",
|
||||
"timezone": "Africa/Accra",
|
||||
"theme": "dark"
|
||||
}`),
|
||||
}, &raw)
|
||||
@@ -144,7 +144,7 @@ func TestIntegrationPreferences(t *testing.T) {
|
||||
|
||||
jj, _ = json.Marshal(bootdata.Result.User)
|
||||
require.JSONEq(t, `{
|
||||
"timezone":"africa",
|
||||
"timezone":"Africa/Johannesburg",
|
||||
"weekStart":"saturday",
|
||||
"theme":"dark",
|
||||
"language":"en-US", `+ // FROM global default!
|
||||
@@ -157,10 +157,10 @@ func TestIntegrationPreferences(t *testing.T) {
|
||||
Path: "/apis/preferences.grafana.app/v1alpha1/namespaces/default/preferences/merged",
|
||||
}, &preferences.Preferences{})
|
||||
require.Equal(t, http.StatusOK, merged.Response.StatusCode, "get merged preferences")
|
||||
require.Equal(t, "saturday", *merged.Result.Spec.WeekStart) // from user
|
||||
require.Equal(t, "africa", *merged.Result.Spec.Timezone) // from team
|
||||
require.Equal(t, "dark", *merged.Result.Spec.Theme) // from org
|
||||
require.Equal(t, "en-US", *merged.Result.Spec.Language) // settings.ini
|
||||
require.Equal(t, "dd/mm/yyyy", *merged.Result.Spec.RegionalFormat) // from user update
|
||||
require.Equal(t, "saturday", *merged.Result.Spec.WeekStart) // from user
|
||||
require.Equal(t, "Africa/Johannesburg", *merged.Result.Spec.Timezone) // from team
|
||||
require.Equal(t, "dark", *merged.Result.Spec.Theme) // from org
|
||||
require.Equal(t, "en-US", *merged.Result.Spec.Language) // settings.ini
|
||||
require.Equal(t, "dd/mm/yyyy", *merged.Result.Spec.RegionalFormat) // from user update
|
||||
})
|
||||
}
|
||||
|
||||
Generated
+4
-10
@@ -6152,11 +6152,8 @@
|
||||
]
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
]
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
"type": "string"
|
||||
@@ -8657,11 +8654,8 @@
|
||||
]
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
]
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
"type": "string"
|
||||
|
||||
Generated
+11
-11
@@ -6167,10 +6167,16 @@
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A comma separated list of folder ID(s) to filter the elements by.",
|
||||
"description": "A comma separated list of folder ID(s) to filter the elements by.\nDeprecated: Use FolderFilterUIDs instead.",
|
||||
"name": "folderFilter",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A comma separated list of folder UID(s) to filter the elements by.",
|
||||
"name": "folderFilterUIDs",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
@@ -18729,11 +18735,8 @@
|
||||
]
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
]
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
"type": "string"
|
||||
@@ -23120,11 +23123,8 @@
|
||||
]
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
]
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
"type": "string"
|
||||
|
||||
@@ -3,7 +3,8 @@ import { css, keyframes } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import grafanaIconSvg from 'img/grafana_icon.svg';
|
||||
|
||||
import { Branding } from '../Branding/Branding';
|
||||
|
||||
export function BouncingLoader() {
|
||||
const styles = useStyles2(getStyles);
|
||||
@@ -16,7 +17,7 @@ export function BouncingLoader() {
|
||||
aria-label={t('bouncing-loader.label', 'Loading')}
|
||||
>
|
||||
<div className={styles.bounce}>
|
||||
<img alt="" src={grafanaIconSvg} className={styles.logo} />
|
||||
<Branding.LoginLogo className={styles.logo} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,10 @@ export const validateDashboardJson = (json: string) => {
|
||||
if (hasInvalidTag) {
|
||||
return t('dashboard.validation.tags-expected-strings', 'tags expected array of strings');
|
||||
}
|
||||
const hasTooLongTag = dashboard.tags.some((tag: string) => tag.length > 50);
|
||||
if (hasTooLongTag) {
|
||||
return t('dashboard.validation.tag-too-long', 'Dashboard tag too long, max 50 characters');
|
||||
}
|
||||
} else {
|
||||
return t('dashboard.validation.tags-expected-array', 'tags expected array');
|
||||
}
|
||||
|
||||
@@ -5696,6 +5696,7 @@
|
||||
"validation": {
|
||||
"invalid-dashboard-id": "Could not find a valid Grafana.com ID",
|
||||
"invalid-json": "Not valid JSON",
|
||||
"tag-too-long": "Dashboard tag too long, max 50 characters",
|
||||
"tags-expected-array": "tags expected array",
|
||||
"tags-expected-strings": "tags expected array of strings"
|
||||
},
|
||||
@@ -9254,7 +9255,8 @@
|
||||
"tags-input": {
|
||||
"add": "Add",
|
||||
"placeholder-new-tag": "New tag (enter key to add)",
|
||||
"remove": "Remove tag: {{name}}"
|
||||
"remove": "Remove tag: {{name}}",
|
||||
"tag-too-long": "Tag too long, max 50 characters"
|
||||
},
|
||||
"time-sync-button": {
|
||||
"aria-label-sync": "Sync times",
|
||||
|
||||
Generated
+11
-9
@@ -8264,10 +8264,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"timezone": {
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
],
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
@@ -12654,10 +12651,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"timezone": {
|
||||
"enum": [
|
||||
"utc",
|
||||
"browser"
|
||||
],
|
||||
"description": "Any IANA timezone string (e.g. America/New_York), 'utc', 'browser', or empty string",
|
||||
"type": "string"
|
||||
},
|
||||
"weekStart": {
|
||||
@@ -20727,13 +20721,21 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A comma separated list of folder ID(s) to filter the elements by.",
|
||||
"description": "A comma separated list of folder ID(s) to filter the elements by.\nDeprecated: Use FolderFilterUIDs instead.",
|
||||
"in": "query",
|
||||
"name": "folderFilter",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A comma separated list of folder UID(s) to filter the elements by.",
|
||||
"in": "query",
|
||||
"name": "folderFilterUIDs",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "The number of results per page.",
|
||||
"in": "query",
|
||||
|
||||
@@ -3792,23 +3792,23 @@ __metadata:
|
||||
"@react-aria/overlays": "npm:3.30.0"
|
||||
"@react-aria/utils": "npm:3.31.0"
|
||||
"@rollup/plugin-node-resolve": "npm:16.0.1"
|
||||
"@storybook/addon-a11y": "npm:^8.6.2"
|
||||
"@storybook/addon-actions": "npm:^8.6.2"
|
||||
"@storybook/addon-docs": "npm:^8.6.2"
|
||||
"@storybook/addon-essentials": "npm:^8.6.2"
|
||||
"@storybook/addon-storysource": "npm:^8.6.2"
|
||||
"@storybook/addon-a11y": "npm:^8.6.15"
|
||||
"@storybook/addon-actions": "npm:^8.6.15"
|
||||
"@storybook/addon-docs": "npm:^8.6.15"
|
||||
"@storybook/addon-essentials": "npm:^8.6.15"
|
||||
"@storybook/addon-storysource": "npm:^8.6.15"
|
||||
"@storybook/addon-webpack5-compiler-swc": "npm:^2.1.0"
|
||||
"@storybook/blocks": "npm:^8.6.2"
|
||||
"@storybook/components": "npm:^8.6.2"
|
||||
"@storybook/core-events": "npm:^8.6.2"
|
||||
"@storybook/manager-api": "npm:^8.6.2"
|
||||
"@storybook/blocks": "npm:^8.6.15"
|
||||
"@storybook/components": "npm:^8.6.15"
|
||||
"@storybook/core-events": "npm:^8.6.15"
|
||||
"@storybook/manager-api": "npm:^8.6.15"
|
||||
"@storybook/mdx2-csf": "npm:1.1.0"
|
||||
"@storybook/preset-scss": "npm:1.0.3"
|
||||
"@storybook/preview-api": "npm:^8.6.2"
|
||||
"@storybook/react": "npm:^8.6.2"
|
||||
"@storybook/react-webpack5": "npm:^8.6.2"
|
||||
"@storybook/preview-api": "npm:^8.6.15"
|
||||
"@storybook/react": "npm:^8.6.15"
|
||||
"@storybook/react-webpack5": "npm:^8.6.15"
|
||||
"@storybook/test-runner": "npm:^0.23.0"
|
||||
"@storybook/theming": "npm:^8.6.2"
|
||||
"@storybook/theming": "npm:^8.6.15"
|
||||
"@tanstack/react-virtual": "npm:^3.5.1"
|
||||
"@testing-library/dom": "npm:10.4.1"
|
||||
"@testing-library/jest-dom": "npm:6.6.4"
|
||||
@@ -3899,7 +3899,7 @@ __metadata:
|
||||
slate: "npm:0.47.9"
|
||||
slate-plain-serializer: "npm:0.7.13"
|
||||
slate-react: "npm:0.22.10"
|
||||
storybook: "npm:^8.6.2"
|
||||
storybook: "npm:^8.6.15"
|
||||
style-loader: "npm:4.0.0"
|
||||
tinycolor2: "npm:1.6.0"
|
||||
tslib: "npm:2.8.1"
|
||||
@@ -7961,22 +7961,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-a11y@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-a11y@npm:8.6.2"
|
||||
"@storybook/addon-a11y@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-a11y@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/addon-highlight": "npm:8.6.2"
|
||||
"@storybook/test": "npm:8.6.2"
|
||||
"@storybook/addon-highlight": "npm:8.6.15"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/test": "npm:8.6.15"
|
||||
axe-core: "npm:^4.2.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/c7a161734c4d587bbc2b926fcf01103203b4f50112f5ea19bdbd4dad4c1c62bb358613e3c6e608335f064ef7b7627f5a1ffeb1f524ec008bb19e86e50b1dfb27
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/558fcb105486112118bfc5f0068efcb5d4b66b508820f8e2a6d4041e7b06029b64d2d3a8b51a7a6049c836b900ead67c33fa9f89e0a1b550f0e5eedbab18e33c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-actions@npm:8.6.2, @storybook/addon-actions@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-actions@npm:8.6.2"
|
||||
"@storybook/addon-actions@npm:8.6.15, @storybook/addon-actions@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-actions@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@types/uuid": "npm:^9.0.1"
|
||||
@@ -7984,139 +7985,139 @@ __metadata:
|
||||
polished: "npm:^4.2.2"
|
||||
uuid: "npm:^9.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/16127ee35f08fe98df98a688a8724c803274cbe1a81d3ae46727ad6b34bdae913dd905a3a124954805e4f2650e56e18f80de2f4cf7cb0fc0480c185cf342a8e5
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/4d47e3ce9319d282e5abb44e7694748792c29f37c883afbcfc8939353be47bcc004ab41ce1f421c3d5bafbaa0366935f0b90272e5e6542a2229db55f63bef82c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-backgrounds@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-backgrounds@npm:8.6.2"
|
||||
"@storybook/addon-backgrounds@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-backgrounds@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
memoizerific: "npm:^1.11.3"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/b303afb745fb34cb77565f595fdd5f1749927f3be6bc58702f3ed6b8931d89abc099b46940436a1f0509b4a6580f7c58100bf091ba6e5fe7f040704ac723118f
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/c96107e892d39d5841e7f64f53a619527268636c61184770ca07684432fb3cee30c224a35b716ff30ba9bcdb4326649cd4e7873359d65a7fa8889b0fe7a15ad4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-controls@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-controls@npm:8.6.2"
|
||||
"@storybook/addon-controls@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-controls@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
dequal: "npm:^2.0.2"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/4d54617c514b6e88d5708e2d3b067a01f3863e83dcf327bdec0b55df36bf8e6269ab1d9e5c5cb0edb27e9554c2d212ce087356b9d68779744854207febd26808
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/ee7ea1e4d6cdb47c233ff3dd48196e649bea62bb88816261f65eb0ecd4f83e1593f09e657fc91ed8595b6279a04a1267c01d82020ef749d90c28d4f71b879224
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-docs@npm:8.6.2, @storybook/addon-docs@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-docs@npm:8.6.2"
|
||||
"@storybook/addon-docs@npm:8.6.15, @storybook/addon-docs@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-docs@npm:8.6.15"
|
||||
dependencies:
|
||||
"@mdx-js/react": "npm:^3.0.0"
|
||||
"@storybook/blocks": "npm:8.6.2"
|
||||
"@storybook/csf-plugin": "npm:8.6.2"
|
||||
"@storybook/react-dom-shim": "npm:8.6.2"
|
||||
"@storybook/blocks": "npm:8.6.15"
|
||||
"@storybook/csf-plugin": "npm:8.6.15"
|
||||
"@storybook/react-dom-shim": "npm:8.6.15"
|
||||
react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/d13752c4f31f01426724dbfdc70313948475dbbf6c43ed1cceca8d37d86424f79369c1b06c5e4daebe581e8702b02c9522ea77aff1864a7228662f4c8517fedf
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/ec18d166ebab276258098ef86e9ad9bcaa163b357766bcef957a8f8c2260d4c128834497304cd0cde8fed1b0dfa02b9e79d82b88d61e21eab35437b2d17fa163
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-essentials@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-essentials@npm:8.6.2"
|
||||
"@storybook/addon-essentials@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-essentials@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/addon-actions": "npm:8.6.2"
|
||||
"@storybook/addon-backgrounds": "npm:8.6.2"
|
||||
"@storybook/addon-controls": "npm:8.6.2"
|
||||
"@storybook/addon-docs": "npm:8.6.2"
|
||||
"@storybook/addon-highlight": "npm:8.6.2"
|
||||
"@storybook/addon-measure": "npm:8.6.2"
|
||||
"@storybook/addon-outline": "npm:8.6.2"
|
||||
"@storybook/addon-toolbars": "npm:8.6.2"
|
||||
"@storybook/addon-viewport": "npm:8.6.2"
|
||||
"@storybook/addon-actions": "npm:8.6.15"
|
||||
"@storybook/addon-backgrounds": "npm:8.6.15"
|
||||
"@storybook/addon-controls": "npm:8.6.15"
|
||||
"@storybook/addon-docs": "npm:8.6.15"
|
||||
"@storybook/addon-highlight": "npm:8.6.15"
|
||||
"@storybook/addon-measure": "npm:8.6.15"
|
||||
"@storybook/addon-outline": "npm:8.6.15"
|
||||
"@storybook/addon-toolbars": "npm:8.6.15"
|
||||
"@storybook/addon-viewport": "npm:8.6.15"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/2e8a9cb6fed038122230929f72dfc94116c7884d838f633b81f1b485bf169129cf8e91bc31cc9949cbfc39d31ada1d5ae4a8bc61c533b47c9b63ea7d5045c468
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/0416693b5f0b7f727deaa2c575e1ad826b93852f41fbd0d905c7bad54c31cf312278575cacc28498db81b35b027373e98c5980b307876297e075e74f9267e7f8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-highlight@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-highlight@npm:8.6.2"
|
||||
"@storybook/addon-highlight@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-highlight@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/0bd8298612390daa6d455876c3485e8e60751f51d6a2e67c79d2bb37b27a5059b1fab3ed4117371f6b375a6294a5e038abe6bd65db9259723578e4c55b0abcd2
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/51f0a7fbf6c81e78e74f71943f8cf2b5f7e9ec08712e9f186381ecaa15f011c4c7df9d8d99e1e3b44e37bd646ff4d162cf91024d6b6a8b881fe988ccab47f786
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-measure@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-measure@npm:8.6.2"
|
||||
"@storybook/addon-measure@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-measure@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
tiny-invariant: "npm:^1.3.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/c81946d8459aa953f633503872f30ae13336cfb9c7e539c49dccbeae6f33e57e774ff35a197d3aea46d28a33c0a45a497a14eacd403817fa87572d377d5ad4d9
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/62b899f873e0024ed21e081759d731ff978fe917e8739dab0de3ebc857bb43641c9c9074f4a562864b353550fafd17950ab8dbd17b20a97371501ebe5f188a05
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-outline@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-outline@npm:8.6.2"
|
||||
"@storybook/addon-outline@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-outline@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/357a72cb76cd8d1d2e7ff5ab1fc152f17b1f8c4ab087d8b94e1f157554a641aa47d96ede8087d5045eda8b99dfc2d94c29c2bdc1dce8f8d7d0c0a0b660aae966
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/9439e6ab319475df7fed652ea4265916699df45d4ba4a04ec6b576a604f4d0917b2b5c8f1a48cabfd174f7baf3b943d3789ba80efb9e299ecefb388f8bf22f79
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-storysource@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-storysource@npm:8.6.2"
|
||||
"@storybook/addon-storysource@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-storysource@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/source-loader": "npm:8.6.2"
|
||||
"@storybook/source-loader": "npm:8.6.15"
|
||||
estraverse: "npm:^5.2.0"
|
||||
tiny-invariant: "npm:^1.3.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/4c06dab42fd2ff88df632960bfc70144e7ab423bec373be7f1b318519a383f33515a296440e77c085345e220af5de77dd9c500a49fcc66e23db9612164d94d9f
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/499555d1178795c8c046a0269a980006e586d3445a734e65d9789ab84b2b62d4c4193b3d0e241bfc3954aec9977b9777b5ec357d22a6929c9325b3f4427d399c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-toolbars@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-toolbars@npm:8.6.2"
|
||||
"@storybook/addon-toolbars@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-toolbars@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/7c7863a1e9698128557cf38bdce81aab127958c4892aeaa2f9035042d0fd36edcabb296575cf02a69d8f19abe4b1b114223a6312f25c84dff827314f004303ee
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/27cfba470fd0f85d8bd236a7929b77cc50c89948926a4463f3473bcd04f823cebbf08f8e240a4055d77aac9636d32cfaaee3ca912ff32ee5806e3250df53dff7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-viewport@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/addon-viewport@npm:8.6.2"
|
||||
"@storybook/addon-viewport@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/addon-viewport@npm:8.6.15"
|
||||
dependencies:
|
||||
memoizerific: "npm:^1.11.3"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/60e67fb0b2f21c889f416bbb7d1729bf3310f56efa23d016d9984f6a9fce39cccccc02422b6ece736a558fef0053c5ac39d46df1735aa2e560e580a3fae3337f
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/2b3359ac92e9a131c7dc7c4b6bc9d131786c86bead9490d464e4b275278e309a579cd67756d4d9ea5764aae502e3e65104e98486933f7f57b583ab8a3757db8b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8142,22 +8143,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/blocks@npm:8.6.2, @storybook/blocks@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/blocks@npm:8.6.2"
|
||||
"@storybook/blocks@npm:8.6.15, @storybook/blocks@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/blocks@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/icons": "npm:^1.2.12"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
storybook: ^8.6.2
|
||||
storybook: ^8.6.15
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
checksum: 10/8137b042e99572b7bdd6df3484c75d3b1cf78b15bb7d3a7ad09738e94ec21481d295acfe2b59fa547be9ee5a0b075bb485f88a1972948e4703aef6b174b60ead
|
||||
checksum: 10/7598b9fe3c5dcabc02b22eee3780055ae7ca259bc51520c5bf12c34395d11dbac4b0b3f817c46492b407a16f67ff5ba36879fd30c91299ddb053e9f274664e21
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8189,11 +8190,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/builder-webpack5@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/builder-webpack5@npm:8.6.2"
|
||||
"@storybook/builder-webpack5@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/builder-webpack5@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/core-webpack": "npm:8.6.2"
|
||||
"@storybook/core-webpack": "npm:8.6.15"
|
||||
"@types/semver": "npm:^7.3.4"
|
||||
browser-assert: "npm:^1.2.1"
|
||||
case-sensitive-paths-webpack-plugin: "npm:^2.4.0"
|
||||
@@ -8218,29 +8219,29 @@ __metadata:
|
||||
webpack-hot-middleware: "npm:^2.25.1"
|
||||
webpack-virtual-modules: "npm:^0.6.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
storybook: ^8.6.15
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10/909d74c281a41a43d17ff9f313231283ac21c9c97ef47d8f8f96753f0b639dbdaeb2d12d46a7cd4fd8001bffcc2d707e83d47ab62fe3757ab30093159a1eded1
|
||||
checksum: 10/8e8e816dbfa83e2fd56401a65a1551ecbaa658db54b2270e90560710c024878a09df48e1a4e114eacc75ff5c924cb7a277f4e3501ae4744c6a2742ab55135afe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/components@npm:8.6.2, @storybook/components@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/components@npm:8.6.2"
|
||||
"@storybook/components@npm:8.6.15, @storybook/components@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/components@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10/d85bb39aedd03a05043194debf3d35965dbe84d386029f63f0aa20ac943f4cc635558f6b08cc8ec013a2cc7f2407ef3c8735a76d4805e41569aaabe8efe59fd4
|
||||
checksum: 10/350075ffe67cfc307c0f8f9b6568c5f25e97a2ffb55d723b88c16a3f3ad6d687c312580c4b4d3cbf8ef245a30723797d89be20a44f6c500f79e7b173b0cb79d0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core-events@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/core-events@npm:8.6.2"
|
||||
"@storybook/core-events@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/core-events@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10/d2f574be4bc4fd5be82be376954b795dca291dd834b62ef4545eb912bf0c879bd6b4e544613cc399bbe5161c05788d32ad9119811d05921f690417fd3f1448f4
|
||||
checksum: 10/95dd9f683d502c8b83600d455c960afe9b18278177324bfbb3904a9ef7a6022939017924659088118bb7b272b6ad7e4912b6e6a222e3274a480ab61183b89616
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8255,22 +8256,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core-webpack@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/core-webpack@npm:8.6.2"
|
||||
"@storybook/core-webpack@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/core-webpack@npm:8.6.15"
|
||||
dependencies:
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/666edcb895b034b74fa86bb6d6dc16d26078ffc3524d20917ca27c40b4f722706622f83c4f97a323f8fc441d655a5ab124c9fbea12a2fa2e25000cf1231a5e78
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/494110266d622be00a61cd160a4e799ed4c4c447ab04699d497de7c3d95ee800f212680c31722b8938819577853e095af545f7853e7ce4cf751d2a9e9b4c7f12
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/core@npm:8.6.2"
|
||||
"@storybook/core@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/core@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/theming": "npm:8.6.2"
|
||||
"@storybook/theming": "npm:8.6.15"
|
||||
better-opn: "npm:^3.0.2"
|
||||
browser-assert: "npm:^1.2.1"
|
||||
esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0"
|
||||
@@ -8286,15 +8287,15 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
prettier:
|
||||
optional: true
|
||||
checksum: 10/57d8af6d822c4cbeab201aec813830d632165c2411bf8708481ad0daa2fa942ce6a912e0ef764e6acb9bd2053baf0614b7726e5827b071f3f845d459ac1f3d3a
|
||||
checksum: 10/d268d6fa00c38b35e5c363ee33779c2e087ab8e4681e0e205baa2fdb2780ea9feda3c9f6db35d60092778878d2782b2093c744bdf1af173c5688c3e1e0e960ac
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core@patch:@storybook/core@npm%3A8.6.2#~/.yarn/patches/@storybook-core-npm-8.6.2-8c752112c0.patch":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/core@patch:@storybook/core@npm%3A8.6.2#~/.yarn/patches/@storybook-core-npm-8.6.2-8c752112c0.patch::version=8.6.2&hash=f4cc1f"
|
||||
"@storybook/core@patch:@storybook/core@npm%3A8.6.15#~/.yarn/patches/@storybook-core-npm-8.6.15-a468a35170.patch":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/core@patch:@storybook/core@npm%3A8.6.15#~/.yarn/patches/@storybook-core-npm-8.6.15-a468a35170.patch::version=8.6.15&hash=c479fb"
|
||||
dependencies:
|
||||
"@storybook/theming": "npm:8.6.2"
|
||||
"@storybook/theming": "npm:8.6.15"
|
||||
better-opn: "npm:^3.0.2"
|
||||
browser-assert: "npm:^1.2.1"
|
||||
esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0"
|
||||
@@ -8310,18 +8311,18 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
prettier:
|
||||
optional: true
|
||||
checksum: 10/cd95a51437135dd3c4333b14acefd528d8064b2cea7789f859ba80783c115c92ed4be51d4a7bd6236888fdd5f46f488a379e0c71bc1a712ffe6dc1353fb4e648
|
||||
checksum: 10/fd635098effe4ae87122ac706394dc89a26b3cae74d7d126897852a9da1960d617c76dc1be6d6d8a4c2d02c19e694c7222a3cfe7a6beb7daa605b30ffbf41644
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/csf-plugin@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/csf-plugin@npm:8.6.2"
|
||||
"@storybook/csf-plugin@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/csf-plugin@npm:8.6.15"
|
||||
dependencies:
|
||||
unplugin: "npm:^1.3.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/6d71101640975cbe08d5dc9bae30938337b0e999f5724c4802713cf3d8c34671b646158ffde659e9cbcd005153844223cd4f9a4af2aa0d6f5a15b3db8d31f85d
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/c544089d7a675d19e226e331a791db6c2e2cede893a2955578959086e7c35e846319a9080d91968ec81a2115e2c396fe3d76d2f50d74baca098dd5b03ad939b0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8342,24 +8343,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/instrumenter@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/instrumenter@npm:8.6.2"
|
||||
"@storybook/instrumenter@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/instrumenter@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@vitest/utils": "npm:^2.1.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/40d028d6f8b5ab51eb112bb5b903f64438eaf818c501a78ef77a5e946676e13f15ad8f5188a85e40bf91f987c6ab15c6a33b4e8bef8b8f8e05011013dcda092a
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/5f56da838ccd47b9a262e5aa54a5574985295994fb1b6fb165d4c3a66d96367588fa93c60fe55892ffa450ea3e41e0abcc313a12a873d5b4be7625a1c3b0d883
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/manager-api@npm:8.6.2, @storybook/manager-api@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/manager-api@npm:8.6.2"
|
||||
"@storybook/manager-api@npm:8.6.15, @storybook/manager-api@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/manager-api@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10/d344c88c6cad0bcc54767a8ef1d269a9df868c76ae22927c31936e46aaeb47075783d84f8815b4d0c7812ed50b2d4616417429479e3a9ea36043c557eb141590
|
||||
checksum: 10/0b378fc657830c48b7c304ea915883161e8271d76b8f90b90e86e4260f6e513ae9f0f87eee6cad057a6c38e8a9faf7bac0ba169e586aabce2b4e48d36a0d27c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8394,12 +8395,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/preset-react-webpack@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/preset-react-webpack@npm:8.6.2"
|
||||
"@storybook/preset-react-webpack@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/preset-react-webpack@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/core-webpack": "npm:8.6.2"
|
||||
"@storybook/react": "npm:8.6.2"
|
||||
"@storybook/core-webpack": "npm:8.6.15"
|
||||
"@storybook/react": "npm:8.6.15"
|
||||
"@storybook/react-docgen-typescript-plugin": "npm:1.0.6--canary.9.0c3f3b7.0"
|
||||
"@types/semver": "npm:^7.3.4"
|
||||
find-up: "npm:^5.0.0"
|
||||
@@ -8412,11 +8413,11 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.6.2
|
||||
storybook: ^8.6.15
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10/d903a14e6e65bdfb56568962f456a103ec3f64d339d4ed3d091befe66dddcff2e31d7a2acee1bbf52cf9a33d09564af2dc36483961f73c812eacb34d71f7a951
|
||||
checksum: 10/e3c2bf792a3dc051f27f8723b1b2c9671ecda57f6f20950fe30d65c17ff3751c382ffcf606a2efd85d6b5266356e0b62b57e23560b44cc497d78335dd5ae6462
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8431,12 +8432,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/preview-api@npm:8.6.2, @storybook/preview-api@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/preview-api@npm:8.6.2"
|
||||
"@storybook/preview-api@npm:8.6.15, @storybook/preview-api@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/preview-api@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10/5d286ed8c266a8aa63361bbb0245163e6fe3fd85a5e60555a79a579535faf36c30a9ad07bff30b0d9d536d35ec8f5ee78484629b174ecc965cbe0726e749d6de
|
||||
checksum: 10/70df6006ce7340371e207f7f077d52c8684743a64f172d54f3e99fb6d2e190f46a4321c40be7ea813b9bd407530f971372156b3dd6ba1f61681f7b3acc498010
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8469,14 +8470,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react-dom-shim@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/react-dom-shim@npm:8.6.2"
|
||||
"@storybook/react-dom-shim@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/react-dom-shim@npm:8.6.15"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/f32718a49ccbd7c01233c83d738479eb60c41a3f8855066b85593fb7a07129b1b18a0c93fe64b01dce9c9105293b40c1e131410169d5aaaa2f8b7a7c00f836ee
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/7625cfa2a385315851cd0aeb36f517e75679262c2942a5a53dd2909483b62602b9e5157ba51a8e464eb70112a4916278fba63b05178beef3d2ff493a464a2c64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8499,22 +8500,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react-webpack5@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/react-webpack5@npm:8.6.2"
|
||||
"@storybook/react-webpack5@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/react-webpack5@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/builder-webpack5": "npm:8.6.2"
|
||||
"@storybook/preset-react-webpack": "npm:8.6.2"
|
||||
"@storybook/react": "npm:8.6.2"
|
||||
"@storybook/builder-webpack5": "npm:8.6.15"
|
||||
"@storybook/preset-react-webpack": "npm:8.6.15"
|
||||
"@storybook/react": "npm:8.6.15"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.6.2
|
||||
storybook: ^8.6.15
|
||||
typescript: ">= 4.2.x"
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10/1d8c745d21da7853328a1870797808982864be68783c2a56248ab642a81eaad667f5522cc9f0eba74a9b96658d6fcd9b6a5b9296e235ff8e1566edbc48e5d146
|
||||
checksum: 10/0468aa5ca0ed76170cbdef6b2a211625e64b74a8012aabeca03d38c8fa8f34013b2068f68dd173bb5db32aa9ccaa87c923344a506c561ad98d0afb0f88856b79
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8536,41 +8537,41 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react@npm:8.6.2, @storybook/react@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/react@npm:8.6.2"
|
||||
"@storybook/react@npm:8.6.15, @storybook/react@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/react@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/components": "npm:8.6.2"
|
||||
"@storybook/components": "npm:8.6.15"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/manager-api": "npm:8.6.2"
|
||||
"@storybook/preview-api": "npm:8.6.2"
|
||||
"@storybook/react-dom-shim": "npm:8.6.2"
|
||||
"@storybook/theming": "npm:8.6.2"
|
||||
"@storybook/manager-api": "npm:8.6.15"
|
||||
"@storybook/preview-api": "npm:8.6.15"
|
||||
"@storybook/react-dom-shim": "npm:8.6.15"
|
||||
"@storybook/theming": "npm:8.6.15"
|
||||
peerDependencies:
|
||||
"@storybook/test": 8.6.2
|
||||
"@storybook/test": 8.6.15
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.6.2
|
||||
storybook: ^8.6.15
|
||||
typescript: ">= 4.2.x"
|
||||
peerDependenciesMeta:
|
||||
"@storybook/test":
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10/b8a91e6a8aeb9e32e05e12db4df1dafd59b54d82954e481ea9224316bd1e432093259b474f773911e90aeebe441cbb17e8dc0a6940b79b5899eff1f2b4aae334
|
||||
checksum: 10/a7e33bd68e25bf04fac77c9573c51d76d556c51a4329e84dae2a4e2afd39950e4d3ab9a49787ac465e9e81522b40ea12dc86cd0b60a2aab1ee2f88a753bc9b43
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/source-loader@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/source-loader@npm:8.6.2"
|
||||
"@storybook/source-loader@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/source-loader@npm:8.6.15"
|
||||
dependencies:
|
||||
es-toolkit: "npm:^1.22.0"
|
||||
estraverse: "npm:^5.2.0"
|
||||
prettier: "npm:^3.1.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/8cf43eb6ce2df997272c71f3d9f8e85f3fecb6ca1d176c87fd349ea17e1d821dadb43496af5d10a2c6163fd6d920940a253a075a7774fc9bb5f724c132cfcaf0
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/37e6749a8bd633aa7b84546eb8f3bf4f259614846589fe5cfe9b461926b57bbda013948b95ccb12108324f1580d7330fcab7828ab90936b0567dba27e0a626a1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8604,29 +8605,29 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/test@npm:8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/test@npm:8.6.2"
|
||||
"@storybook/test@npm:8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/test@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/instrumenter": "npm:8.6.2"
|
||||
"@storybook/instrumenter": "npm:8.6.15"
|
||||
"@testing-library/dom": "npm:10.4.0"
|
||||
"@testing-library/jest-dom": "npm:6.5.0"
|
||||
"@testing-library/user-event": "npm:14.5.2"
|
||||
"@vitest/expect": "npm:2.0.5"
|
||||
"@vitest/spy": "npm:2.0.5"
|
||||
peerDependencies:
|
||||
storybook: ^8.6.2
|
||||
checksum: 10/4cb89e254143374716fcd72c3a9a4c603a9f664162c5755ead7257ce130bc33d3c48c9cbaa35274023f4b961d66c4e84733e35ca663019d770fcfa6ef5b21b84
|
||||
storybook: ^8.6.15
|
||||
checksum: 10/5f54b9ef1910011813059708f6d2c32f4db5f4e719de9de2a7f2280efe7535c45c36668cf3e346b4788f4bbe6b71a3ab169ccdc17f0d8e634443d92849b46bf1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/theming@npm:8.6.2, @storybook/theming@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "@storybook/theming@npm:8.6.2"
|
||||
"@storybook/theming@npm:8.6.15, @storybook/theming@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "@storybook/theming@npm:8.6.15"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10/81ff1f740edaa000d6abaab5a47b038b46cfc54ddad308335b8d26d7a6f1ee100f617f52d51cd6596f424a534dbda0d9801e3928b4b6f758d9a3e8da6f9d40f5
|
||||
checksum: 10/f02760831a13d7af9dbfeb6feea949f4c13c897861cbc75253a6776d133891567889c8d99c7e91a99124d0772c3bde1f978984c83b19117d1d7c908ed7eb8409
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -31431,11 +31432,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"storybook@npm:^8.6.2":
|
||||
version: 8.6.2
|
||||
resolution: "storybook@npm:8.6.2"
|
||||
"storybook@npm:^8.6.15":
|
||||
version: 8.6.15
|
||||
resolution: "storybook@npm:8.6.15"
|
||||
dependencies:
|
||||
"@storybook/core": "npm:8.6.2"
|
||||
"@storybook/core": "npm:8.6.15"
|
||||
peerDependencies:
|
||||
prettier: ^2 || ^3
|
||||
peerDependenciesMeta:
|
||||
@@ -31445,7 +31446,7 @@ __metadata:
|
||||
getstorybook: ./bin/index.cjs
|
||||
sb: ./bin/index.cjs
|
||||
storybook: ./bin/index.cjs
|
||||
checksum: 10/81884ce80d36bfe3170c46ce08168f24a2a27b2698a9ec66ebb1a9727502ab9db3e6e221121a10606ef06db466966b47a12b48b99e519755c508bc183a2de815
|
||||
checksum: 10/15762c79ec8444a46bc14cddfadbdd54dfd379828acd38555887a246c01e7c9ebb61e4eafafe04efb3ddf6278fb47035216e7f7d9f94fc205da148870173abdf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user