-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/mashup-test-button #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tirirote
wants to merge
46
commits into
main
Choose a base branch
from
feature/mashup-test-button
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
0453618
feat: added draft catalog step
alvarobernal2412 c73cd63
feat(dashboard): added empty dashboard form
alvarobernal2412 0493542
Merge branch 'multi-step-form' into enhance-dashboard-module
alvarobernal2412 dd52840
feat(catalog): enhanced controls creation step
alvarobernal2412 0014d7c
feat(panel): added panel creation form
alvarobernal2412 18d34a9
feat(multi-step): added catalog recovery
alvarobernal2412 97b6a59
refactor: rewrite calendar component for react-day-picker v9
ferferga 80ac95c
Merge remote-tracking branch 'origin/fix-reactdarypicker-v9-shadcn' i…
alvarobernal2412 0c910bd
Merge remote-tracking branch 'origin' into enhance-dashboard-module
alvarobernal2412 49bceef
Merge branch 'main' into enhance-dashboard-module
alvarobernal2412 2368a76
feat(catalog): added edit functionality
alvarobernal2412 fa2c653
refactor(dashboard): simplified panel model
alvarobernal2412 49498c3
feat(panel): enhanced SQL query builder and form UI
alvarobernal2412 084da52
feat(panel): improved panel preview functionality
alvarobernal2412 277b038
feat(dashboard): added new panel types and restructure options
alvarobernal2412 8b5cc56
refactor(dashboard): clean up code and improve type handling
alvarobernal2412 e45c46c
feat(dashboard): simplify dashboard configuration UI
alvarobernal2412 5a48271
feat(dashboard): integrated panel creation in multi-step-form
alvarobernal2412 dd18dd3
feat: improve dashboard draft handling
alvarobernal2412 a14a0af
fix: enhance control error handling
alvarobernal2412 e275b27
fix: improve panel handling
alvarobernal2412 f5b9e72
Merge branch 'main' into enhance-dashboard-module
alvarobernal2412 6abbf60
chore(deps): update npm (development)
renovate[bot] 8feb351
feat: added wip mashup testing button
tirirote 72ea5e2
feat: added wip mashup testing button
tirirote 32f15f2
Merge branch 'feature/mashup-test-button' into feature/mashup-test-b…
tirirote 582884c
feat: added full wip testing button
tirirote 0105b78
wip(panels): added panel card
alvarobernal2412 41e1023
feat: added wip changes for the testing button
tirirote 9f671eb
feat: replace modal mashup testing with dedicated page
alvarobernal2412 94916c6
Merge branch 'enhance-dashboard-module' into feature/mashup-test-button
alvarobernal2412 4d898d2
feat: add IndexedDB utility for mashup test persistence
alvarobernal2412 e714940
feat: add custom hook for mashup test management
alvarobernal2412 ba5f2d0
feat: add reusable components for test results display
alvarobernal2412 d6af37c
refactor: update control forms to integrate with test persistence
alvarobernal2412 a65edb4
feat: enhance mashup pages with persistent test results
alvarobernal2412 73d7681
Merge branch 'main' into feature/mashup-test-button
alvarobernal2412 8087471
feat: updated forms input feedback
tirirote f4c5254
fix: fixed input feedback for catalog wizard
tirirote 097291d
chore: minor updates on the UI
tirirote 4fcb18d
fix: unified ui styles and layout
tirirote ada26d7
fix: minor ui bug fixe
tirirote cfacf00
chore: improved ui feedback
tirirote dc9b39f
chore: reverted branch to previous commit
tirirote f95bfdf
Merge branch 'feature/mashup-test-button' of https://github.com/statu…
tirirote 7f2049e
Revert "chore: reverted branch to previous commit"
tirirote File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| import React, { useState, useEffect, useCallback } from 'react'; | ||
| import { Button } from '@/components/ui/button'; | ||
| import { Loader2, ExternalLink } from 'lucide-react'; // Importa ExternalLink | ||
| import { toast } from 'sonner'; | ||
| import { | ||
| Dialog, | ||
| DialogContent, | ||
| DialogHeader, | ||
| DialogTitle, | ||
| DialogDescription, | ||
| } from '@/components/ui/dialog'; | ||
|
|
||
| import { NewControlForm } from '@/forms/control/new/form'; // Tu formulario de creación de control | ||
| import { executeNodeRedMashup, getAllNodeRedFlows, createDraftCatalog } from '@/services/mashups'; // Servicios necesarios | ||
|
|
||
| export function ControlCreationAndTestView({ mashup, isOpen, onClose }) { | ||
| const [draftCatalogId, setDraftCatalogId] = useState(null); | ||
| const [isFormCreating, setIsFormCreating] = useState(true); | ||
| const [loadingInitialSetup, setLoadingInitialSetup] = useState(false); | ||
| const [loadingTestExecution, setLoadingTestExecution] = useState(false); | ||
| const [testResults, setTestResults] = useState(null); | ||
| const [mashupDetails, setMashupDetails] = useState(null); | ||
|
|
||
| // 1. Efecto para inicializar el catálogo borrador y obtener los detalles del mashup cuando la vista se abre | ||
| useEffect(() => { | ||
| if (isOpen && (!draftCatalogId || !mashupDetails)) { // Solo si está abierta y faltan datos | ||
| const initializeEnvironment = async () => { | ||
| setLoadingInitialSetup(true); | ||
| try { | ||
| // Crear catálogo borrador | ||
| if (!draftCatalogId) { | ||
| const newCatalog = await createDraftCatalog(); | ||
| if (!newCatalog || !newCatalog.id) { | ||
| throw new Error('No se pudo crear el catálogo borrador o falta el ID.'); | ||
| } | ||
| setDraftCatalogId(newCatalog.id); | ||
| toast.success(`Configuración de prueba: Catálogo borrador "${newCatalog.name}" listo.`, { duration: 3000 }); | ||
| } | ||
|
|
||
| // Obtener detalles completos del mashup | ||
| if (mashup && mashup.id && !mashupDetails) { | ||
| const allMashupsResponse = await getAllNodeRedFlows(); | ||
| const foundMashup = allMashupsResponse.data.find(m => m.id === mashup.id); | ||
| if (foundMashup) { | ||
| setMashupDetails(foundMashup); | ||
| } else { | ||
| toast.error('No se encontraron detalles del Mashup proporcionado. Asegúrate de que existe.', { duration: 5000 }); | ||
| onClose(); // Cerrar si no se encuentra el mashup | ||
| return; // Salir para evitar más errores | ||
| } | ||
| } | ||
|
|
||
| } catch (error) { | ||
| console.error('Error al configurar el entorno de prueba:', error); | ||
| toast.error(`Error al configurar el entorno de prueba: ${error.message || 'Error desconocido'}`, { duration: 5000 }); | ||
| onClose(); // Cerrar la vista si falla la inicialización crítica | ||
| } finally { | ||
| setLoadingInitialSetup(false); | ||
| } | ||
| }; | ||
| initializeEnvironment(); | ||
| } | ||
| }, [isOpen, draftCatalogId, mashup, mashupDetails, onClose]); | ||
|
|
||
|
|
||
| // Callback que se ejecuta cuando el control es creado exitosamente en el formulario | ||
| const handleControlCreated = useCallback(async (controlId, formMashupId) => { | ||
| console.log('[ControlCreationAndTestView] Mashup details: ', JSON.stringify(mashupDetails, null, 2)); | ||
| console.log('[ControlCreationAndTestView] handleControlCreated llamado. controlId:', controlId, 'formMashupId:', formMashupId); | ||
| setIsFormCreating(false); // Cambiamos a la fase de visualización de resultados | ||
| setTestResults(null); // Limpiamos resultados anteriores | ||
|
|
||
| // Aseguramos que tenemos los detalles completos del mashup antes de ejecutar | ||
| if (!mashupDetails || mashupDetails.id !== formMashupId || !mashupDetails.endpoint) { | ||
| toast.error('No se pudo obtener la URL del Mashup para la ejecución. Inténtalo de nuevo.'); | ||
| console.error('Error: mashupDetails no válido o URL faltante para la ejecución del test.'); | ||
| setLoadingTestExecution(false); // Asegúrate de que el spinner se desactive | ||
| return; | ||
| } | ||
|
|
||
| setLoadingTestExecution(true); | ||
| toast.loading('Ejecutando prueba del mashup de Node-RED...', { id: 'mashup-test', duration: 0 }); // Toast persistente | ||
|
|
||
| try { | ||
| // Prepara el payload para el mashup de Node-RED. | ||
| // Puedes ajustar esto según lo que tu Node-RED espere. | ||
| const payloadForMashup = { | ||
| payload: `Test execution for Control ID: ${controlId} - ${new Date().toLocaleString()}`, | ||
| controlId: controlId, | ||
| mashupId: formMashupId, | ||
| catalogId: draftCatalogId, | ||
| // Puedes añadir aquí otros parámetros relevantes para tu test | ||
| }; | ||
|
|
||
| console.log('[ControlCreationAndTestView] Ejecutando mashup con URL:', mashupDetails.endpoint, 'y payload:', payloadForMashup); | ||
| const mashupResult = await executeNodeRedMashup(mashupDetails.endpoint, payloadForMashup); | ||
|
|
||
| setTestResults(mashupResult); | ||
| toast.success('¡Mashup ejecutado exitosamente!', { | ||
| id: 'mashup-test', | ||
| description: ( | ||
| <div className="mt-2 text-xs text-wrap break-all max-h-40 overflow-y-auto"> | ||
| <h4 className="font-semibold mb-1">Resultados:</h4> | ||
| <pre className="whitespace-pre-wrap">{JSON.stringify(mashupResult, null, 2)}</pre> | ||
| </div> | ||
| ), | ||
| duration: 8000 // Deja el toast más tiempo para leer los resultados | ||
| }); | ||
|
|
||
| } catch (error) { | ||
| console.error('Error durante la ejecución de la prueba del mashup de Node-RED:', error); | ||
| const errorMessage = error.response?.data?.message || error.message || 'Error desconocido'; | ||
| toast.error(`La prueba del mashup falló: ${errorMessage}`, { id: 'mashup-test', duration: 8000 }); | ||
| } finally { | ||
| setLoadingTestExecution(false); | ||
| console.log('[ControlCreationAndTestView] Ejecución del mashup finalizada. loadingTestExecution es false.'); | ||
| } | ||
| }, [mashupDetails, draftCatalogId]); // Dependencias del useCallback | ||
|
|
||
| // Callback para reiniciar la vista y permitir la creación de un nuevo control | ||
| const handleReset = useCallback(() => { | ||
| setDraftCatalogId(null); // Esto forzará la creación de un nuevo catálogo borrador | ||
| setIsFormCreating(true); | ||
| setTestResults(null); | ||
| setLoadingInitialSetup(false); // Asegúrate de que se reinicie para re-ejecutar el efecto de inicialización | ||
| setMashupDetails(null); // Reinicia también los detalles del mashup | ||
| toast.info('Vista de prueba reiniciada. Lista para la creación de un nuevo control.'); | ||
| }, []); | ||
|
|
||
| // Renderizado del Diálogo Principal | ||
| return ( | ||
| <Dialog open={isOpen} onOpenChange={onClose}> | ||
| <DialogContent | ||
| className="max-w-[800px] w-full p-6 max-h-[90vh] overflow-y-auto" | ||
| aria-describedby="control-creation-dialog-description" | ||
| > | ||
| <DialogHeader> | ||
| <DialogTitle className="text-xl font-bold"> | ||
| {isFormCreating ? `Crear Control para Mashup: ${mashup?.name || 'Cargando...'}` : `Testeo de Mashup: ${mashup?.name || 'Cargando...'}`} | ||
| </DialogTitle> | ||
| <DialogDescription id="control-creation-dialog-description"> | ||
| {isFormCreating ? 'Crea un nuevo control asociado a un catálogo borrador para iniciar el test.' : 'Control creado. Ejecutando o mostrando resultados de la prueba del mashup.'} | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
|
|
||
| {loadingInitialSetup ? ( | ||
| <div className="flex justify-center items-center h-40"> | ||
| <Loader2 className="mr-2 h-6 w-6 animate-spin" /> | ||
| Preparando entorno de prueba y cargando detalles del Mashup... | ||
| </div> | ||
| ) : ( | ||
| <> | ||
| {isFormCreating ? ( | ||
| // Solo renderizamos el formulario si el draftCatalogId y mashupDetails están disponibles | ||
| draftCatalogId && mashupDetails ? ( | ||
| <NewControlForm | ||
| catalogId={draftCatalogId} | ||
| onClose={onClose} | ||
| onSuccess={handleControlCreated} | ||
| mashupIdPreselected={mashupDetails.id} // Pasa el ID del mashup completo | ||
| /> | ||
| ) : ( | ||
| <div className="flex justify-center items-center h-40 text-red-600"> | ||
| <p>No se pudo cargar el entorno de prueba. Intenta reiniciar.</p> | ||
| </div> | ||
| ) | ||
| ) : ( | ||
| // Sección para mostrar los resultados de la prueba | ||
| <div className="space-y-4 pt-4"> | ||
| <h3 className="text-lg font-medium border-b pb-2 mb-2">Resultados del Test de Mashup</h3> | ||
| {loadingTestExecution ? ( | ||
| <div className="flex justify-center items-center py-4"> | ||
| <Loader2 className="mr-2 h-5 w-5 animate-spin" /> Ejecutando prueba... | ||
| </div> | ||
| ) : testResults ? ( | ||
| <div> | ||
| <h4 className="text-md font-medium mb-2">Respuesta del Mashup:</h4> | ||
| <pre className="bg-gray-100 p-3 rounded-md text-sm whitespace-pre-wrap max-h-[300px] overflow-auto"> | ||
| {typeof testResults === 'object' ? JSON.stringify(testResults, null, 2) : String(testResults)} | ||
| </pre> | ||
| {/* Botón para ver el Mashup en Node-RED */} | ||
| {mashupDetails?.id && ( | ||
| <div className="mt-4 flex justify-end"> | ||
| <Button | ||
| variant="outline" | ||
| onClick={() => window.open(`/red#flow/${mashupDetails.id}`, '_blank')} | ||
| > | ||
| <ExternalLink className="mr-2 h-4 w-4" /> Ver Mashup en Node-RED | ||
| </Button> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ) : ( | ||
| <p>La prueba del mashup ha finalizado o no se obtuvieron resultados.</p> | ||
| )} | ||
|
|
||
| <div className="flex justify-end space-x-2 mt-4"> | ||
| <Button variant="outline" onClick={handleReset} disabled={loadingTestExecution}> | ||
| Crear Nuevo Control / Reiniciar Prueba | ||
| </Button> | ||
| <Button variant="outline" onClick={onClose} disabled={loadingTestExecution}> | ||
| Cerrar Vista de Prueba | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| )} | ||
| </> | ||
| )} | ||
| </DialogContent> | ||
| </Dialog> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // src/components/ui/combobox.jsx | ||
| import * as React from "react" | ||
| import { Check, ChevronsUpDown } from "lucide-react" | ||
|
|
||
| import { cn } from "@/lib/utils" | ||
| import { Button } from "@/components/ui/button" | ||
| import { | ||
| Command, | ||
| CommandEmpty, | ||
| CommandGroup, | ||
| CommandInput, | ||
| CommandItem, | ||
| CommandList, | ||
| } from "@/components/ui/command" | ||
| import { | ||
| Popover, | ||
| PopoverContent, | ||
| PopoverTrigger, | ||
| } from "@/components/ui/popover" | ||
|
|
||
| /** | ||
| * A reusable ComboBox component for selecting from a list of options with search functionality. | ||
| * | ||
| * @param {object} props - The component props. | ||
| * @param {Array<object>} props.options - An array of objects, where each object has `value` and `label` properties. | ||
| * @param {string} props.value - The current selected value. | ||
| * @param {function} props.onValueChange - Callback function when the value changes. | ||
| * @param {string} [props.placeholder="Select option..."] - Placeholder text for the input. | ||
| * @param {string} [props.className=""] - Optional CSS class names for the component. | ||
| * @param {boolean} [props.disabled=false] - If true, the combobox will be disabled. | ||
| */ | ||
| export function ComboBox({ options, value, onValueChange, placeholder = "Select option...", className = "", disabled = false }) { | ||
| const [open, setOpen] = React.useState(false) | ||
|
|
||
| return ( | ||
| <Popover open={open} onOpenChange={setOpen}> | ||
| <PopoverTrigger asChild> | ||
| <Button | ||
| variant="outline" | ||
| role="combobox" | ||
| aria-expanded={open} | ||
| className={cn("w-full justify-between", className)} | ||
| disabled={disabled} | ||
| > | ||
| {value | ||
| ? options.find((option) => option.value === value)?.label | ||
| : placeholder} | ||
| <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" /> | ||
| </Button> | ||
| </PopoverTrigger> | ||
| <PopoverContent className="w-[--radix-popover-trigger-width] p-0"> | ||
| <Command> | ||
| <CommandInput placeholder={placeholder} /> | ||
| <CommandList> | ||
| <CommandEmpty>No option found.</CommandEmpty> | ||
| <CommandGroup> | ||
| {options.map((option) => ( | ||
| <CommandItem | ||
| key={option.value} | ||
| value={option.label} // Use label for search, value for actual selection | ||
| onSelect={(currentLabel) => { | ||
| // Find the option by its label | ||
| const selectedOption = options.find( | ||
| (opt) => opt.label.toLowerCase() === currentLabel.toLowerCase() | ||
| ); | ||
| onValueChange(selectedOption ? selectedOption.value : ""); | ||
| setOpen(false); | ||
| }} | ||
| > | ||
| <Check | ||
| className={cn( | ||
| "mr-2 h-4 w-4", | ||
| value === option.value ? "opacity-100" : "opacity-0" | ||
| )} | ||
| /> | ||
| {option.label} | ||
| </CommandItem> | ||
| ))} | ||
| </CommandGroup> | ||
| </CommandList> | ||
| </Command> | ||
| </PopoverContent> | ||
| </Popover> | ||
| ) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is a mix between a component and a page, a component must be reusable and a page must include only its features. E.g. The Mashup Page must only include the fetch, see (redirect to Details page), test mashup (redirect to Test Mashup Page) and delete features.