From 42bae2e9ca214334a244e29e0c88c67b12991a19 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Fri, 27 Feb 2026 14:47:48 -0500 Subject: [PATCH 1/5] feat: Manage and Create Guestbook --- public/locales/en/guestbooks.json | 91 +++++ public/locales/es/guestbooks.json | 91 +++++ src/router/routes.tsx | 32 ++ src/sections/Route.enum.ts | 6 + src/sections/guestbooks/GuestbookSkeleton.tsx | 20 ++ .../guestbooks/Guestbooks.module.scss | 138 ++++++++ .../guestbooks/GuestbooksEmptyState.tsx | 50 +++ src/sections/guestbooks/GuestbooksFactory.tsx | 20 ++ src/sections/guestbooks/ManageGuestbooks.tsx | 225 ++++++++++++ .../action-buttons/GuestbookActionButtons.tsx | 58 ++++ .../CreateGuestbook.module.scss | 63 ++++ .../create-guestbooks/CreateGuestbook.tsx | 322 ++++++++++++++++++ .../CreateGuestbookButton.tsx | 25 ++ .../CreateGuestbookFactory.tsx | 18 + 14 files changed, 1159 insertions(+) create mode 100644 public/locales/en/guestbooks.json create mode 100644 public/locales/es/guestbooks.json create mode 100644 src/sections/guestbooks/GuestbookSkeleton.tsx create mode 100644 src/sections/guestbooks/Guestbooks.module.scss create mode 100644 src/sections/guestbooks/GuestbooksEmptyState.tsx create mode 100644 src/sections/guestbooks/GuestbooksFactory.tsx create mode 100644 src/sections/guestbooks/ManageGuestbooks.tsx create mode 100644 src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx create mode 100644 src/sections/guestbooks/create-guestbooks/CreateGuestbook.module.scss create mode 100644 src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx create mode 100644 src/sections/guestbooks/create-guestbooks/CreateGuestbookButton.tsx create mode 100644 src/sections/guestbooks/create-guestbooks/CreateGuestbookFactory.tsx diff --git a/public/locales/en/guestbooks.json b/public/locales/en/guestbooks.json new file mode 100644 index 000000000..036d0f2fa --- /dev/null +++ b/public/locales/en/guestbooks.json @@ -0,0 +1,91 @@ +{ + "title": "Dataset Guestbooks", + "filters": { + "includeFromRoot": "Include Guestbooks from {{root}}" + }, + "actions": { + "create": "Create Dataset Guestbook", + "enable": "Enable", + "disable": "Disable", + "view": "View", + "copy": "Copy", + "edit": "Edit", + "downloadResponses": "Download responses", + "viewResponses": "View Responses" + }, + "errors": { + "getGuestbook": "Something went wrong getting the guestbook. Try again later." + }, + "preview": { + "title": "Preview Guestbook", + "description": "Upon downloading files the guestbook asks for the following information.", + "guestbookNameLabel": "Guestbook Name", + "guestbookDataLabel": "Collected Data", + "guestbookDataTip": "User data collected by the guestbook.", + "collectedDataLabel": "Collected Data", + "collectedDataTip": "User data collected by the guestbook.", + "accountInformation": "Account Information", + "customQuestionsLabel": "Custom Questions", + "required": "Required", + "optional": "Optional" + }, + "table": { + "name": "Guestbook Name", + "created": "Created", + "usage": "Usage", + "responses": "Responses", + "action": "Action", + "guestbookCreatedAt": "Guestbook created at {{alias}}" + }, + "emptyState": { + "whyTitle": "Why Use Guestbooks?", + "whyBullets": [ + "Guestbooks allow you to collect data about who is downloading the files from your datasets. You can decide to collect account information (username, given name & last name, affiliation, etc.) as well as create custom questions (e.g., What do you plan to use this data for?).", + "You can download the data collected from the enabled guestbooks to be able to store it outside of Dataverse." + ], + "howTitle": "How To Use Guestbooks", + "howBullets": [ + "A guestbook can be used for multiple datasets but only one guestbook can be used for a dataset.", + "Custom questions can have free form text answers or have a user select an answer from several options." + ], + "footer": "To get started, click on Edit Collection in this Dataverse and then select General Information. To learn more about guestbooks, visit the Dataset Guestbook section of the User Guide." + }, + "create": { + "title": "Create Dataset Guestbook", + "info": "To learn more about guestbooks, visit the Dataset Guestbook section of the User Guide.", + "fields": { + "name": { + "label": "Guestbook Name" + }, + "dataCollected": { + "label": "Data Collected", + "help": "Dataverse account information that will be collected when a user downloads a file. Check the ones that will be required.", + "options": { + "name": "Name", + "email": "Email", + "institution": "Institution", + "position": "Position" + } + }, + "customQuestions": { + "label": "Custom Questions", + "help": "Create your own questions to have users provide more than their account information when they download a file. Questions can be required or optional and answers can be text or multiple choice.", + "typeLabel": "Question Type", + "questionText": "Question Text", + "required": "Required field", + "addQuestion": "Add question", + "types": { + "singleLine": "Single Line", + "multipleLine": "Multiple Line", + "multipleChoice": "Multiple Choice" + }, + "responseOptions": "Response Options", + "addOption": "Add response option", + "removeOption": "Remove response option", + "removeQuestion": "Remove question" + } + }, + "submit": "Create Dataset Guestbook", + "cancel": "Cancel" + } +} diff --git a/public/locales/es/guestbooks.json b/public/locales/es/guestbooks.json new file mode 100644 index 000000000..a44359d98 --- /dev/null +++ b/public/locales/es/guestbooks.json @@ -0,0 +1,91 @@ +{ + "title": "Libros de visitas de datasets", + "filters": { + "includeFromRoot": "Incluir libros de visitas de {{root}}" + }, + "actions": { + "create": "Crear libro de visitas de dataset", + "enable": "Habilitar", + "disable": "Deshabilitar", + "view": "Ver", + "copy": "Copiar", + "edit": "Editar", + "downloadResponses": "Descargar respuestas", + "viewResponses": "Ver respuestas" + }, + "errors": { + "getGuestbook": "Ocurrió un error al obtener el libro de visitas. Inténtalo de nuevo más tarde." + }, + "preview": { + "title": "Vista previa del libro de visitas", + "description": "Al descargar archivos, el libro de visitas solicita la siguiente información.", + "guestbookNameLabel": "Nombre del libro de visitas", + "guestbookDataLabel": "Datos recopilados", + "guestbookDataTip": "Datos de usuario recopilados por el libro de visitas.", + "collectedDataLabel": "Datos recopilados", + "collectedDataTip": "Datos de usuario recopilados por el libro de visitas.", + "accountInformation": "Información de cuenta", + "customQuestionsLabel": "Preguntas personalizadas", + "required": "Obligatorio", + "optional": "Opcional" + }, + "table": { + "name": "Nombre del libro de visitas", + "created": "Creado", + "usage": "Uso", + "responses": "Respuestas", + "action": "Acción", + "guestbookCreatedAt": "Libro de visitas creado en {{alias}}" + }, + "emptyState": { + "whyTitle": "¿Por qué usar libros de visitas?", + "whyBullets": [ + "Los libros de visitas te permiten recopilar datos sobre quién está descargando los archivos de tus datasets. Puedes decidir recopilar información de cuenta (nombre de usuario, nombre y apellido, afiliación, etc.) así como crear preguntas personalizadas (p. ej., ¿Para qué planeas usar estos datos?).", + "Puedes descargar los datos recopilados de los libros de visitas habilitados para almacenarlos fuera de Dataverse." + ], + "howTitle": "Cómo usar libros de visitas", + "howBullets": [ + "Un libro de visitas puede usarse para varios datasets, pero solo un libro de visitas puede usarse para un dataset.", + "Las preguntas personalizadas pueden tener respuestas de texto libre o permitir que un usuario seleccione una respuesta entre varias opciones." + ], + "footer": "Para comenzar, haz clic en Editar colección en este Dataverse y luego selecciona Información general. Para aprender más sobre los libros de visitas, visita la sección Dataset Guestbook de la Guía del usuario." + }, + "create": { + "title": "Crear libro de visitas de dataset", + "info": "Para aprender más sobre los libros de visitas, visita la sección Dataset Guestbook de la Guía del usuario.", + "fields": { + "name": { + "label": "Nombre del libro de visitas" + }, + "dataCollected": { + "label": "Datos recopilados", + "help": "Información de cuenta de Dataverse que se recopilará cuando un usuario descargue un archivo. Marca los campos que serán obligatorios.", + "options": { + "name": "Nombre", + "email": "Correo electrónico", + "institution": "Institución", + "position": "Cargo" + } + }, + "customQuestions": { + "label": "Preguntas personalizadas", + "help": "Crea tus propias preguntas para que los usuarios proporcionen más que su información de cuenta cuando descarguen un archivo. Las preguntas pueden ser obligatorias u opcionales y las respuestas pueden ser texto o de opción múltiple.", + "typeLabel": "Tipo de pregunta", + "questionText": "Texto de la pregunta", + "required": "Campo obligatorio", + "addQuestion": "Agregar pregunta", + "types": { + "singleLine": "Una línea", + "multipleLine": "Varias líneas", + "multipleChoice": "Opción múltiple" + }, + "responseOptions": "Opciones de respuesta", + "addOption": "Agregar opción de respuesta", + "removeOption": "Eliminar opción de respuesta", + "removeQuestion": "Eliminar pregunta" + } + }, + "submit": "Crear libro de visitas de dataset", + "cancel": "Cancelar" + } +} diff --git a/src/router/routes.tsx b/src/router/routes.tsx index 089a17d85..2206d6ebd 100644 --- a/src/router/routes.tsx +++ b/src/router/routes.tsx @@ -113,6 +113,20 @@ const FeaturedItemPage = lazy(() => })) ) +const GuestbooksPage = lazy(() => + import('../sections/guestbooks/GuestbooksFactory').then(({ GuestbooksFactory }) => ({ + default: () => GuestbooksFactory.create() + })) +) + +const CreateGuestbookPage = lazy(() => + import('../sections/guestbooks/create-guestbooks/CreateGuestbookFactory').then( + ({ CreateGuestbookFactory }) => ({ + default: () => CreateGuestbookFactory.create() + }) + ) +) + const NotFoundPage = lazy(() => import('../sections/not-found-page/NotFoundPageFactory').then(({ NotFoundPageFactory }) => ({ default: () => NotFoundPageFactory.create() @@ -292,6 +306,24 @@ export const routes: RouteObject[] = [ ), errorElement: }, + { + path: Route.GUESTBOOKS, + element: ( + }> + + + ), + errorElement: + }, + { + path: Route.GUESTBOOKS_CREATE, + element: ( + }> + + + ), + errorElement: + }, { path: Route.EDIT_FILE_METADATA, element: ( diff --git a/src/sections/Route.enum.ts b/src/sections/Route.enum.ts index 133e043af..2264f5ee7 100644 --- a/src/sections/Route.enum.ts +++ b/src/sections/Route.enum.ts @@ -20,6 +20,9 @@ export enum Route { ACCOUNT = '/account', EDIT_COLLECTION = '/collections/:collectionId/edit', EDIT_FEATURED_ITEMS = '/collections/:collectionId/edit-featured-items', + COLLECTION_TEMPLATES = '/collections/:collectionId/templates', + GUESTBOOKS = '/collections/:collectionId/guestbooks', + GUESTBOOKS_CREATE = '/collections/:collectionId/guestbooks/create', FEATURED_ITEM = '/featured-item/:parentCollectionId/:featuredItemId', NOT_FOUND_PAGE = '/404', AUTH_CALLBACK = '/auth-callback', @@ -34,6 +37,9 @@ export const RouteWithParams = { CREATE_DATASET: (collectionId: string) => `/datasets/${collectionId}/create`, EDIT_COLLECTION: (collectionId: string) => `/collections/${collectionId}/edit`, EDIT_FEATURED_ITEMS: (collectionId: string) => `/collections/${collectionId}/edit-featured-items`, + COLLECTION_TEMPLATES: (collectionId: string) => `/collections/${collectionId}/templates`, + GUESTBOOKS: (collectionId: string) => `/collections/${collectionId}/guestbooks`, + GUESTBOOKS_CREATE: (collectionId: string) => `/collections/${collectionId}/guestbooks/create`, EDIT_FILE_METADATA: ( datasetPersistentId: string, datasetVersion: string, diff --git a/src/sections/guestbooks/GuestbookSkeleton.tsx b/src/sections/guestbooks/GuestbookSkeleton.tsx new file mode 100644 index 000000000..abd83ffaf --- /dev/null +++ b/src/sections/guestbooks/GuestbookSkeleton.tsx @@ -0,0 +1,20 @@ +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' +import { BreadcrumbsSkeleton } from '@/sections/shared/hierarchy/BreadcrumbsSkeleton' +import { SeparationLine } from '@/sections/shared/layout/SeparationLine/SeparationLine' + +export const GuestbookSkeleton = () => ( + +
+ + + + + + + + + + +
+
+) diff --git a/src/sections/guestbooks/Guestbooks.module.scss b/src/sections/guestbooks/Guestbooks.module.scss new file mode 100644 index 000000000..39c17dc85 --- /dev/null +++ b/src/sections/guestbooks/Guestbooks.module.scss @@ -0,0 +1,138 @@ +@import 'node_modules/bootstrap/scss/functions'; +@import 'node_modules/bootstrap/scss/variables'; +@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module'; + +.header { + margin-bottom: $spacer; +} + +.header-title { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 0.5rem; +} + +.subtext { + color: $dv-subtext-color; +} + +.table-actions { + display: flex; + justify-content: space-between; + align-items: center; + margin: $spacer 0; +} + +.table-actions-left { + flex: 1; +} + +.include-templates-filter { + margin-bottom: 0; +} + +@media (max-width: 576px) { + .table-actions { + flex-direction: column; + align-items: stretch; + gap: 0.75rem; + } + + .table-actions-left { + width: 100%; + } + + .create-button { + width: 100%; + justify-content: center; + } +} + +.create-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.action-group { + flex-wrap: wrap; +} + +.action-group .btn { + min-height: 2.25rem; + display: inline-flex; + align-items: center; + justify-content: center; +} + +td { + text-align: center; + vertical-align: middle; +} + +.template-origin { + display: block; + color: $dv-subtext-color; + font-style: italic; + white-space: nowrap; + overflow: hidden; + word-break: break-word; +} + +.toggle-status-button { + margin-right: 0.75rem; +} + +.name-column { + width: 32%; +} + +.action-column { + width: 32%; +} + +.sort-button { + padding: 0; + text-decoration: none; + color: inherit; + background: none; + border: none; + display: inline-flex; + align-items: center; + font-size: inherit; + font-weight: inherit; +} + +.sort-button:focus, +.sort-button:active, +.sort-button:focus-visible { + color: inherit; + box-shadow: none; + opacity: 1; +} + +.sort-button:hover { + color: inherit; +} + +.sort-button-active { + color: $dv-subtext-color; +} + +.sort-header-active { + background-color: rgba($dv-subtext-color, 0.08); + color: $dv-subtext-color; +} + +.sort-icon { + display: inline-flex; + vertical-align: middle; +} + +.empty-state { + color: $dv-subtext-color; + padding: 2rem; + border: 1px solid rgba($dv-subtext-color, 0.2); + border-radius: 0.5rem; +} diff --git a/src/sections/guestbooks/GuestbooksEmptyState.tsx b/src/sections/guestbooks/GuestbooksEmptyState.tsx new file mode 100644 index 000000000..4494bc17e --- /dev/null +++ b/src/sections/guestbooks/GuestbooksEmptyState.tsx @@ -0,0 +1,50 @@ +import { Trans, useTranslation } from 'react-i18next' +import { RouteWithParams } from '@/sections/Route.enum' +import styles from './Guestbooks.module.scss' + +interface GuestbooksEmptyStateProps { + collectionId: string +} + +export const GuestbooksEmptyState = ({ collectionId }: GuestbooksEmptyStateProps) => { + const { t } = useTranslation('guestbooks') + const emptyStateWhyBullets = t('emptyState.whyBullets', { + returnObjects: true + }) as string[] + const emptyStateHowBullets = t('emptyState.howBullets', { + returnObjects: true + }) as string[] + + const generalInfoUrl = `/spa${RouteWithParams.EDIT_COLLECTION(collectionId)}` + const guestbooksGuideUrl = + 'https://guides.dataverse.org/en/6.9/user/dataverse-management.html#dataset-guestbooks' + + return ( +
+
+

{t('emptyState.whyTitle')}

+
    + {emptyStateWhyBullets.map((item) => ( +
  • {item}
  • + ))} +
+

{t('emptyState.howTitle')}

+
    + {emptyStateHowBullets.map((item) => ( +
  • {item}
  • + ))} +
+

+ , + anchorGuide: + }} + /> +

+
+
+ ) +} diff --git a/src/sections/guestbooks/GuestbooksFactory.tsx b/src/sections/guestbooks/GuestbooksFactory.tsx new file mode 100644 index 000000000..9a3ba21fa --- /dev/null +++ b/src/sections/guestbooks/GuestbooksFactory.tsx @@ -0,0 +1,20 @@ +import { ReactElement } from 'react' +import { useParams } from 'react-router-dom' +import { CollectionJSDataverseRepository } from '@/collection/infrastructure/repositories/CollectionJSDataverseRepository' +import { Guestbooks } from './ManageGuestbooks' + +const collectionRepository = new CollectionJSDataverseRepository() + +export class GuestbooksFactory { + static create(): ReactElement { + return + } +} + +function GuestbooksWithParams() { + const { collectionId } = useParams<{ collectionId: string }>() + + return ( + + ) +} diff --git a/src/sections/guestbooks/ManageGuestbooks.tsx b/src/sections/guestbooks/ManageGuestbooks.tsx new file mode 100644 index 000000000..f7daa12aa --- /dev/null +++ b/src/sections/guestbooks/ManageGuestbooks.tsx @@ -0,0 +1,225 @@ +import { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Button, Form, Table, Alert } from '@iqss/dataverse-design-system' +import { CaretDown, CaretUp, ChevronExpand } from 'react-bootstrap-icons' +import { CollectionRepository } from '@/collection/domain/repositories/CollectionRepository' +import { Guestbook } from '@/guestbooks/domain/models/Guestbook' +import { useCollection } from '@/sections/collection/useCollection' +import { NotFoundPage } from '@/sections/not-found-page/NotFoundPage' +import { BreadcrumbsGenerator } from '@/sections/shared/hierarchy/BreadcrumbsGenerator' +import { SeparationLine } from '@/sections/shared/layout/SeparationLine/SeparationLine' +import { GuestbookActionButtons } from './action-buttons/GuestbookActionButtons' +import { CreateGuestbookButton } from './create-guestbooks/CreateGuestbookButton' +import { GuestbookSkeleton } from './GuestbookSkeleton' +import { GuestbooksEmptyState } from './GuestbooksEmptyState' +import { PreviewGuestbookModal } from './preview-modal/PreviewGuestbookModal' +import { useGetGuestbooksByCollectionId } from './useGetGuestbooksByCollectionId' +import styles from './Guestbooks.module.scss' + +interface GuestbooksProps { + collectionRepository: CollectionRepository + collectionId: string +} + +export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksProps) => { + const { t } = useTranslation('guestbooks') + const [includeGuestbooksFromRoot, setIncludeGuestbooksFromRoot] = useState(true) + const [sortBy, setSortBy] = useState<'name' | 'created' | 'usage' | 'responses' | null>(null) + const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc') + const [guestbookToPreview, setGuestbookToPreview] = useState() + + const { collection, isLoading } = useCollection(collectionRepository, collectionId) + const { guestbooks, isLoadingGuestbooksByCollectionId, errorGetGuestbooksByCollectionId } = + useGetGuestbooksByCollectionId({ + collectionIdOrAlias: collection?.id + }) + console.log('Guestbooks', guestbooks) + const rootCollectionNames = collection?.hierarchy?.toArray().map((node) => node.name) ?? [] + + const currentDataverseId = Number(collection?.id) || 1 + + const filteredGuestbooks = useMemo( + () => + includeGuestbooksFromRoot + ? guestbooks + : guestbooks.filter((guestbook) => guestbook.dataverseId === currentDataverseId), + [guestbooks, includeGuestbooksFromRoot, currentDataverseId] + ) + const sortedGuestbooks = useMemo(() => { + if (!sortBy) { + return filteredGuestbooks + } + + const sorted = [...filteredGuestbooks] + sorted.sort((first, second) => { + if (sortBy === 'name') { + return first.name.localeCompare(second.name, undefined, { sensitivity: 'base' }) + } + if (sortBy === 'created') { + return new Date(first.createTime).getTime() - new Date(second.createTime).getTime() + } + // TODO: Update after api is ready for usage and response + return first.customQuestions.length - second.customQuestions.length + }) + + return sortDirection === 'asc' ? sorted : sorted.reverse() + }, [filteredGuestbooks, sortBy, sortDirection]) + + const handleSort = (column: 'name' | 'created' | 'usage' | 'responses') => { + if (sortBy === column) { + setSortDirection((current) => (current === 'asc' ? 'desc' : 'asc')) + return + } + + setSortBy(column) + setSortDirection('asc') + } + + const sortIndicator = (column: 'name' | 'created' | 'usage' | 'responses') => { + if (sortBy === column) { + return sortDirection === 'asc' ? ( + + ) : ( + + ) + } + return + } + const sortButtonClass = (column: 'name' | 'created' | 'usage' | 'responses') => + `${styles['sort-button']}${sortBy === column ? ` ${styles['sort-button-active']}` : ''}` + const sortHeaderClass = (column: 'name' | 'created' | 'usage' | 'responses') => + sortBy === column ? styles['sort-header-active'] : '' + + if (!isLoading && !collection) { + return + } + + if (isLoading || isLoadingGuestbooksByCollectionId || !collection) { + return + } + + return ( +
+ +
+
+

{collection.name}

+ {collection.affiliation ? ( + ({collection.affiliation}) + ) : null} +
+
+ + + {guestbookToPreview && ( + setGuestbookToPreview(undefined)} + guestbook={guestbookToPreview} + /> + )} + +
+
+ {rootCollectionNames.length > 0 && ( + setIncludeGuestbooksFromRoot((current) => !current)} + className={styles['include-templates-filter']} + /> + )} +
+ +
+ {errorGetGuestbooksByCollectionId && ( + {errorGetGuestbooksByCollectionId} + )} + + {filteredGuestbooks.length === 0 ? ( + + ) : ( + + + + + + + + + + + + {sortedGuestbooks.map((guestbook) => ( + + + + {/* TODO: Update after api is ready for usage and response */} + {/* + */} + + + + + ))} + +
+ + + + + + + + + {t('table.action')} +
{guestbook.name}{new Date(guestbook.createTime).toLocaleDateString()}{guestbook.usageCount}{getGuestbookResponseCount(guestbook)}usageresponses + {guestbook.dataverseId !== currentDataverseId && ( + + {t('table.guestbookCreatedAt', { alias: guestbook.dataverseId })} + + )} + setGuestbookToPreview(guestbook)} + actionGroupClassName={styles['action-group']} + toggleStatusButtonClassName={styles['toggle-status-button']} + /> +
+ )} +
+ ) +} diff --git a/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx b/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx new file mode 100644 index 000000000..3f1398d76 --- /dev/null +++ b/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx @@ -0,0 +1,58 @@ +import { useTranslation } from 'react-i18next' +import { Button, ButtonGroup, Tooltip } from '@iqss/dataverse-design-system' +import { Download, Eye, Files, Pencil } from 'react-bootstrap-icons' + +interface GuestbookActionButtonsProps { + isEnabled: boolean + onView: () => void + actionGroupClassName?: string + toggleStatusButtonClassName?: string +} + +export const GuestbookActionButtons = ({ + isEnabled, + onView, + actionGroupClassName, + toggleStatusButtonClassName +}: GuestbookActionButtonsProps) => { + const { t } = useTranslation('guestbooks') + + return ( + + + + + + + + + + + + + + + + + ) +} diff --git a/src/sections/guestbooks/create-guestbooks/CreateGuestbook.module.scss b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.module.scss new file mode 100644 index 000000000..645f4e780 --- /dev/null +++ b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.module.scss @@ -0,0 +1,63 @@ +@import 'node_modules/bootstrap/scss/functions'; +@import 'node_modules/bootstrap/scss/variables'; +@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module'; + +.form { + margin-top: 1.5rem; +} + +.form-row { + margin-bottom: 2rem; +} + +.row-label { + font-weight: 700; +} + +.help { + color: $dv-subtext-color; + margin-bottom: 1rem; +} + +.checkboxes { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.add-question-button { + min-width: 3rem; +} + +.question-controls { + display: flex; + gap: 0.75rem; +} + +.question-block { + margin-bottom: 1rem; +} + +.response-options { + margin-top: 0.75rem; +} + +.option-row { + margin-top: 0.75rem; +} + +.option-button { + min-width: 3rem; +} + +.question-separator { + border-bottom: 1px solid rgba($dv-subtext-color, 0.2); + margin-top: 1rem; +} + +.actions { + display: flex; + align-items: center; + gap: 1rem; + margin-top: 1rem; +} diff --git a/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx new file mode 100644 index 000000000..45e242ddd --- /dev/null +++ b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx @@ -0,0 +1,322 @@ +import { useState } from 'react' +import { Trans, useTranslation } from 'react-i18next' +import { Alert, Button, Col, Form, Row } from '@iqss/dataverse-design-system' +import { useNavigate } from 'react-router-dom' +import { DashLg, PlusLg } from 'react-bootstrap-icons' +import { CollectionRepository } from '@/collection/domain/repositories/CollectionRepository' +import { GuestbookQuestionType } from '@/guestbooks/domain/models/Guestbook' +import { RouteWithParams } from '@/sections/Route.enum' +import { useCollection } from '@/sections/collection/useCollection' +import { NotFoundPage } from '@/sections/not-found-page/NotFoundPage' +import { BreadcrumbsGenerator } from '@/sections/shared/hierarchy/BreadcrumbsGenerator' +// import { GuestbookSkeleton } from './GuestbookSkeleton' +import styles from './CreateGuestbook.module.scss' + +interface CreateGuestbookProps { + collectionId: string + collectionRepository: CollectionRepository +} + +interface CustomQuestionDraft { + id: number + type: GuestbookQuestionType + questionText: string + required: boolean + responseOptions: string[] +} + +export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGuestbookProps) => { + const { t } = useTranslation('guestbooks') + const navigate = useNavigate() + const { collection, isLoading } = useCollection(collectionRepository, collectionId) + const [customQuestions, setCustomQuestions] = useState([ + { + id: 1, + type: 'text', + questionText: '', + required: false, + responseOptions: [''] + } + ]) + const guestbooksGuideUrl = + 'https://guides.dataverse.org/en/6.9/user/dataverse-management.html#dataset-guestbooks' + + const updateQuestion = ( + questionId: number, + updater: (question: CustomQuestionDraft) => CustomQuestionDraft + ) => { + setCustomQuestions((current) => + current.map((question) => (question.id === questionId ? updater(question) : question)) + ) + } + + const addQuestionAfter = (questionId: number) => { + setCustomQuestions((current) => { + const nextId = Math.max(...current.map((question) => question.id), 0) + 1 + const newQuestion: CustomQuestionDraft = { + id: nextId, + type: 'text', + questionText: '', + required: false, + responseOptions: [''] + } + + const insertionIndex = current.findIndex((question) => question.id === questionId) + if (insertionIndex === -1) { + return [...current, newQuestion] + } + + const nextQuestions = [...current] + nextQuestions.splice(insertionIndex + 1, 0, newQuestion) + return nextQuestions + }) + } + + const removeQuestion = (questionId: number) => { + setCustomQuestions((current) => { + if (current.length === 1) { + return current + } + return current.filter((question) => question.id !== questionId) + }) + } + + const addOptionLine = (questionId: number, optionIndex: number) => { + updateQuestion(questionId, (question) => { + const nextOptions = [...question.responseOptions] + nextOptions.splice(optionIndex + 1, 0, '') + return { ...question, responseOptions: nextOptions } + }) + } + + const removeOptionLine = (questionId: number, optionIndex: number) => { + updateQuestion(questionId, (question) => { + if (question.responseOptions.length === 1) { + return question + } + const nextOptions = question.responseOptions.filter((_, index) => index !== optionIndex) + return { ...question, responseOptions: nextOptions } + }) + } + + if (!isLoading && !collection) { + return + } + + if (isLoading || !collection) { + return + } + + return ( +
+ + + + + }} + /> + + +
event.preventDefault()} noValidate> + + + {t('create.fields.name.label')} + + + + + + + + + {t('create.fields.dataCollected.label')} + + +

