1+ import { Codesnippet } from "@/components/CodeSnippet" ;
2+ import { CollapsibleCard } from "@/components/CollapsibleCard" ;
13import { SheetHeader } from "@/components/sheet/SheetHeader" ;
24import { flavorQueries } from "@/data/flavors" ;
35import { stackQueries } from "@/data/stacks" ;
@@ -15,23 +17,31 @@ import {
1517 SheetTrigger ,
1618 Skeleton
1719} from "@zenml-io/react-component-library" ;
18- import { PropsWithChildren } from "react" ;
20+ import { PropsWithChildren , useEffect } from "react" ;
1921import { CopyButton } from "../../CopyButton" ;
2022import { ComponentBadge } from "../../stack-components/ComponentBadge" ;
2123import { ComponentFallbackDialog } from "../../stack-components/ComponentFallbackDialog" ;
24+ import { IntegrationsContextProvider , useIntegrationsContext } from "./IntegrationsContext" ;
2225
2326type Props = {
2427 stackId : string ;
2528} ;
2629
27- export function StackSheet ( { children, stackId } : PropsWithChildren < Props > ) {
30+ export function StackSheet ( {
31+ children,
32+ stackId,
33+ stackName
34+ } : PropsWithChildren < Props & { stackName : string } > ) {
2835 return (
2936 < Sheet >
3037 < SheetTrigger > { children } </ SheetTrigger >
3138 < SheetContent className = "w-[1000px] overflow-y-auto" >
32- < SheetHeader />
33- < StackHeadline stackId = { stackId } />
34- < ComponentList stackId = { stackId } />
39+ < IntegrationsContextProvider >
40+ < SheetHeader />
41+ < StackHeadline stackId = { stackId } />
42+ < StackSetCommand name = { stackName } />
43+ < ComponentList stackId = { stackId } />
44+ </ IntegrationsContextProvider >
3545 </ SheetContent >
3646 </ Sheet >
3747 ) ;
@@ -130,8 +140,22 @@ type FlavorIconProps = {
130140} ;
131141
132142function FlavorIcon ( { flavor, type } : FlavorIconProps ) {
143+ const { setIntegrations } = useIntegrationsContext ( ) ;
133144 const flavorQuery = useQuery ( { ...flavorQueries . flavorList ( { name : flavor , type } ) } ) ;
134145
146+ useEffect ( ( ) => {
147+ if (
148+ flavorQuery . data ?. items ?. length &&
149+ flavorQuery . data . items [ 0 ] . body ?. integration &&
150+ flavorQuery . data . items [ 0 ] . body . integration !== "built-in"
151+ ) {
152+ setIntegrations ( ( prev ) => {
153+ const newIntegration = flavorQuery . data . items [ 0 ] . body ?. integration || "" ;
154+ return Array . from ( new Set ( [ ...prev , newIntegration ] ) ) . filter ( Boolean ) ;
155+ } ) ;
156+ }
157+ } , [ setIntegrations , flavorQuery . data ] ) ;
158+
135159 if ( flavorQuery . isError ) return null ;
136160 if ( flavorQuery . isPending ) return < Skeleton className = "h-6 w-6" /> ;
137161
@@ -144,3 +168,61 @@ function FlavorIcon({ flavor, type }: FlavorIconProps) {
144168 />
145169 ) ;
146170}
171+
172+ type StackSetCommandProps = {
173+ name : string ;
174+ } ;
175+ function StackSetCommand ( { name } : StackSetCommandProps ) {
176+ const { integrations } = useIntegrationsContext ( ) ;
177+
178+ return (
179+ < section className = "px-5 pt-5" >
180+ < CollapsibleCard title = { < span className = "text-text-lg" > Set this stack</ span > } >
181+ < ul className = "space-y-5" >
182+ < li className = "space-y-2" >
183+ < div className = "flex items-center gap-2" >
184+ < Number > 1</ Number >
185+ < p className = "font-semibold" > Set your stack</ p >
186+ </ div >
187+ < div className = "space-y-1" >
188+ < p className = "text-text-sm text-theme-text-secondary" >
189+ Set the stack as active on your client
190+ </ p >
191+ < Codesnippet
192+ codeClasses = "whitespace-pre-wrap"
193+ wrap
194+ code = { `zenml stack set ${ name } ` }
195+ />
196+ </ div >
197+ </ li >
198+ { integrations . length >= 1 && (
199+ < li className = "space-y-2" >
200+ < div className = "flex items-center gap-2" >
201+ < Number > 2</ Number >
202+ < p className = "font-semibold" > Install the integrations</ p >
203+ </ div >
204+ < div className = "space-y-1" >
205+ < p className = "text-text-sm text-theme-text-secondary" >
206+ Install the required integrations to run pipelines in your stack
207+ </ p >
208+ < Codesnippet
209+ codeClasses = "whitespace-pre-wrap"
210+ wrap
211+ code = { `zenml integration install ${ integrations . join ( " " ) } ` }
212+ />
213+ </ div >
214+ </ li >
215+ ) }
216+ </ ul >
217+ </ CollapsibleCard >
218+ </ section >
219+ ) ;
220+ }
221+
222+ function Number ( { children } : PropsWithChildren ) {
223+ return (
224+ < div className = "flex h-7 w-7 items-center justify-center rounded-sm bg-primary-100 text-text-lg font-semibold text-theme-text-brand" >
225+ { children }
226+ </ div >
227+ ) ;
228+ }
0 commit comments