import React , { useState } from "react" ; import produce from "immer" ; import { ServiceIngress } from "@garden-io/core/build/src/types/service" ; import { DependencyGraphNodeType } from "@garden-io/core/build/src/config-graph" ; import { PickFromUnion } from "@garden-io/core/build/src/util/util" ; interface UiState { isMenuOpen : boolean ; overview : { selectedIngress : ServiceIngress | null ; selectedEntity : SelectedEntity | null ; filters : { [ key in OverviewSupportedFilterKeys ] : boolean ; } ; } ; stackGraph : { filters : { [ key in StackGraphSupportedFilterKeys ] : boolean ; } ; } ; selectedGraphNode : string | null ; modal : { visible : boolean ; content : React . ReactNode ; } ; infoBox : { visible : boolean ; content : React . ReactNode ; } ; } export type SelectGraphNode = ( node : string ) => void ; export type SelectEntity = ( selectedEntity : SelectedEntity | null ) => void ; export type SelectIngress = ( ingress : ServiceIngress | null ) => void ; export type OverviewSupportedFilterKeys = "modules" | "modulesInfo" | "services" | "servicesInfo" | "tasks" | "tasksInfo" | "tests" | "testsInfo" ; export type StackGraphSupportedFilterKeys = PickFromUnion < DependencyGraphNodeType , "test" | "deploy" | "build" | "run" > ; export type EntityResultSupportedTypes = StackGraphSupportedFilterKeys | "task" ; export type SelectedEntity = { type : EntityResultSupportedTypes ; name : string ; module : string ; } ; interface UiActions { overviewToggleItemsView : ( filterKey : OverviewSupportedFilterKeys ) => void ; stackGraphToggleItemsView : ( filterKey : StackGraphSupportedFilterKeys ) => void ; selectGraphNode : SelectGraphNode ; selectEntity : SelectEntity ; selectIngress : SelectIngress ; clearGraphNodeSelection : ( ) => void ; showModal : ( content : React . ReactNode ) => void ; hideModal : ( ) => void ; showInfoBox : ( content : React . ReactNode ) => void ; hideInfoBox : ( ) => void ; } const INITIAL_UI_STATE = { overview : { selectedIngress : null , selectedEntity : null , filters : { modules : true , modulesInfo : true , services : true , servicesInfo : true , tasks : true , tasksInfo : true , tests : true , testsInfo : true , } , } , stackGraph : { filters : { build : true , run : true , deploy : true , test : true , } , } , modal : { visible : false , content : null , } , infoBox : { visible : false , content : null , } , isMenuOpen : true , selectedGraphNode : null , } ; interface UiStateAndActions { state : UiState ; actions : UiActions ; } const useUiStateProvider = ( ) => { const [ uiState , setState ] = useState < UiState > ( INITIAL_UI_STATE ) ; const overviewToggleItemsView = ( filterKey ) => { setState ( produce ( uiState , ( draft ) => { draft . overview . filters [ filterKey ] = ! uiState . overview . filters [ filterKey ] ; } ) ) ; } ; const stackGraphToggleItemsView = ( filterKey ) => { setState ( produce ( uiState , ( draft ) => { draft . stackGraph . filters [ filterKey ] = ! uiState . stackGraph . filters [ filterKey ] ; } ) ) ; } ; const selectGraphNode = ( node ) => { setState ( produce ( uiState , ( draft ) => { draft . selectedGraphNode = node ; } ) ) ; } ; const selectIngress = ( ingress ) => { setState ( produce ( uiState , ( draft ) => { draft . overview . selectedIngress = ingress ; } ) ) ; } ; const selectEntity = ( selectedEntity ) => { setState ( produce ( uiState , ( draft ) => { draft . overview . selectedIngress = null ; draft . overview . selectedEntity = selectedEntity ; } ) ) ; } ; const clearGraphNodeSelection = ( ) => { setState ( produce ( uiState , ( draft ) => { draft . selectedGraphNode = null ; } ) ) ; } ; const showModal = ( content ) => { setState ( produce ( uiState , ( draft ) => { draft . modal = { content , visible : true , } ; } ) ) ; } ; const hideModal = ( ) => { setState ( produce ( uiState , ( draft ) => { draft . modal = { content : null , visible : false , } ; } ) ) ; } ; const showInfoBox = ( content ) => { setState ( produce ( uiState , ( draft ) => { draft . infoBox = { content , visible : true , } ; } ) ) ; } ; const hideInfoBox = ( ) => { setState ( produce ( uiState , ( draft ) => { draft . infoBox = { content : null , visible : false , } ; } ) ) ; } ; return { state : uiState , actions : { overviewToggleItemsView , stackGraphToggleItemsView , selectGraphNode , clearGraphNodeSelection , selectIngress , selectEntity , showModal , hideModal , showInfoBox , hideInfoBox , } , } ; } ; export const UiContext = React . createContext < UiStateAndActions > ( { } as UiStateAndActions ) ; export const UiStateProvider = ( { children } ) => { const storeAndActions = useUiStateProvider ( ) ; return < UiContext . Provider value = { storeAndActions } > { children } < /UiContext.Provider>; } ;