{t('create.fields.dataCollected.help')}

+
+ + + + +
+ +
+ + + + {t('create.fields.customQuestions.label')} + + +

{t('create.fields.customQuestions.help')}

+ {customQuestions.map((question, questionIndex) => ( +
+ + + + {t('create.fields.customQuestions.typeLabel')} + + + updateQuestion(question.id, (current) => ({ + ...current, + type: event.target.value as GuestbookQuestionType + })) + }> + + + + + + + + {t('create.fields.customQuestions.questionText')} + + + updateQuestion(question.id, (current) => ({ + ...current, + questionText: event.target.value + })) + } + /> + + +
+ + +
+ +
+ + {question.type === 'options' && ( +
+ + +
+ + + + {t('create.fields.customQuestions.responseOptions')} + + + + {question.responseOptions.map((responseOption, optionIndex) => ( + + +
+ + + + updateQuestion(question.id, (current) => ({ + ...current, + responseOptions: current.responseOptions.map((option, index) => + index === optionIndex ? event.target.value : option + ) + })) + } + /> + + +
+ + +
+ + + ))} +
+ )} + + + updateQuestion(question.id, (current) => ({ + ...current, + required: !current.required + })) + } + /> + + {questionIndex !== customQuestions.length - 1 && ( +
+ )} +
+ ))} + + + +
+ + +
+ +
+ ) +} diff --git a/src/sections/guestbooks/create-guestbooks/CreateGuestbookButton.tsx b/src/sections/guestbooks/create-guestbooks/CreateGuestbookButton.tsx new file mode 100644 index 000000000..ce99ff7cf --- /dev/null +++ b/src/sections/guestbooks/create-guestbooks/CreateGuestbookButton.tsx @@ -0,0 +1,25 @@ +import { useNavigate } from 'react-router-dom' +import { useTranslation } from 'react-i18next' +import { Button } from '@iqss/dataverse-design-system' +import { PlusLg } from 'react-bootstrap-icons' +import { RouteWithParams } from '@/sections/Route.enum' + +interface CreateGuestbookButtonProps { + collectionId: string + className?: string +} + +export const CreateGuestbookButton = ({ collectionId, className }: CreateGuestbookButtonProps) => { + const { t } = useTranslation('guestbooks') + const navigate = useNavigate() + + return ( + + ) +} diff --git a/src/sections/guestbooks/create-guestbooks/CreateGuestbookFactory.tsx b/src/sections/guestbooks/create-guestbooks/CreateGuestbookFactory.tsx new file mode 100644 index 000000000..39120d69b --- /dev/null +++ b/src/sections/guestbooks/create-guestbooks/CreateGuestbookFactory.tsx @@ -0,0 +1,18 @@ +import { ReactElement } from 'react' +import { useParams } from 'react-router-dom' +import { CollectionJSDataverseRepository } from '@/collection/infrastructure/repositories/CollectionJSDataverseRepository' +import { CreateGuestbook } from './CreateGuestbook' + +const collectionRepository = new CollectionJSDataverseRepository() + +export class CreateGuestbookFactory { + static create(): ReactElement { + return + } +} + +function CreateGuestbookWithParams() { + const { collectionId } = useParams<{ collectionId: string }>() as { collectionId: string } + + return +} From ca3da348823b22eb4de7f5235e6b4521a08215a3 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Fri, 27 Feb 2026 14:49:36 -0500 Subject: [PATCH 2/5] feat: collection page --- public/locales/en/collection.json | 1 + public/locales/es/collection.json | 1 + .../edit-collection-dropdown/EditCollectionDropdown.tsx | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index c6f1a3a88..925aa8adc 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -52,6 +52,7 @@ "editCollection": { "edit": "Edit", "generalInfo": "General Information", + "datasetGuestbooks": "Dataset Guestbooks", "deleteCollection": "Delete Collection" }, "featuredItems": { diff --git a/public/locales/es/collection.json b/public/locales/es/collection.json index a7b718fa1..b06b55222 100644 --- a/public/locales/es/collection.json +++ b/public/locales/es/collection.json @@ -52,6 +52,7 @@ "editCollection": { "edit": "Editar", "generalInfo": "Información general", + "datasetGuestbooks": "Libros de visitas de datasets", "deleteCollection": "Eliminar colección" }, "featuredItems": { diff --git a/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx b/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx index eace09e12..9334b4eaf 100644 --- a/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx +++ b/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx @@ -60,7 +60,9 @@ export const EditCollectionDropdown = ({ {t('featuredItems.title')} - + + {t('editCollection.datasetGuestbooks')} + {canCollectionBeDeleted && ( <> From 9121485b0b8a17d757fdc37b91bdbea384d176f9 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Mon, 11 May 2026 15:21:35 -0400 Subject: [PATCH 3/5] feat: create guestbook integration --- public/locales/en/guestbooks.json | 4 - public/locales/es/guestbooks.json | 17 +++ .../repositories/GuestbookRepository.ts | 5 + .../domain/useCases/createGuestbook.ts | 10 ++ .../GuestbookJSDataverseRepository.ts | 9 ++ .../EditCollectionDropdown.tsx | 6 +- src/sections/guestbooks/ManageGuestbooks.tsx | 4 +- .../create-guestbooks/CreateGuestbook.tsx | 99 +++++++++++++++-- .../create-guestbooks/useCreateGuestbook.ts | 48 ++++++++ .../shared/hierarchy/BreadcrumbsGenerator.tsx | 36 +++++- .../guestbook/GuestbookMockRepository.ts | 9 +- ...ownloadWithTermsAndGuestbookModal.spec.tsx | 1 + .../DatasetGuestbook.spec.tsx | 1 + .../EditDatasetTerms.spec.tsx | 1 + .../edit-dataset-terms/EditGuestbook.spec.tsx | 1 + .../useAssignDatasetGuestbook.spec.tsx | 1 + .../useRemoveDatasetGuestbook.spec.tsx | 1 + .../access-file-menu/AccessFileMenu.spec.tsx | 2 + .../useCreateGuestbook.spec.tsx | 104 ++++++++++++++++++ .../createGuestbookRepositoryStub.ts | 1 + 20 files changed, 341 insertions(+), 19 deletions(-) create mode 100644 src/guestbooks/domain/useCases/createGuestbook.ts create mode 100644 src/sections/guestbooks/create-guestbooks/useCreateGuestbook.ts create mode 100644 tests/component/sections/guestbooks/create-guestbooks/useCreateGuestbook.spec.tsx diff --git a/public/locales/en/guestbooks.json b/public/locales/en/guestbooks.json index cf3465be3..036d0f2fa 100644 --- a/public/locales/en/guestbooks.json +++ b/public/locales/en/guestbooks.json @@ -57,8 +57,6 @@ "name": { "label": "Guestbook Name" }, - "create": { - "fields": { "dataCollected": { "label": "Data Collected", "help": "Dataverse account information that will be collected when a user downloads a file. Check the ones that will be required.", @@ -89,7 +87,5 @@ }, "submit": "Create Dataset Guestbook", "cancel": "Cancel" - } - } } } diff --git a/public/locales/es/guestbooks.json b/public/locales/es/guestbooks.json index c2f429046..4270da885 100644 --- a/public/locales/es/guestbooks.json +++ b/public/locales/es/guestbooks.json @@ -25,6 +25,23 @@ "institution": "Institución", "position": "Cargo" } + }, + "customQuestions": { + "label": "Preguntas personalizadas", + "help": "Crea tus propias preguntas para que los usuarios proporcionen más información que la de su cuenta cuando descarguen un fichero. Las preguntas pueden ser obligatorias u opcionales, y las respuestas pueden ser de texto o de opción múltiple.", + "typeLabel": "Tipo de pregunta", + "questionText": "Texto de la pregunta", + "required": "Campo obligatorio", + "addQuestion": "Añadir pregunta", + "types": { + "singleLine": "Una línea", + "multipleLine": "Varias líneas", + "multipleChoice": "Opción múltiple" + }, + "responseOptions": "Opciones de respuesta", + "addOption": "Añadir opción de respuesta", + "removeOption": "Eliminar opción de respuesta", + "removeQuestion": "Eliminar pregunta" } } } diff --git a/src/guestbooks/domain/repositories/GuestbookRepository.ts b/src/guestbooks/domain/repositories/GuestbookRepository.ts index a596c1a50..0b1b67cad 100644 --- a/src/guestbooks/domain/repositories/GuestbookRepository.ts +++ b/src/guestbooks/domain/repositories/GuestbookRepository.ts @@ -1,6 +1,11 @@ +import { type CreateGuestbookDTO } from '@iqss/dataverse-client-javascript' import { Guestbook } from '../models/Guestbook' export interface GuestbookRepository { + createGuestbook: ( + collectionIdOrAlias: number | string, + guestbook: CreateGuestbookDTO + ) => Promise getGuestbook: (guestbookId: number) => Promise getGuestbooksByCollectionId: (collectionIdOrAlias: number | string) => Promise assignDatasetGuestbook: (datasetId: number | string, guestbookId: number) => Promise diff --git a/src/guestbooks/domain/useCases/createGuestbook.ts b/src/guestbooks/domain/useCases/createGuestbook.ts new file mode 100644 index 000000000..905d630cc --- /dev/null +++ b/src/guestbooks/domain/useCases/createGuestbook.ts @@ -0,0 +1,10 @@ +import { type CreateGuestbookDTO } from '@iqss/dataverse-client-javascript' +import { GuestbookRepository } from '../repositories/GuestbookRepository' + +export function createGuestbook( + guestbookRepository: GuestbookRepository, + collectionIdOrAlias: number | string, + guestbook: CreateGuestbookDTO +): Promise { + return guestbookRepository.createGuestbook(collectionIdOrAlias, guestbook) +} diff --git a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts index 7925752ef..3883da959 100644 --- a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts +++ b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts @@ -1,5 +1,7 @@ import { assignDatasetGuestbook, + createGuestbook, + type CreateGuestbookDTO, getGuestbooksByCollectionId, getGuestbook, removeDatasetGuestbook @@ -8,6 +10,13 @@ import { GuestbookRepository } from '../../domain/repositories/GuestbookReposito import { Guestbook } from '../../domain/models/Guestbook' export class GuestbookJSDataverseRepository implements GuestbookRepository { + createGuestbook( + collectionIdOrAlias: number | string, + guestbook: CreateGuestbookDTO + ): Promise { + return createGuestbook.execute(guestbook, collectionIdOrAlias) + } + getGuestbook(guestbookId: number): Promise { return getGuestbook.execute(guestbookId).then((guestbook) => guestbook as Guestbook) } diff --git a/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx b/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx index 05988ea07..1fb666848 100644 --- a/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx +++ b/src/sections/collection/edit-collection-dropdown/EditCollectionDropdown.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { Link } from 'react-router-dom' +import { type NavigateFunction, Link, useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { DropdownButton, @@ -27,6 +27,7 @@ export const EditCollectionDropdown = ({ canUserDeleteCollection }: EditCollectionDropdownProps) => { const { t } = useTranslation('collection') + const navigate: NavigateFunction = useNavigate() const [showNotImplementedModal, setShowNotImplementedModal] = useState(false) const canCollectionBeDeleted = @@ -38,6 +39,7 @@ export const EditCollectionDropdown = ({ event.stopPropagation() setShowNotImplementedModal(true) } + const handleDatasetGuestbooksClick = () => navigate(RouteWithParams.GUESTBOOKS(collection.id)) return ( <> @@ -78,7 +80,7 @@ export const EditCollectionDropdown = ({ {t('editCollection.datasetTemplates')} - + {t('editCollection.datasetGuestbooks')} diff --git a/src/sections/guestbooks/ManageGuestbooks.tsx b/src/sections/guestbooks/ManageGuestbooks.tsx index f7daa12aa..d9201c6db 100644 --- a/src/sections/guestbooks/ManageGuestbooks.tsx +++ b/src/sections/guestbooks/ManageGuestbooks.tsx @@ -12,6 +12,7 @@ import { GuestbookActionButtons } from './action-buttons/GuestbookActionButtons' import { CreateGuestbookButton } from './create-guestbooks/CreateGuestbookButton' import { GuestbookSkeleton } from './GuestbookSkeleton' import { GuestbooksEmptyState } from './GuestbooksEmptyState' +import { useGuestbookRepository } from './GuestbookRepositoryContext' import { PreviewGuestbookModal } from './preview-modal/PreviewGuestbookModal' import { useGetGuestbooksByCollectionId } from './useGetGuestbooksByCollectionId' import styles from './Guestbooks.module.scss' @@ -27,13 +28,14 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro const [sortBy, setSortBy] = useState<'name' | 'created' | 'usage' | 'responses' | null>(null) const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc') const [guestbookToPreview, setGuestbookToPreview] = useState() + const guestbookRepository = useGuestbookRepository() const { collection, isLoading } = useCollection(collectionRepository, collectionId) const { guestbooks, isLoadingGuestbooksByCollectionId, errorGetGuestbooksByCollectionId } = useGetGuestbooksByCollectionId({ + guestbookRepository, collectionIdOrAlias: collection?.id }) - console.log('Guestbooks', guestbooks) const rootCollectionNames = collection?.hierarchy?.toArray().map((node) => node.name) ?? [] const currentDataverseId = Number(collection?.id) || 1 diff --git a/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx index 45e242ddd..21008735d 100644 --- a/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx +++ b/src/sections/guestbooks/create-guestbooks/CreateGuestbook.tsx @@ -1,7 +1,8 @@ import { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' +import { type CreateGuestbookDTO } from '@iqss/dataverse-client-javascript' import { Alert, Button, Col, Form, Row } from '@iqss/dataverse-design-system' -import { useNavigate } from 'react-router-dom' +import { type NavigateFunction, useNavigate } from 'react-router-dom' import { DashLg, PlusLg } from 'react-bootstrap-icons' import { CollectionRepository } from '@/collection/domain/repositories/CollectionRepository' import { GuestbookQuestionType } from '@/guestbooks/domain/models/Guestbook' @@ -9,7 +10,9 @@ import { RouteWithParams } from '@/sections/Route.enum' import { useCollection } from '@/sections/collection/useCollection' import { NotFoundPage } from '@/sections/not-found-page/NotFoundPage' import { BreadcrumbsGenerator } from '@/sections/shared/hierarchy/BreadcrumbsGenerator' -// import { GuestbookSkeleton } from './GuestbookSkeleton' +import { useGuestbookRepository } from '../GuestbookRepositoryContext' +import { GuestbookSkeleton } from '../GuestbookSkeleton' +import { useCreateGuestbook } from './useCreateGuestbook' import styles from './CreateGuestbook.module.scss' interface CreateGuestbookProps { @@ -27,8 +30,14 @@ interface CustomQuestionDraft { export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGuestbookProps) => { const { t } = useTranslation('guestbooks') - const navigate = useNavigate() + const navigate: NavigateFunction = useNavigate() + const guestbookRepository = useGuestbookRepository() const { collection, isLoading } = useCollection(collectionRepository, collectionId) + const [guestbookName, setGuestbookName] = useState('') + const [nameRequired, setNameRequired] = useState(false) + const [emailRequired, setEmailRequired] = useState(false) + const [institutionRequired, setInstitutionRequired] = useState(false) + const [positionRequired, setPositionRequired] = useState(false) const [customQuestions, setCustomQuestions] = useState([ { id: 1, @@ -40,6 +49,15 @@ export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGu ]) const guestbooksGuideUrl = 'https://guides.dataverse.org/en/6.9/user/dataverse-management.html#dataset-guestbooks' + const guestbooksRoute = RouteWithParams.GUESTBOOKS(collectionId) + const navigateToGuestbooks = () => navigate(guestbooksRoute) + const { isCreatingGuestbook, errorCreatingGuestbook, handleCreateGuestbook } = useCreateGuestbook( + { + guestbookRepository, + collectionIdOrAlias: collectionId, + onSuccessfulCreate: navigateToGuestbooks + } + ) const updateQuestion = ( questionId: number, @@ -99,17 +117,62 @@ export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGu }) } + const buildGuestbookDTO = (): CreateGuestbookDTO => ({ + name: guestbookName.trim(), + enabled: false, + nameRequired, + emailRequired, + institutionRequired, + positionRequired, + customQuestions: customQuestions + .filter((question) => question.questionText.trim().length > 0) + .map((question, index) => ({ + question: question.questionText.trim(), + required: question.required, + displayOrder: index, + type: question.type, + hidden: false, + optionValues: + question.type === 'options' + ? question.responseOptions + .filter((option) => option.trim().length > 0) + .map((option, optionIndex) => ({ + value: option.trim(), + displayOrder: optionIndex + })) + : undefined + })) + }) + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault() + void handleCreateGuestbook(buildGuestbookDTO()) + } + if (!isLoading && !collection) { return } if (isLoading || !collection) { - return + return } return (
- + -
event.preventDefault()} noValidate> + {errorCreatingGuestbook && {errorCreatingGuestbook}} + + {t('create.fields.name.label')} - + setGuestbookName(event.target.value)} + /> @@ -141,18 +211,26 @@ export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGu setNameRequired((current) => !current)} /> setEmailRequired((current) => !current)} /> setInstitutionRequired((current) => !current)} /> setPositionRequired((current) => !current)} /> @@ -308,11 +386,14 @@ export const CreateGuestbook = ({ collectionId, collectionRepository }: CreateGu
- +
diff --git a/src/sections/guestbooks/create-guestbooks/useCreateGuestbook.ts b/src/sections/guestbooks/create-guestbooks/useCreateGuestbook.ts new file mode 100644 index 000000000..03f348d3b --- /dev/null +++ b/src/sections/guestbooks/create-guestbooks/useCreateGuestbook.ts @@ -0,0 +1,48 @@ +import { useState } from 'react' +import { type CreateGuestbookDTO, WriteError } from '@iqss/dataverse-client-javascript' +import { GuestbookRepository } from '@/guestbooks/domain/repositories/GuestbookRepository' +import { createGuestbook } from '@/guestbooks/domain/useCases/createGuestbook' +import { JSDataverseWriteErrorHandler } from '@/shared/helpers/JSDataverseWriteErrorHandler' + +interface UseCreateGuestbookProps { + guestbookRepository: GuestbookRepository + collectionIdOrAlias: number | string + onSuccessfulCreate?: (guestbookId: number) => void +} + +export const useCreateGuestbook = ({ + guestbookRepository, + collectionIdOrAlias, + onSuccessfulCreate +}: UseCreateGuestbookProps) => { + const [isCreatingGuestbook, setIsCreatingGuestbook] = useState(false) + const [errorCreatingGuestbook, setErrorCreatingGuestbook] = useState(null) + + const handleCreateGuestbook = async (guestbook: CreateGuestbookDTO) => { + setIsCreatingGuestbook(true) + setErrorCreatingGuestbook(null) + + try { + const guestbookId = await createGuestbook(guestbookRepository, collectionIdOrAlias, guestbook) + onSuccessfulCreate?.(guestbookId) + return guestbookId + } catch (err: WriteError | unknown) { + if (err instanceof WriteError) { + const error = new JSDataverseWriteErrorHandler(err) + const formattedError = + error.getReasonWithoutStatusCode() ?? /* istanbul ignore next */ error.getErrorMessage() + setErrorCreatingGuestbook(formattedError) + } else { + setErrorCreatingGuestbook('Something went wrong creating the guestbook. Try again later.') + } + } finally { + setIsCreatingGuestbook(false) + } + } + + return { + isCreatingGuestbook, + errorCreatingGuestbook, + handleCreateGuestbook + } +} diff --git a/src/sections/shared/hierarchy/BreadcrumbsGenerator.tsx b/src/sections/shared/hierarchy/BreadcrumbsGenerator.tsx index 47e251c36..e8d60ae1e 100644 --- a/src/sections/shared/hierarchy/BreadcrumbsGenerator.tsx +++ b/src/sections/shared/hierarchy/BreadcrumbsGenerator.tsx @@ -1,4 +1,5 @@ import { Breadcrumb } from '@iqss/dataverse-design-system' +import { Link } from 'react-router-dom' import { DvObjectType, UpwardHierarchyNode @@ -7,24 +8,33 @@ import { LinkToPage } from '../link-to-page/LinkToPage' import { Route } from '../../Route.enum' import styles from './BreadcrumbsGenerator.module.scss' +interface ActionItem { + text: string + url?: string +} + type BreadcrumbGeneratorProps = | { hierarchy: UpwardHierarchyNode withActionItem?: false actionItemText?: never + actionItems?: never } | { hierarchy: UpwardHierarchyNode withActionItem: true actionItemText: string + actionItems?: ActionItem[] } export function BreadcrumbsGenerator({ hierarchy, withActionItem, - actionItemText + actionItemText, + actionItems }: BreadcrumbGeneratorProps) { const hierarchyArray = hierarchy.toArray() + const resolvedActionItems = withActionItem ? actionItems ?? [{ text: actionItemText }] : [] return ( @@ -69,7 +79,29 @@ export function BreadcrumbsGenerator({ ) })} - {withActionItem && {actionItemText}} + {withActionItem && + resolvedActionItems.map((item, index) => { + const isLast = index === resolvedActionItems.length - 1 + + if (isLast || !item.url) { + return ( + + {item.text} + + ) + } + + return ( + + {item.text} + + ) + })} ) } diff --git a/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts b/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts index 076a3155e..7a37b50a2 100644 --- a/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts +++ b/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts @@ -1,4 +1,7 @@ -import { type Guestbook as JSDataverseGuestbook } from '@iqss/dataverse-client-javascript' +import { + type CreateGuestbookDTO, + type Guestbook as JSDataverseGuestbook +} from '@iqss/dataverse-client-javascript' import { GuestbookRepository } from '@/guestbooks/domain/repositories/GuestbookRepository' import { Guestbook } from '@/guestbooks/domain/models/Guestbook' @@ -39,6 +42,10 @@ export const storybookClientGuestbooks: JSDataverseGuestbook[] = [ ] export class GuestbookMockRepository implements GuestbookRepository { + createGuestbook(_collectionIdOrAlias: number | string, _guestbook: CreateGuestbookDTO) { + return Promise.resolve(storybookGuestbook.id) + } + getGuestbook(_guestbookId: number): Promise { return Promise.resolve(storybookGuestbook) } diff --git a/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx b/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx index 66095d974..f75f99e27 100644 --- a/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx +++ b/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx @@ -142,6 +142,7 @@ describe('DownloadWithTermsAndGuestbookModal', () => { Promise.resolve('/api/v1/access/datafiles/10,11?token=test') guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy .stub() .as('getGuestbook') diff --git a/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx b/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx index 42df75645..37f2e00ed 100644 --- a/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx +++ b/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx @@ -24,6 +24,7 @@ describe('DatasetGuestbook', () => { beforeEach(() => { guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(undefined), diff --git a/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx b/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx index 7d91af925..0051bfdae 100644 --- a/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx @@ -101,6 +101,7 @@ describe('EditDatasetTerms', () => { cy.viewport(1920, 1080) licenseRepository.getAvailableStandardLicenses = cy.stub().resolves(mockLicenses) guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub().resolves(mockGuestbooks), assignDatasetGuestbook: cy.stub().resolves(undefined), diff --git a/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx index 3dff96744..e24eede22 100644 --- a/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx @@ -83,6 +83,7 @@ describe('EditGuestbook', () => { beforeEach(() => { guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub().resolves(mockGuestbooks), assignDatasetGuestbook: cy.stub().resolves(undefined), diff --git a/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx index 9e43b6594..52f39ec21 100644 --- a/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx @@ -10,6 +10,7 @@ describe('useAssignDatasetGuestbook', () => { beforeEach(() => { onSuccessfulAssignDatasetGuestbook = cy.stub().as('onSuccessfulAssignDatasetGuestbook') guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), assignDatasetGuestbook: cy.stub(), diff --git a/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx index 038bb086f..54a4ca4ad 100644 --- a/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx @@ -10,6 +10,7 @@ describe('useRemoveDatasetGuestbook', () => { beforeEach(() => { onSuccessfulRemoveDatasetGuestbook = cy.stub().as('onSuccessfulRemoveDatasetGuestbook') guestbookRepository = { + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), assignDatasetGuestbook: cy.stub(), diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx index f02786603..6631f8749 100644 --- a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx @@ -197,6 +197,7 @@ describe('AccessFileMenu', () => { it('opens the guestbook modal before starting the file download', () => { const guestbookRepository: GuestbookRepository = { + createGuestbook: cy.stub().resolves(1), getGuestbook: cy.stub().as('getGuestbook').resolves(guestbook), getGuestbooksByCollectionId: cy.stub().resolves([]), assignDatasetGuestbook: cy.stub().resolves(), @@ -328,6 +329,7 @@ describe('AccessFileMenu', () => { it('opens the terms modal when custom terms exist without a guestbook', () => { const guestbookRepository: GuestbookRepository = { + createGuestbook: cy.stub().resolves(1), getGuestbook: cy.stub().as('getGuestbook').resolves(guestbook), getGuestbooksByCollectionId: cy.stub().resolves([]), assignDatasetGuestbook: cy.stub().resolves(), diff --git a/tests/component/sections/guestbooks/create-guestbooks/useCreateGuestbook.spec.tsx b/tests/component/sections/guestbooks/create-guestbooks/useCreateGuestbook.spec.tsx new file mode 100644 index 000000000..0ae1374b4 --- /dev/null +++ b/tests/component/sections/guestbooks/create-guestbooks/useCreateGuestbook.spec.tsx @@ -0,0 +1,104 @@ +import { act, renderHook } from '@testing-library/react' +import { type CreateGuestbookDTO, WriteError } from '@iqss/dataverse-client-javascript' +import { GuestbookRepository } from '@/guestbooks/domain/repositories/GuestbookRepository' +import { useCreateGuestbook } from '@/sections/guestbooks/create-guestbooks/useCreateGuestbook' +import { createGuestbookRepositoryStub } from '../createGuestbookRepositoryStub' + +const guestbook: CreateGuestbookDTO = { + name: 'Test Guestbook', + enabled: false, + emailRequired: true, + nameRequired: true, + institutionRequired: false, + positionRequired: false, + customQuestions: [ + { + question: 'How will you use this data?', + required: true, + displayOrder: 0, + type: 'text', + hidden: false + } + ] +} + +describe('useCreateGuestbook', () => { + let guestbookRepository: GuestbookRepository + let onSuccessfulCreate: Cypress.Agent + + beforeEach(() => { + guestbookRepository = createGuestbookRepositoryStub() + onSuccessfulCreate = cy.stub().as('onSuccessfulCreate') + }) + + it('creates guestbook and calls success callback', async () => { + const createGuestbookStub = + guestbookRepository.createGuestbook as Cypress.Agent + createGuestbookStub.resolves(123) + + const { result } = renderHook(() => + useCreateGuestbook({ + guestbookRepository, + collectionIdOrAlias: 'root', + onSuccessfulCreate + }) + ) + + await act(async () => { + await result.current.handleCreateGuestbook(guestbook) + }) + + expect(createGuestbookStub).to.have.been.calledOnceWith('root', guestbook) + expect(onSuccessfulCreate).to.have.been.calledOnceWith(123) + expect(result.current.errorCreatingGuestbook).to.deep.equal(null) + expect(result.current.isCreatingGuestbook).to.deep.equal(false) + }) + + it('sets formatted error when create fails with WriteError', async () => { + const writeError = new WriteError() + writeError.message = 'Request failed. Reason was: [400] Guestbook name is required' + const createGuestbookStub = + guestbookRepository.createGuestbook as Cypress.Agent + createGuestbookStub.rejects(writeError) + + const { result } = renderHook(() => + useCreateGuestbook({ + guestbookRepository, + collectionIdOrAlias: 'root', + onSuccessfulCreate + }) + ) + + await act(async () => { + await result.current.handleCreateGuestbook(guestbook) + }) + + expect(onSuccessfulCreate).to.not.have.been.called + expect(result.current.errorCreatingGuestbook).to.deep.equal('Guestbook name is required') + expect(result.current.isCreatingGuestbook).to.deep.equal(false) + }) + + it('sets default error when create fails with unknown error', async () => { + const createGuestbookStub = + guestbookRepository.createGuestbook as Cypress.Agent + createGuestbookStub.rejects(new Error('unexpected')) + + const { result } = renderHook(() => + useCreateGuestbook({ + guestbookRepository, + collectionIdOrAlias: 'root', + onSuccessfulCreate + }) + ) + + await act(async () => { + await result.current.handleCreateGuestbook(guestbook) + }) + + expect(onSuccessfulCreate).to.not.have.been.called + expect(result.current.errorCreatingGuestbook).to.deep.equal( + 'Something went wrong creating the guestbook. Try again later.' + ) + expect(result.current.isCreatingGuestbook).to.deep.equal(false) + }) +}) diff --git a/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts b/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts index a2378952b..80f2f93cb 100644 --- a/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts +++ b/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts @@ -1,6 +1,7 @@ import { GuestbookRepository } from '@/guestbooks/domain/repositories/GuestbookRepository' export const createGuestbookRepositoryStub = (): GuestbookRepository => ({ + createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), assignDatasetGuestbook: cy.stub(), From 94b9ed258888ac55c18d83b6345c7c1b3b1e8de8 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Tue, 19 May 2026 11:23:21 -0400 Subject: [PATCH 4/5] action buttons of guestbook table --- package-lock.json | 2544 ++--------------- package.json | 2 +- public/locales/en/guestbooks.json | 9 +- .../repositories/GuestbookRepository.ts | 10 + ...downloadGuestbookResponsesByDataverseId.ts | 8 + .../downloadGuestbookResponsesOfAGuestbook.ts | 9 + .../domain/useCases/setGuestbookEnabled.ts | 10 + .../GuestbookJSDataverseRepository.ts | 22 + .../guestbooks/Guestbooks.module.scss | 25 + src/sections/guestbooks/ManageGuestbooks.tsx | 114 +- .../action-buttons/GuestbookActionButtons.tsx | 93 +- .../guestbook/GuestbookMockRepository.ts | 19 + ...ownloadWithTermsAndGuestbookModal.spec.tsx | 3 + .../DatasetGuestbook.spec.tsx | 3 + .../EditDatasetTerms.spec.tsx | 3 + .../edit-dataset-terms/EditGuestbook.spec.tsx | 3 + .../useAssignDatasetGuestbook.spec.tsx | 3 + .../useRemoveDatasetGuestbook.spec.tsx | 3 + .../access-file-menu/AccessFileMenu.spec.tsx | 6 + .../GuestbookActionButtons.spec.tsx | 133 + .../guestbooks/ManageGuestbooks.spec.tsx | 316 ++ .../createGuestbookRepositoryStub.ts | 3 + 22 files changed, 980 insertions(+), 2361 deletions(-) create mode 100644 src/guestbooks/domain/useCases/downloadGuestbookResponsesByDataverseId.ts create mode 100644 src/guestbooks/domain/useCases/downloadGuestbookResponsesOfAGuestbook.ts create mode 100644 src/guestbooks/domain/useCases/setGuestbookEnabled.ts create mode 100644 tests/component/sections/guestbooks/GuestbookActionButtons.spec.tsx create mode 100644 tests/component/sections/guestbooks/ManageGuestbooks.spec.tsx diff --git a/package-lock.json b/package-lock.json index c5b242488..8ff797abe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@dnd-kit/sortable": "8.0.0", "@dnd-kit/utilities": "3.2.2", "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.1.0-alpha.4", + "@iqss/dataverse-client-javascript": "v2.2.0-pr449.8ac4f89", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", @@ -230,93 +230,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "regexpu-core": "^6.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", - "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "debug": "^4.4.3", - "lodash.debounce": "^4.0.8", - "resolve": "^1.22.11" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -326,21 +239,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", @@ -371,20 +269,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-plugin-utils": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", @@ -394,59 +278,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -474,22 +305,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helpers": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", @@ -518,109 +333,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -676,23 +388,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", @@ -700,922 +395,7 @@ "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", - "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1624,48 +404,37 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", - "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { + "node_modules/@babel/plugin-syntax-jsx": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1676,119 +445,92 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1797,16 +539,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1815,102 +555,30 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz", - "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/compat-data": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.29.0", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.29.0", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.29.0", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.15", - "babel-plugin-polyfill-corejs3": "^0.14.0", - "babel-plugin-polyfill-regenerator": "^0.6.6", - "core-js-compat": "^3.48.0", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1919,20 +587,20 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/runtime": { @@ -3285,9 +1953,9 @@ } }, "node_modules/@iqss/dataverse-client-javascript": { - "version": "2.1.0-alpha.4", - "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.1.0-alpha.4/0a0dc68d4d99581d7ec017e58dbce3407f99f5d9", - "integrity": "sha512-UwHnFSYuvhxpc/JG2cFr5+bwERZXqGfNBTMSUQwtJaj6vfHO7anJAAxAx8g/AB8b4JtR9rljnYjAbsGJXicfBw==", + "version": "2.2.0-pr449.8ac4f89", + "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.2.0-pr449.8ac4f89/a9e4add611381d0a911e723f8c8ed1f474f1466e", + "integrity": "sha512-rxtoUMBc79CqQwlBkJefzyS5cR/sbYPtvwO33G0R8B702MDHdRBI7cWoIy+1K3hHMgJGoDHcRXybsz9tGIEymw==", "license": "MIT", "dependencies": { "@types/node": "^18.15.11", @@ -4792,18 +3460,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -7019,6 +5675,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7032,6 +5689,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7045,6 +5703,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7058,6 +5717,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7071,6 +5731,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7084,6 +5745,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7097,6 +5759,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7110,6 +5773,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7123,6 +5787,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7136,6 +5801,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7149,6 +5815,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7162,6 +5829,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7175,6 +5843,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7188,6 +5857,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7201,6 +5871,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7214,6 +5885,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7227,6 +5899,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7240,6 +5913,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7253,6 +5927,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7266,6 +5941,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7279,6 +5955,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7292,6 +5969,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8794,6 +7472,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", @@ -9574,34 +8253,11 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, "license": "MIT" }, "node_modules/@types/graceful-fs": { @@ -10408,198 +9064,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true - }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -10680,7 +9144,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -10700,20 +9164,6 @@ "acorn-walk": "^8.0.2" } }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -10761,6 +9211,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -10818,20 +9269,6 @@ } } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -10937,6 +9374,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, "license": "MIT", "dependencies": { "default-require-extensions": "^3.0.0" @@ -10977,6 +9415,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -11349,154 +9788,6 @@ "@babel/core": "^7.8.0" } }, - "node_modules/babel-loader": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", - "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-loader/node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/babel-loader/node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "find-up": "^6.3.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", @@ -11564,51 +9855,6 @@ "dev": true, "license": "MIT" }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", - "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.8", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", - "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.8", - "core-js-compat": "^3.48.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", - "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.8" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/babel-plugin-styled-components": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", @@ -12004,7 +10250,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/byte-size": { @@ -12112,6 +10358,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, "license": "MIT", "dependencies": { "hasha": "^5.0.0", @@ -12127,6 +10374,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -12142,6 +10390,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", @@ -12436,17 +10685,6 @@ } } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.0" - } - }, "node_modules/ci-info": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", @@ -12479,6 +10717,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -12815,14 +11054,6 @@ "dev": true, "license": "ISC" }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true, - "license": "ISC", - "peer": true - }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -12837,6 +11068,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, "license": "MIT" }, "node_modules/compare-func": { @@ -13065,21 +11297,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, - "node_modules/core-js-compat": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", - "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "browserslist": "^4.28.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -13202,6 +11419,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -13593,6 +11811,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13726,6 +11945,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "dev": true, "license": "MIT", "dependencies": { "strip-bom": "^4.0.0" @@ -14248,12 +12468,14 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -14264,6 +12486,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -14283,21 +12506,6 @@ "once": "^1.4.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", - "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", @@ -14471,14 +12679,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-module-lexer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", - "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -14541,6 +12741,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, "license": "MIT" }, "node_modules/esbuild": { @@ -15226,17 +13427,6 @@ "dev": true, "license": "MIT" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", @@ -15570,6 +13760,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, "license": "MIT", "dependencies": { "commondir": "^1.0.1", @@ -15587,6 +13778,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -15865,6 +14057,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, "funding": [ { "type": "github", @@ -16047,6 +14240,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -16517,14 +14711,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true - }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -16832,6 +15018,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, "license": "MIT", "dependencies": { "is-stream": "^2.0.0", @@ -16848,6 +15035,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -16950,6 +15138,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, "license": "MIT" }, "node_modules/html-parse-stringify": { @@ -17259,6 +15448,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -17684,6 +15874,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -17936,6 +16127,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -18010,6 +16202,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, "license": "MIT" }, "node_modules/is-unc-path": { @@ -18132,6 +16325,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/isstream": { @@ -18145,6 +16339,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=8" @@ -18154,6 +16349,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "append-transform": "^2.0.0" @@ -18206,6 +16402,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "dev": true, "license": "ISC", "dependencies": { "archy": "^1.0.0", @@ -18223,6 +16420,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=8" @@ -18232,6 +16430,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" @@ -18244,6 +16443,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -18253,6 +16453,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", @@ -18267,6 +16468,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", @@ -18281,6 +16483,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", @@ -21932,21 +20135,6 @@ "node": ">=8" } }, - "node_modules/loader-runner": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", - "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -21969,18 +20157,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true, "license": "MIT" }, "node_modules/lodash.get": { @@ -22161,6 +20342,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^7.5.3" @@ -22176,6 +20358,7 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -23504,6 +21687,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { "type": "github", @@ -23819,6 +22003,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, "license": "MIT", "dependencies": { "process-on-spawn": "^1.0.0" @@ -24268,6 +22453,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", @@ -24309,6 +22495,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -24320,12 +22507,14 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true, "license": "MIT" }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -24339,6 +22528,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", @@ -24353,6 +22543,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -24373,6 +22564,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.7.5", @@ -24388,6 +22580,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -24400,6 +22593,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -24415,6 +22609,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -24430,6 +22625,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -24442,6 +22638,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" @@ -24454,6 +22651,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -24463,6 +22661,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -24477,12 +22676,14 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, "license": "ISC" }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, "license": "MIT", "dependencies": { "cliui": "^6.0.0", @@ -24505,6 +22706,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -24977,6 +23179,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, "license": "ISC", "dependencies": { "graceful-fs": "^4.1.15", @@ -25514,6 +23717,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -25633,6 +23837,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.0.0" @@ -25645,6 +23850,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -25658,6 +23864,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -25670,6 +23877,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -25685,6 +23893,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -25766,6 +23975,7 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -25987,6 +24197,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", + "dev": true, "license": "MIT", "dependencies": { "fromentries": "^1.2.0" @@ -26461,6 +24672,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -26562,6 +24774,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -27152,28 +25365,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", - "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -27207,51 +25398,11 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/regexpu-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", - "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.2", - "regjsgen": "^0.8.0", - "regjsparser": "^0.13.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.2.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/regjsparser": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", - "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "jsesc": "~3.1.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, "license": "ISC", "dependencies": { "es6-error": "^4.0.1" @@ -27358,6 +25509,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -27376,6 +25528,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, "license": "ISC" }, "node_modules/requireindex": { @@ -27534,6 +25687,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -27550,6 +25704,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -27570,6 +25725,7 @@ "version": "4.52.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz", "integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -27748,7 +25904,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/sass": { @@ -27785,49 +25941,10 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "loose-envify": "^1.1.0" } }, "node_modules/semver": { @@ -27843,6 +25960,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, "license": "ISC" }, "node_modules/set-function-length": { @@ -27902,6 +26020,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -27914,6 +26033,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -28008,6 +26128,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, "license": "ISC" }, "node_modules/sigstore": { @@ -28157,6 +26278,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -28203,6 +26325,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^2.0.0", @@ -28220,6 +26343,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", @@ -28233,6 +26357,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -28242,6 +26367,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -28483,6 +26609,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -28600,6 +26727,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -28626,6 +26754,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -29381,21 +27510,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -29511,114 +27625,6 @@ "node": ">=4" } }, - "node_modules/terser": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz", - "integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==", - "devOptional": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "devOptional": true, - "license": "MIT", - "peer": true - }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -30328,6 +28334,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" @@ -30416,54 +28423,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", - "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", - "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/unified": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", @@ -31034,6 +28993,7 @@ "version": "5.4.20", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz", "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", + "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -31209,6 +29169,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31225,6 +29186,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31241,6 +29203,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31257,6 +29220,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31273,6 +29237,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31289,6 +29254,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31305,6 +29271,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31321,6 +29288,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31337,6 +29305,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31353,6 +29322,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31369,6 +29339,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31385,6 +29356,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31401,6 +29373,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31417,6 +29390,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31433,6 +29407,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31449,6 +29424,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31465,6 +29441,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31481,6 +29458,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31497,6 +29475,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31513,6 +29492,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31529,6 +29509,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31545,6 +29526,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31561,6 +29543,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -31574,6 +29557,7 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -31788,21 +29772,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -31829,66 +29798,6 @@ "node": ">=12" } }, - "node_modules/webpack": { - "version": "5.106.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", - "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.16.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.20.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "loader-runner": "^4.3.1", - "mime-db": "^1.54.0", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.17", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.4" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.0.tgz", - "integrity": "sha512-gHwIe1cgBvvfLeu1Yz/dcFpmHfKDVxxyqI+kzqmuxZED81z2ChxpyqPaWcNqigPywhaEke7AjSGga+kxY55gjQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webpack-virtual-modules": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", @@ -31896,17 +29805,6 @@ "dev": true, "license": "MIT" }, - "node_modules/webpack/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -31961,6 +29859,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -32041,6 +29940,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, "license": "ISC" }, "node_modules/which-typed-array": { diff --git a/package.json b/package.json index 6d54dca10..d1b5d8d7c 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@dnd-kit/sortable": "8.0.0", "@dnd-kit/utilities": "3.2.2", "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.1.0-alpha.4", + "@iqss/dataverse-client-javascript": "v2.2.0-pr449.8ac4f89", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", diff --git a/public/locales/en/guestbooks.json b/public/locales/en/guestbooks.json index 036d0f2fa..73d9e1c21 100644 --- a/public/locales/en/guestbooks.json +++ b/public/locales/en/guestbooks.json @@ -7,6 +7,7 @@ "create": "Create Dataset Guestbook", "enable": "Enable", "disable": "Disable", + "downloadAllResponses": "Download All Responses", "view": "View", "copy": "Copy", "edit": "Edit", @@ -14,7 +15,13 @@ "viewResponses": "View Responses" }, "errors": { - "getGuestbook": "Something went wrong getting the guestbook. Try again later." + "getGuestbook": "Something went wrong getting the guestbook. Try again later.", + "toggleEnabled": "Something went wrong updating the guestbook status. Try again later.", + "downloadResponses": "Something went wrong downloading guestbook responses. Try again later." + }, + "alerts": { + "statusUpdated": "The guestbook status has been updated.", + "downloadStarted": "Your download has started." }, "preview": { "title": "Preview Guestbook", diff --git a/src/guestbooks/domain/repositories/GuestbookRepository.ts b/src/guestbooks/domain/repositories/GuestbookRepository.ts index 0b1b67cad..dc01f3736 100644 --- a/src/guestbooks/domain/repositories/GuestbookRepository.ts +++ b/src/guestbooks/domain/repositories/GuestbookRepository.ts @@ -8,6 +8,16 @@ export interface GuestbookRepository { ) => Promise getGuestbook: (guestbookId: number) => Promise getGuestbooksByCollectionId: (collectionIdOrAlias: number | string) => Promise + setGuestbookEnabled: ( + collectionIdOrAlias: number | string, + guestbookId: number, + enabled: boolean + ) => Promise + downloadGuestbookResponsesByDataverseId: (dataverseId: number | string) => Promise + downloadGuestbookResponsesOfAGuestbook: ( + dataverseId: number | string, + guestbookId: number + ) => Promise assignDatasetGuestbook: (datasetId: number | string, guestbookId: number) => Promise removeDatasetGuestbook: (datasetId: number | string) => Promise } diff --git a/src/guestbooks/domain/useCases/downloadGuestbookResponsesByDataverseId.ts b/src/guestbooks/domain/useCases/downloadGuestbookResponsesByDataverseId.ts new file mode 100644 index 000000000..b4614617b --- /dev/null +++ b/src/guestbooks/domain/useCases/downloadGuestbookResponsesByDataverseId.ts @@ -0,0 +1,8 @@ +import { GuestbookRepository } from '../repositories/GuestbookRepository' + +export function downloadGuestbookResponsesByDataverseId( + guestbookRepository: GuestbookRepository, + dataverseId: number | string +): Promise { + return guestbookRepository.downloadGuestbookResponsesByDataverseId(dataverseId) +} diff --git a/src/guestbooks/domain/useCases/downloadGuestbookResponsesOfAGuestbook.ts b/src/guestbooks/domain/useCases/downloadGuestbookResponsesOfAGuestbook.ts new file mode 100644 index 000000000..5c4ca2d99 --- /dev/null +++ b/src/guestbooks/domain/useCases/downloadGuestbookResponsesOfAGuestbook.ts @@ -0,0 +1,9 @@ +import { GuestbookRepository } from '../repositories/GuestbookRepository' + +export function downloadGuestbookResponsesOfAGuestbook( + guestbookRepository: GuestbookRepository, + dataverseId: number | string, + guestbookId: number +): Promise { + return guestbookRepository.downloadGuestbookResponsesOfAGuestbook(dataverseId, guestbookId) +} diff --git a/src/guestbooks/domain/useCases/setGuestbookEnabled.ts b/src/guestbooks/domain/useCases/setGuestbookEnabled.ts new file mode 100644 index 000000000..77dad1d2d --- /dev/null +++ b/src/guestbooks/domain/useCases/setGuestbookEnabled.ts @@ -0,0 +1,10 @@ +import { GuestbookRepository } from '../repositories/GuestbookRepository' + +export function setGuestbookEnabled( + guestbookRepository: GuestbookRepository, + collectionIdOrAlias: number | string, + guestbookId: number, + enabled: boolean +): Promise { + return guestbookRepository.setGuestbookEnabled(collectionIdOrAlias, guestbookId, enabled) +} diff --git a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts index 3883da959..7dea72251 100644 --- a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts +++ b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts @@ -1,9 +1,12 @@ import { assignDatasetGuestbook, createGuestbook, + downloadGuestbookResponsesByDataverseId, + downloadGuestbookResponsesOfAGuestbook, type CreateGuestbookDTO, getGuestbooksByCollectionId, getGuestbook, + setGuestbookEnabled, removeDatasetGuestbook } from '@iqss/dataverse-client-javascript' import { GuestbookRepository } from '../../domain/repositories/GuestbookRepository' @@ -27,6 +30,25 @@ export class GuestbookJSDataverseRepository implements GuestbookRepository { .then((guestbooks) => guestbooks as Guestbook[]) } + setGuestbookEnabled( + collectionIdOrAlias: number | string, + guestbookId: number, + enabled: boolean + ): Promise { + return setGuestbookEnabled.execute(collectionIdOrAlias, guestbookId, enabled) + } + + downloadGuestbookResponsesByDataverseId(dataverseId: number | string): Promise { + return downloadGuestbookResponsesByDataverseId.execute(dataverseId) + } + + downloadGuestbookResponsesOfAGuestbook( + dataverseId: number | string, + guestbookId: number + ): Promise { + return downloadGuestbookResponsesOfAGuestbook.execute(dataverseId, guestbookId) + } + assignDatasetGuestbook(datasetId: number | string, guestbookId: number): Promise { return assignDatasetGuestbook.execute(datasetId, guestbookId) } diff --git a/src/sections/guestbooks/Guestbooks.module.scss b/src/sections/guestbooks/Guestbooks.module.scss index 39c17dc85..4ed8768df 100644 --- a/src/sections/guestbooks/Guestbooks.module.scss +++ b/src/sections/guestbooks/Guestbooks.module.scss @@ -28,10 +28,25 @@ flex: 1; } +.table-actions-right { + display: flex; + align-items: center; + gap: 1rem; + flex-wrap: wrap; + justify-content: flex-end; +} + .include-templates-filter { margin-bottom: 0; } +.download-all-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + white-space: nowrap; +} + @media (max-width: 576px) { .table-actions { flex-direction: column; @@ -43,10 +58,20 @@ width: 100%; } + .table-actions-right { + width: 100%; + justify-content: stretch; + } + .create-button { width: 100%; justify-content: center; } + + .download-all-button { + width: 100%; + justify-content: center; + } } .create-button { diff --git a/src/sections/guestbooks/ManageGuestbooks.tsx b/src/sections/guestbooks/ManageGuestbooks.tsx index d9201c6db..4ba14e39b 100644 --- a/src/sections/guestbooks/ManageGuestbooks.tsx +++ b/src/sections/guestbooks/ManageGuestbooks.tsx @@ -1,13 +1,18 @@ -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { Button, Form, Table, Alert } from '@iqss/dataverse-design-system' -import { CaretDown, CaretUp, ChevronExpand } from 'react-bootstrap-icons' +import { CaretDown, CaretUp, ChevronExpand, Download } from 'react-bootstrap-icons' +import { toast } from 'react-toastify' import { CollectionRepository } from '@/collection/domain/repositories/CollectionRepository' import { Guestbook } from '@/guestbooks/domain/models/Guestbook' +import { downloadGuestbookResponsesByDataverseId } from '@/guestbooks/domain/useCases/downloadGuestbookResponsesByDataverseId' +import { downloadGuestbookResponsesOfAGuestbook } from '@/guestbooks/domain/useCases/downloadGuestbookResponsesOfAGuestbook' +import { setGuestbookEnabled } from '@/guestbooks/domain/useCases/setGuestbookEnabled' import { useCollection } from '@/sections/collection/useCollection' import { NotFoundPage } from '@/sections/not-found-page/NotFoundPage' import { BreadcrumbsGenerator } from '@/sections/shared/hierarchy/BreadcrumbsGenerator' import { SeparationLine } from '@/sections/shared/layout/SeparationLine/SeparationLine' +import { downloadFile } from '@/sections/shared/citation/citation-download/useDownloadCitation' import { GuestbookActionButtons } from './action-buttons/GuestbookActionButtons' import { CreateGuestbookButton } from './create-guestbooks/CreateGuestbookButton' import { GuestbookSkeleton } from './GuestbookSkeleton' @@ -28,6 +33,12 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro const [sortBy, setSortBy] = useState<'name' | 'created' | 'usage' | 'responses' | null>(null) const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc') const [guestbookToPreview, setGuestbookToPreview] = useState() + const [displayGuestbooks, setDisplayGuestbooks] = useState([]) + const [togglingGuestbookId, setTogglingGuestbookId] = useState() + const [toggleGuestbookError, setToggleGuestbookError] = useState(null) + const [isDownloadingAllResponses, setIsDownloadingAllResponses] = useState(false) + const [downloadingGuestbookId, setDownloadingGuestbookId] = useState() + const [downloadResponsesError, setDownloadResponsesError] = useState(null) const guestbookRepository = useGuestbookRepository() const { collection, isLoading } = useCollection(collectionRepository, collectionId) @@ -40,12 +51,16 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro const currentDataverseId = Number(collection?.id) || 1 + useEffect(() => { + setDisplayGuestbooks(guestbooks) + }, [guestbooks]) + const filteredGuestbooks = useMemo( () => includeGuestbooksFromRoot - ? guestbooks - : guestbooks.filter((guestbook) => guestbook.dataverseId === currentDataverseId), - [guestbooks, includeGuestbooksFromRoot, currentDataverseId] + ? displayGuestbooks + : displayGuestbooks.filter((guestbook) => guestbook.dataverseId === currentDataverseId), + [displayGuestbooks, includeGuestbooksFromRoot, currentDataverseId] ) const sortedGuestbooks = useMemo(() => { if (!sortBy) { @@ -92,6 +107,77 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro const sortHeaderClass = (column: 'name' | 'created' | 'usage' | 'responses') => sortBy === column ? styles['sort-header-active'] : '' + const handleToggleEnabled = async (guestbook: Guestbook) => { + setToggleGuestbookError(null) + setTogglingGuestbookId(guestbook.id) + + try { + await setGuestbookEnabled( + guestbookRepository, + guestbook.dataverseId, + guestbook.id, + !guestbook.enabled + ) + setDisplayGuestbooks((currentGuestbooks) => + currentGuestbooks.map((currentGuestbook) => + currentGuestbook.id === guestbook.id + ? { ...currentGuestbook, enabled: !currentGuestbook.enabled } + : currentGuestbook + ) + ) + toast.success(t('alerts.statusUpdated')) + } catch { + setToggleGuestbookError(t('errors.toggleEnabled')) + } finally { + setTogglingGuestbookId(undefined) + } + } + + const handleDownloadResponses = async (guestbook: Guestbook) => { + setDownloadResponsesError(null) + setDownloadingGuestbookId(guestbook.id) + + try { + const csvContent = await downloadGuestbookResponsesOfAGuestbook( + guestbookRepository, + guestbook.dataverseId, + guestbook.id + ) + downloadFile(csvContent, `${guestbook.name}-responses.csv`, 'text/csv;charset=utf-8') + toast.success(t('alerts.downloadStarted')) + } catch { + setDownloadResponsesError(t('errors.downloadResponses')) + } finally { + setDownloadingGuestbookId(undefined) + } + } + + const handleDownloadAllResponses = async () => { + if (!collection) { + return + } + + setDownloadResponsesError(null) + setIsDownloadingAllResponses(true) + + try { + const csvContent = await downloadGuestbookResponsesByDataverseId( + guestbookRepository, + collection.id + ) + downloadFile( + csvContent, + `${collection.name}-all-guestbook-responses.csv`, + 'text/csv;charset=utf-8' + ) + toast.success(t('alerts.downloadStarted')) + } catch { + setDownloadResponsesError(t('errors.downloadResponses')) + } finally { + setIsDownloadingAllResponses(false) + } + } + if (!isLoading && !collection) { return } @@ -137,11 +223,23 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro /> )} - +
+ + +
{errorGetGuestbooksByCollectionId && ( {errorGetGuestbooksByCollectionId} )} + {toggleGuestbookError && {toggleGuestbookError}} + {downloadResponsesError && {downloadResponsesError}} {filteredGuestbooks.length === 0 ? ( @@ -213,6 +311,10 @@ export const Guestbooks = ({ collectionRepository, collectionId }: GuestbooksPro setGuestbookToPreview(guestbook)} + onToggleEnabled={() => handleToggleEnabled(guestbook)} + isTogglingEnabled={togglingGuestbookId === guestbook.id} + onDownloadResponses={() => handleDownloadResponses(guestbook)} + isDownloadingResponses={downloadingGuestbookId === guestbook.id} actionGroupClassName={styles['action-group']} toggleStatusButtonClassName={styles['toggle-status-button']} /> diff --git a/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx b/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx index 3f1398d76..bdb6579a4 100644 --- a/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx +++ b/src/sections/guestbooks/action-buttons/GuestbookActionButtons.tsx @@ -1,10 +1,16 @@ +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { Button, ButtonGroup, Tooltip } from '@iqss/dataverse-design-system' import { Download, Eye, Files, Pencil } from 'react-bootstrap-icons' +import { NotImplementedModal } from '@/sections/not-implemented/NotImplementedModal' interface GuestbookActionButtonsProps { isEnabled: boolean onView: () => void + onToggleEnabled: () => void + isTogglingEnabled?: boolean + onDownloadResponses: () => void + isDownloadingResponses?: boolean actionGroupClassName?: string toggleStatusButtonClassName?: string } @@ -12,47 +18,72 @@ interface GuestbookActionButtonsProps { export const GuestbookActionButtons = ({ isEnabled, onView, + onToggleEnabled, + isTogglingEnabled = false, + onDownloadResponses, + isDownloadingResponses = false, actionGroupClassName, toggleStatusButtonClassName }: GuestbookActionButtonsProps) => { const { t } = useTranslation('guestbooks') + const [showNotImplementedModal, setShowNotImplementedModal] = useState(false) return ( - - - - - - - - - - - - + + + + + + + + + + + + - - - + + setShowNotImplementedModal(false)} + /> + ) } diff --git a/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts b/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts index 7a37b50a2..e32ca1f70 100644 --- a/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts +++ b/src/stories/shared-mock-repositories/guestbook/GuestbookMockRepository.ts @@ -54,6 +54,25 @@ export class GuestbookMockRepository implements GuestbookRepository { return Promise.resolve(storybookClientGuestbooks as Guestbook[]) } + setGuestbookEnabled( + _collectionIdOrAlias: number | string, + _guestbookId: number, + _enabled: boolean + ): Promise { + return Promise.resolve() + } + + downloadGuestbookResponsesByDataverseId(_dataverseId: number | string): Promise { + return Promise.resolve('name,email\nJane Doe,jane@example.com') + } + + downloadGuestbookResponsesOfAGuestbook( + _dataverseId: number | string, + _guestbookId: number + ): Promise { + return Promise.resolve('name,email\nJane Doe,jane@example.com') + } + assignDatasetGuestbook(_datasetId: number | string, _guestbookId: number): Promise { return Promise.resolve() } diff --git a/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx b/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx index f75f99e27..0952748e7 100644 --- a/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx +++ b/tests/component/sections/dataset/dataset-files/guestbook/DownloadWithTermsAndGuestbookModal.spec.tsx @@ -150,6 +150,9 @@ describe('DownloadWithTermsAndGuestbookModal', () => { return getGuestbookImpl(guestbookId) }), getGuestbooksByCollectionId: cy.stub().resolves([]), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: (_datasetId: number | string, _guestbookId: number) => Promise.resolve(), removeDatasetGuestbook: (_datasetId: number | string) => Promise.resolve() diff --git a/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx b/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx index 37f2e00ed..2ee871b68 100644 --- a/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx +++ b/tests/component/sections/dataset/dataset-guestbook/DatasetGuestbook.spec.tsx @@ -27,6 +27,9 @@ describe('DatasetGuestbook', () => { createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(undefined), removeDatasetGuestbook: cy.stub().resolves(undefined) } diff --git a/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx b/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx index 0051bfdae..3d755f384 100644 --- a/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/EditDatasetTerms.spec.tsx @@ -104,6 +104,9 @@ describe('EditDatasetTerms', () => { createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub().resolves(mockGuestbooks), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(undefined), removeDatasetGuestbook: cy.stub().resolves(undefined) } diff --git a/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx index e24eede22..2a9689797 100644 --- a/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/EditGuestbook.spec.tsx @@ -86,6 +86,9 @@ describe('EditGuestbook', () => { createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub().resolves(mockGuestbooks), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(undefined), removeDatasetGuestbook: cy.stub().resolves(undefined) } diff --git a/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx index 52f39ec21..ffb72606c 100644 --- a/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/useAssignDatasetGuestbook.spec.tsx @@ -13,6 +13,9 @@ describe('useAssignDatasetGuestbook', () => { createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub(), removeDatasetGuestbook: cy.stub() } diff --git a/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx b/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx index 54a4ca4ad..b2af96ed9 100644 --- a/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx +++ b/tests/component/sections/edit-dataset-terms/useRemoveDatasetGuestbook.spec.tsx @@ -13,6 +13,9 @@ describe('useRemoveDatasetGuestbook', () => { createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub(), removeDatasetGuestbook: cy.stub() } diff --git a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx index 6631f8749..465d1b263 100644 --- a/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx +++ b/tests/component/sections/file/file-action-buttons/access-file-menu/AccessFileMenu.spec.tsx @@ -200,6 +200,9 @@ describe('AccessFileMenu', () => { createGuestbook: cy.stub().resolves(1), getGuestbook: cy.stub().as('getGuestbook').resolves(guestbook), getGuestbooksByCollectionId: cy.stub().resolves([]), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(), removeDatasetGuestbook: cy.stub().resolves() } @@ -332,6 +335,9 @@ describe('AccessFileMenu', () => { createGuestbook: cy.stub().resolves(1), getGuestbook: cy.stub().as('getGuestbook').resolves(guestbook), getGuestbooksByCollectionId: cy.stub().resolves([]), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub().resolves(), removeDatasetGuestbook: cy.stub().resolves() } diff --git a/tests/component/sections/guestbooks/GuestbookActionButtons.spec.tsx b/tests/component/sections/guestbooks/GuestbookActionButtons.spec.tsx new file mode 100644 index 000000000..af55808db --- /dev/null +++ b/tests/component/sections/guestbooks/GuestbookActionButtons.spec.tsx @@ -0,0 +1,133 @@ +import { useState } from 'react' +import { Guestbook } from '@/guestbooks/domain/models/Guestbook' +import { GuestbookActionButtons } from '@/sections/guestbooks/action-buttons/GuestbookActionButtons' +import { PreviewGuestbookModal } from '@/sections/guestbooks/preview-modal/PreviewGuestbookModal' + +const guestbook: Guestbook = { + id: 10, + name: 'Downloadable Guestbook', + enabled: true, + emailRequired: true, + nameRequired: true, + institutionRequired: false, + positionRequired: false, + customQuestions: [ + { + question: 'How will you use this data?', + required: true, + displayOrder: 1, + type: 'text', + hidden: false + } + ], + createTime: '2026-01-01T00:00:00.000Z', + dataverseId: 17 +} + +const GuestbookActionButtonsTestWrapper = ({ + isEnabled = true, + isTogglingEnabled = false, + isDownloadingResponses = false, + onToggleEnabled = () => {}, + onDownloadResponses = () => {} +}: { + isEnabled?: boolean + isTogglingEnabled?: boolean + isDownloadingResponses?: boolean + onToggleEnabled?: () => void + onDownloadResponses?: () => void +}) => { + const [showPreview, setShowPreview] = useState(false) + + return ( + <> + setShowPreview(true)} + onToggleEnabled={onToggleEnabled} + isTogglingEnabled={isTogglingEnabled} + onDownloadResponses={onDownloadResponses} + isDownloadingResponses={isDownloadingResponses} + /> + setShowPreview(false)} + guestbook={guestbook} + /> + + ) +} + +describe('GuestbookActionButtons', () => { + it('renders Disable when guestbook is enabled and triggers toggle handler', () => { + const onToggleEnabled = cy.stub().as('onToggleEnabled') + + cy.customMount() + + cy.findByRole('button', { name: 'Disable' }).click() + cy.get('@onToggleEnabled').should('have.been.calledOnce') + }) + + it('renders Enable when guestbook is disabled', () => { + cy.customMount() + + cy.findByRole('button', { name: 'Enable' }).should('exist') + }) + + it('opens and closes the preview guestbook modal from the view button', () => { + cy.customMount() + + cy.findByRole('button', { name: 'View' }).click() + cy.findByRole('dialog').should('be.visible') + cy.findByText('Preview Guestbook').should('exist') + cy.findByText('Downloadable Guestbook').should('exist') + cy.findByText(/How will you use this data\?/).should('exist') + cy.findByText('Close').click() + cy.findByRole('dialog').should('not.exist') + }) + + it('triggers download handler', () => { + const onDownloadResponses = cy.stub().as('onDownloadResponses') + + cy.customMount() + + cy.findByRole('button', { name: 'Download responses' }).click() + cy.get('@onDownloadResponses').should('have.been.calledOnce') + }) + + it('opens the not implemented modal from copy, edit, and view responses buttons', () => { + cy.customMount() + + cy.findByRole('button', { name: 'Copy' }).click() + cy.findByText('Not Implemented').should('exist') + cy.findByText(/This feature is not implemented yet in the Modern version./i).should('exist') + cy.findByText('Close').click() + cy.findByText('Not Implemented').should('not.exist') + + cy.findByRole('button', { name: 'Edit' }).click() + cy.findByText('Not Implemented').should('exist') + cy.findByText('Close').click() + cy.findByText('Not Implemented').should('not.exist') + + cy.findByRole('button', { name: 'View Responses' }).click() + cy.findByText('Not Implemented').should('exist') + }) + + it('keeps toggle and download buttons enabled when loading flags are false', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Disable' }).should('not.be.disabled') + cy.findByRole('button', { name: 'Download responses' }).should('not.be.disabled') + }) + + it('disables toggle and download buttons while actions are in progress', () => { + cy.customMount( + + ) + + cy.findByRole('button', { name: 'Disable' }).should('be.disabled') + cy.findByRole('button', { name: 'Download responses' }).should('be.disabled') + }) +}) diff --git a/tests/component/sections/guestbooks/ManageGuestbooks.spec.tsx b/tests/component/sections/guestbooks/ManageGuestbooks.spec.tsx new file mode 100644 index 000000000..0461e9c9a --- /dev/null +++ b/tests/component/sections/guestbooks/ManageGuestbooks.spec.tsx @@ -0,0 +1,316 @@ +import { ReactNode, Suspense } from 'react' +import { useTranslation } from 'react-i18next' +import { CollectionRepository } from '@/collection/domain/repositories/CollectionRepository' +import { CollectionMother } from '@tests/component/collection/domain/models/CollectionMother' +import { Guestbook } from '@/guestbooks/domain/models/Guestbook' +import { GuestbookRepository } from '@/guestbooks/domain/repositories/GuestbookRepository' +import { GuestbookRepositoryProvider } from '@/sections/guestbooks/GuestbookRepositoryProvider' +import { Guestbooks } from '@/sections/guestbooks/ManageGuestbooks' + +describe('ManageGuestbooks', () => { + const collectionRepository = {} as CollectionRepository + let guestbookRepository: GuestbookRepository + + const guestbook: Guestbook = { + id: 10, + name: 'Downloadable Guestbook', + enabled: true, + emailRequired: true, + nameRequired: true, + institutionRequired: false, + positionRequired: false, + customQuestions: [], + createTime: '2026-01-01T00:00:00.000Z', + dataverseId: 17 + } + const rootGuestbook: Guestbook = { + id: 11, + name: 'Alpha Root Guestbook', + enabled: true, + emailRequired: true, + nameRequired: false, + institutionRequired: false, + positionRequired: false, + customQuestions: [], + createTime: '2025-01-01T00:00:00.000Z', + dataverseId: 1 + } + const localGuestbookLater: Guestbook = { + id: 12, + name: 'zeta local guestbook', + enabled: true, + emailRequired: true, + nameRequired: false, + institutionRequired: false, + positionRequired: false, + customQuestions: [ + { question: 'Q1', required: false, displayOrder: 1, type: 'text', hidden: false } + ], + createTime: '2027-01-01T00:00:00.000Z', + dataverseId: 17 + } + const localGuestbookMostQuestions: Guestbook = { + id: 13, + name: 'Beta Local Guestbook', + enabled: false, + emailRequired: true, + nameRequired: false, + institutionRequired: false, + positionRequired: false, + customQuestions: [ + { question: 'Q1', required: false, displayOrder: 1, type: 'text', hidden: false }, + { question: 'Q2', required: false, displayOrder: 2, type: 'text', hidden: false } + ], + createTime: '2024-01-01T00:00:00.000Z', + dataverseId: 17 + } + + const TranslationPreloader = ({ children }: { children: ReactNode }) => { + useTranslation('guestbooks') + + return <>{children} + } + + const defaultGuestbooks = [ + guestbook, + rootGuestbook, + localGuestbookLater, + localGuestbookMostQuestions + ] + + beforeEach(() => { + collectionRepository.getById = cy.stub().resolves( + CollectionMother.create({ + id: '17', + name: 'Root' + }) + ) + + guestbookRepository = { + createGuestbook: cy.stub(), + getGuestbook: cy.stub(), + getGuestbooksByCollectionId: cy.stub().resolves(defaultGuestbooks), + setGuestbookEnabled: cy.stub().as('setGuestbookEnabled').resolves(undefined), + downloadGuestbookResponsesByDataverseId: cy + .stub() + .as('downloadGuestbookResponsesByDataverseId') + .resolves('name,email\nJane Doe,jane@example.com'), + downloadGuestbookResponsesOfAGuestbook: cy + .stub() + .as('downloadGuestbookResponsesOfAGuestbook') + .resolves('name,email\nJane Doe,jane@example.com'), + assignDatasetGuestbook: cy.stub(), + removeDatasetGuestbook: cy.stub() + } + + cy.window().then((win) => { + cy.stub(win.URL, 'createObjectURL').returns('blob:guestbook-download') + cy.stub(win.URL, 'revokeObjectURL') + }) + }) + + const mountComponent = () => + cy.customMount( + + + + + + + + ) + + const getRenderedGuestbookNames = () => + cy + .get('tbody tr td:first-child') + .then(($cells) => [...$cells].map((cell) => cell.textContent?.trim() ?? '')) + + it('downloads guestbook responses from the guestbook page ui', () => { + const createElementSpy = cy.spy(document, 'createElement') + + mountComponent() + + cy.contains('tbody tr', 'Downloadable Guestbook') + .findByRole('button', { name: 'Download responses' }) + .click() + + cy.get('@downloadGuestbookResponsesOfAGuestbook').should('have.been.calledOnceWith', 17, 10) + cy.then(() => { + expect(createElementSpy).to.have.been.calledWith('a') + }) + cy.window().then((win) => { + expect(win.URL['createObjectURL']).to.have.been.called + expect(win.URL['revokeObjectURL']).to.have.been.called + }) + cy.findByText('Your download has started.').should('exist') + }) + + it('sorts guestbooks by name and toggles sort direction on repeated clicks', () => { + mountComponent() + + cy.findByRole('button', { name: /Guestbook Name/i }).click() + cy.findByRole('button', { name: /Guestbook Name/i }) + .should('have.attr', 'aria-pressed', 'true') + .invoke('attr', 'class') + .should('include', 'sort-button-active') + cy.findByRole('button', { name: /Guestbook Name/i }) + .closest('th') + .invoke('attr', 'class') + .should('include', 'sort-header-active') + getRenderedGuestbookNames().should('deep.equal', [ + 'Alpha Root Guestbook', + 'Beta Local Guestbook', + 'Downloadable Guestbook', + 'zeta local guestbook' + ]) + + cy.findByRole('button', { name: /Guestbook Name/i }).click() + getRenderedGuestbookNames().should('deep.equal', [ + 'zeta local guestbook', + 'Downloadable Guestbook', + 'Beta Local Guestbook', + 'Alpha Root Guestbook' + ]) + }) + + it('sorts guestbooks by created date', () => { + mountComponent() + + cy.findByRole('button', { name: /Created/i }).click() + + getRenderedGuestbookNames().should('deep.equal', [ + 'Beta Local Guestbook', + 'Alpha Root Guestbook', + 'Downloadable Guestbook', + 'zeta local guestbook' + ]) + }) + + it('sorts guestbooks by responses using custom question count', () => { + mountComponent() + + cy.findByRole('button', { name: /Download All Responses/i }).click() + + getRenderedGuestbookNames().should('deep.equal', [ + 'Downloadable Guestbook', + 'Alpha Root Guestbook', + 'zeta local guestbook', + 'Beta Local Guestbook' + ]) + }) + + it('filters inherited guestbooks when include guestbooks from root is toggled', () => { + mountComponent() + + cy.findByLabelText('Include Guestbooks from Root').click() + cy.findByText('Alpha Root Guestbook').should('not.exist') + cy.findByText('Downloadable Guestbook').should('exist') + cy.findByText('Beta Local Guestbook').should('exist') + + cy.findByLabelText('Include Guestbooks from Root').click() + cy.findByText('Alpha Root Guestbook').should('exist') + }) + + it('opens and closes the preview guestbook modal from the page ui', () => { + mountComponent() + + cy.findAllByRole('button', { name: 'View' }).first().click() + cy.findByRole('dialog').should('be.visible') + cy.findByText('Preview Guestbook').should('exist') + cy.findByText('Close').click() + cy.findByRole('dialog').should('not.exist') + }) + + it('downloads all guestbook responses from the dataverse use case', () => { + const createElementSpy = cy.spy(document, 'createElement') + + mountComponent() + + cy.findByText('Download All Responses').click() + + cy.get('@downloadGuestbookResponsesByDataverseId').should('have.been.calledOnceWith', '17') + cy.then(() => { + expect(createElementSpy).to.have.been.calledWith('a') + }) + cy.window().then((win) => { + expect(win.URL['createObjectURL']).to.have.been.called + expect(win.URL['revokeObjectURL']).to.have.been.called + }) + cy.findByText('Your download has started.').should('exist') + }) + + it('toggles a guestbook through the setGuestbookEnabled use case and refreshes the table', () => { + mountComponent() + + cy.contains('tbody tr', 'Downloadable Guestbook') + .findByRole('button', { name: 'Disable' }) + .click() + + cy.get('@setGuestbookEnabled').should('have.been.calledOnceWith', 17, 10, false) + cy.contains('tbody tr', 'Downloadable Guestbook') + .findByRole('button', { name: 'Enable' }) + .should('exist') + cy.findByText('The guestbook status has been updated.').should('exist') + }) + + it('shows an error when toggling guestbook status fails', () => { + ;(guestbookRepository.setGuestbookEnabled as Cypress.Agent).rejects( + new Error('toggle failed') + ) + + mountComponent() + + cy.contains('tbody tr', 'Downloadable Guestbook') + .findByRole('button', { name: 'Disable' }) + .click() + + cy.findByText(/Something went wrong updating the guestbook status. Try again later.*/i).should( + 'exist' + ) + }) + + it('shows an error when guestbook response download fails', () => { + ;( + guestbookRepository.downloadGuestbookResponsesOfAGuestbook as Cypress.Agent + ).rejects(new Error('download failed')) + + mountComponent() + + cy.contains('tbody tr', 'Downloadable Guestbook') + .findByRole('button', { name: 'Download responses' }) + .click() + + cy.findByText( + /Something went wrong downloading guestbook responses. Try again later.*/i + ).should('exist') + }) + + it('shows an error when downloading all guestbook responses fails', () => { + ;( + guestbookRepository.downloadGuestbookResponsesByDataverseId as Cypress.Agent + ).rejects(new Error('download failed')) + + mountComponent() + + cy.findByText('Download All Responses').click() + + cy.findByText( + /Something went wrong downloading guestbook responses. Try again later.*/i + ).should('exist') + }) + + it('shows an error alert when fetching guestbooks fails', () => { + ;(guestbookRepository.getGuestbooksByCollectionId as Cypress.Agent).rejects( + new Error('unexpected') + ) + + mountComponent() + + cy.findByRole('alert') + .should('exist') + .and( + 'contain.text', + 'Something went wrong getting guestbooks by collection id. Try again later.' + ) + }) +}) diff --git a/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts b/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts index 80f2f93cb..68bac2f29 100644 --- a/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts +++ b/tests/component/sections/guestbooks/createGuestbookRepositoryStub.ts @@ -4,6 +4,9 @@ export const createGuestbookRepositoryStub = (): GuestbookRepository => ({ createGuestbook: cy.stub(), getGuestbook: cy.stub(), getGuestbooksByCollectionId: cy.stub(), + setGuestbookEnabled: cy.stub(), + downloadGuestbookResponsesByDataverseId: cy.stub(), + downloadGuestbookResponsesOfAGuestbook: cy.stub(), assignDatasetGuestbook: cy.stub(), removeDatasetGuestbook: cy.stub() }) From fa0849140fa199a6a45d8afcb314cb77d1e9e3ec Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Tue, 19 May 2026 12:59:19 -0400 Subject: [PATCH 5/5] feat: get usage and responses count and changelog update --- CHANGELOG.md | 7 +++ src/guestbooks/domain/models/Guestbook.ts | 2 + .../repositories/GuestbookRepository.ts | 5 +- .../GuestbookJSDataverseRepository.ts | 7 ++- .../edit-guestbook/EditGuestbook.tsx | 26 ++++---- src/sections/guestbooks/ManageGuestbooks.tsx | 16 ++--- .../useGetGuestbooksByCollectionId.tsx | 9 ++- .../guestbook/GuestbookMockRepository.ts | 9 ++- .../edit-dataset-terms/EditGuestbook.spec.tsx | 29 +++++++++ .../guestbooks/ManageGuestbooks.spec.tsx | 59 +++++++++++++++++-- .../useGetGuestbooksByCollectionId.spec.tsx | 29 ++++++++- 11 files changed, 162 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a05b41c..94a44f136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,15 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel ### Added +- Manage Guestbooks page integration, including: + - a guestbooks table with sorting, enable/disable actions, preview, and per-guestbook response download + - Create Guestbook and Download All Responses actions + - the Create Guestbook page + ### Changed +- Dataset Terms > Guestbook now hides disabled guestbooks from the selectable list. + ### Fixed ### Removed diff --git a/src/guestbooks/domain/models/Guestbook.ts b/src/guestbooks/domain/models/Guestbook.ts index a6d8ad46c..cc9744986 100644 --- a/src/guestbooks/domain/models/Guestbook.ts +++ b/src/guestbooks/domain/models/Guestbook.ts @@ -26,4 +26,6 @@ export interface Guestbook { customQuestions: GuestbookCustomQuestion[] createTime: string dataverseId: number + usageCount?: number + responseCount?: number } diff --git a/src/guestbooks/domain/repositories/GuestbookRepository.ts b/src/guestbooks/domain/repositories/GuestbookRepository.ts index dc01f3736..4b97cbe2c 100644 --- a/src/guestbooks/domain/repositories/GuestbookRepository.ts +++ b/src/guestbooks/domain/repositories/GuestbookRepository.ts @@ -7,7 +7,10 @@ export interface GuestbookRepository { guestbook: CreateGuestbookDTO ) => Promise getGuestbook: (guestbookId: number) => Promise - getGuestbooksByCollectionId: (collectionIdOrAlias: number | string) => Promise + getGuestbooksByCollectionId: ( + collectionIdOrAlias: number | string, + includeStats?: boolean + ) => Promise setGuestbookEnabled: ( collectionIdOrAlias: number | string, guestbookId: number, diff --git a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts index 7dea72251..a4185ddea 100644 --- a/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts +++ b/src/guestbooks/infrastructure/repositories/GuestbookJSDataverseRepository.ts @@ -24,9 +24,12 @@ export class GuestbookJSDataverseRepository implements GuestbookRepository { return getGuestbook.execute(guestbookId).then((guestbook) => guestbook as Guestbook) } - getGuestbooksByCollectionId(collectionIdOrAlias: number | string): Promise { + getGuestbooksByCollectionId( + collectionIdOrAlias: number | string, + includeStats = false + ): Promise { return getGuestbooksByCollectionId - .execute(collectionIdOrAlias) + .execute(collectionIdOrAlias, includeStats) .then((guestbooks) => guestbooks as Guestbook[]) } diff --git a/src/sections/edit-dataset-terms/edit-guestbook/EditGuestbook.tsx b/src/sections/edit-dataset-terms/edit-guestbook/EditGuestbook.tsx index d91e7185b..f48cc4486 100644 --- a/src/sections/edit-dataset-terms/edit-guestbook/EditGuestbook.tsx +++ b/src/sections/edit-dataset-terms/edit-guestbook/EditGuestbook.tsx @@ -1,4 +1,4 @@ -import { startTransition, useCallback, useEffect, useState } from 'react' +import { startTransition, useCallback, useEffect, useMemo, useState } from 'react' import { Alert, Button, Col, Form, Row, Spinner } from '@iqss/dataverse-design-system' import { Trans, useTranslation } from 'react-i18next' import { useNavigate } from 'react-router-dom' @@ -61,6 +61,10 @@ export function EditGuestbook({ guestbookRepository, collectionIdOrAlias }) + const enabledGuestbooks = useMemo( + () => guestbooks.filter((guestbook) => guestbook.enabled), + [guestbooks] + ) const { handleAssignDatasetGuestbook, isLoadingAssignDatasetGuestbook, @@ -87,7 +91,7 @@ export function EditGuestbook({ }) useEffect(() => { - if (guestbooks.length === 0) { + if (enabledGuestbooks.length === 0) { setSelectedGuestbookId(undefined) return } @@ -97,14 +101,14 @@ export function EditGuestbook({ if (currentDatasetGuestbookId === undefined) { setSelectedGuestbookId((currentSelectedGuestbookId) => currentSelectedGuestbookId !== undefined && - guestbooks.some((guestbook) => guestbook.id === currentSelectedGuestbookId) + enabledGuestbooks.some((guestbook) => guestbook.id === currentSelectedGuestbookId) ? currentSelectedGuestbookId : undefined ) return } - const hasCurrentDatasetGuestbook = guestbooks.some( + const hasCurrentDatasetGuestbook = enabledGuestbooks.some( (guestbook) => guestbook.id === currentDatasetGuestbookId ) @@ -116,14 +120,14 @@ export function EditGuestbook({ setSelectedGuestbookId((currentSelectedGuestbookId) => { if ( currentSelectedGuestbookId !== undefined && - guestbooks.some((guestbook) => guestbook.id === currentSelectedGuestbookId) + enabledGuestbooks.some((guestbook) => guestbook.id === currentSelectedGuestbookId) ) { return currentSelectedGuestbookId } return currentDatasetGuestbookId }) - }, [dataset?.guestbookId, guestbooks]) + }, [dataset?.guestbookId, enabledGuestbooks]) useEffect(() => { onFormStateChange?.(selectedGuestbookId !== dataset?.guestbookId) @@ -171,7 +175,7 @@ export function EditGuestbook({ /> {!isLoadingGuestbooksByCollectionId && !errorGetGuestbooksByCollectionId && - guestbooks.length === 0 && ( + enabledGuestbooks.length === 0 && (
{t('editTerms.guestbook.noGuestbooksEnabled', { collectionName })}
@@ -180,7 +184,7 @@ export function EditGuestbook({ {!isLoadingGuestbooksByCollectionId && !errorGetGuestbooksByCollectionId && - guestbooks.length > 0 && + enabledGuestbooks.length > 0 && selectedGuestbookId !== undefined && (