diff --git a/Makefile b/Makefile index 4a6ff5b8..c550cc57 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ ps-image: Containerfile.ps ## Build continaer image for the pathservice $(CMD_PREFIX) docker build -f Containerfile.ps -t ghcr.io/instructlab/ui/pathservice:$(TAG) . $(CMD_PREFIX) docker tag ghcr.io/instructlab/ui/pathservice:$(TAG) ghcr.io/instructlab/ui/pathservice:main -##@ Local Dev - Run the stack (UI and PathService) on your local machine +##@ Local Dev - Local machine based deployment of the UI stack .PHONY: stop-dev-local stop-dev-local: ## Stop the npm and pathservice local instances $(CMD_PREFIX) echo "Stopping ui and pathservice..." @@ -72,6 +72,25 @@ start-dev-local: ## Start the npm and pathservice local instances $(CMD_PREFIX) npm run dev & echo $$! > ui.pid $(CMD_PREFIX) echo "Development environment started." +##@ Podman Dev - Podman desktop based Deployment of the UI stack +.PHONY: stop-dev-podman +stop-dev-podman: ## Stop UI development stack running in podman + $(CMD_PREFIX) echo "Deleting UI development stack running in podman..." + $(CMD_PREFIX) podman-compose -f ./deploy/compose/ui-compose.yml down + $(CMD_PREFIX) echo "Development environment deleted." + +.PHONY: start-dev-podman +start-dev-podman: ## Start UI development stack in podman + $(CMD_PREFIX) echo "Deploying UI development stack using compose..." + $(CMD_PREFIX) if [ ! -f .env ]; then \ + echo "Please create a .env file in the root of the project." ; \ + exit 1 ; \ + fi + + $(CMD_PREFIX) yes | cp -rf .env ./deploy/compose/.env + $(CMD_PREFIX) podman-compose -f ./deploy/compose/ui-compose.yml up -d + $(CMD_PREFIX) echo "Development environment started." + ##@ Kubernetes - Kind cluster based dev environment .PHONY: check-kind check-kind: diff --git a/deploy/compose/ui-compose.yml b/deploy/compose/ui-compose.yml new file mode 100644 index 00000000..29b584a8 --- /dev/null +++ b/deploy/compose/ui-compose.yml @@ -0,0 +1,38 @@ +version: '5.1' + +services: + pathservice: + image: ghcr.io/instructlab/ui/pathservice:main + pull_policy: always + deploy: + replicas: 1 + restart_policy: + condition: always + resources: + limits: + cpus: '0.1' + memory: 200M + reservations: + cpus: '0.1' + memory: 200M + ports: + - "4000:4000" + + ui: + image: ghcr.io/instructlab/ui/ui:main + pull_policy: always + env_file: + - .env + deploy: + replicas: 1 + restart_policy: + condition: always + resources: + limits: + cpus: '0.1' + memory: 200M + reservations: + cpus: '0.1' + memory: 200M + ports: + - "3000:3000" diff --git a/src/app/api/envConfig/route.ts b/src/app/api/envConfig/route.ts index a798ea34..c58b2a65 100644 --- a/src/app/api/envConfig/route.ts +++ b/src/app/api/envConfig/route.ts @@ -14,7 +14,8 @@ export async function GET() { MERLINITE_MODEL_NAME: process.env.IL_MERLINITE_MODEL_NAME || '', UPSTREAM_REPO_OWNER: process.env.NEXT_PUBLIC_TAXONOMY_REPO_OWNER || '', UPSTREAM_REPO_NAME: process.env.NEXT_PUBLIC_TAXONOMY_REPO || '', - DEPLOYMENT_TYPE: process.env.IL_UI_DEPLOYMENT || '' + DEPLOYMENT_TYPE: process.env.IL_UI_DEPLOYMENT || '', + EXPERIMENTAL_FEATURES: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || '' }; return NextResponse.json(envConfig); diff --git a/src/app/api/tree/route.ts b/src/app/api/tree/route.ts index 9a97b45c..a3d14077 100644 --- a/src/app/api/tree/route.ts +++ b/src/app/api/tree/route.ts @@ -3,6 +3,7 @@ import axios from 'axios'; import { NextRequest, NextResponse } from 'next/server'; const DEPLOYMENT = process.env.IL_UI_DEPLOYMENT!; +const EXPERIMENTAL_FEATURES = process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || ''; export async function POST(req: NextRequest) { const body = await req.json(); @@ -10,7 +11,7 @@ export async function POST(req: NextRequest) { try { let apiBaseUrl = 'http://pathservice:4000/tree/'; - if (DEPLOYMENT === 'dev') { + if (DEPLOYMENT === 'dev' && EXPERIMENTAL_FEATURES !== 'true') { apiBaseUrl = 'http://localhost:4000/tree/'; } const response = await axios.get(apiBaseUrl + root_path, { diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 417189cd..285eab8b 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -27,6 +27,7 @@ import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner' import UserMenu from './UserMenu/UserMenu'; import { useSession } from 'next-auth/react'; import { useTheme } from '../context/ThemeContext'; +import { useState } from 'react'; interface IAppLayout { children: React.ReactNode; @@ -41,9 +42,21 @@ type Route = { const AppLayout: React.FunctionComponent = ({ children }) => { const { theme } = useTheme(); const { data: session, status } = useSession(); + const [isExperimentalEnabled, setExperimental] = useState(false); + const router = useRouter(); const pathname = usePathname(); + React.useEffect(() => { + // Fetch the experimental feature flag + const fetchExperimentalFeature = async () => { + const res = await fetch('/api/envConfig'); + const envConfig = await res.json(); + setExperimental(envConfig.EXPERIMENTAL_FEATURES === 'true'); + }; + fetchExperimentalFeature(); + }, []); + React.useEffect(() => { if (status === 'loading') return; // Do nothing while loading if (!session && pathname !== '/login') { @@ -59,7 +72,7 @@ const AppLayout: React.FunctionComponent = ({ children }) => { return null; // Return nothing if not authenticated to avoid flicker } - const isExperimentalEnabled = process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES === 'true'; + //const isExperimentalEnabled = process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES === 'true'; // Only log if experimental features are enabled if (isExperimentalEnabled) { diff --git a/src/components/Dashboard/index.tsx b/src/components/Dashboard/index.tsx index 8b683ade..1ee414d4 100644 --- a/src/components/Dashboard/index.tsx +++ b/src/components/Dashboard/index.tsx @@ -61,6 +61,8 @@ const Index: React.FunctionComponent = () => { } setIsFirstPullDone(true); setIsLoading(false); + } else { + setIsLoading(false); } }, [session?.accessToken]);