Skip to content

Commit

Permalink
Adding matching component (incl detailed docu) (#71)
Browse files Browse the repository at this point in the history
* full-detailed readme

* adding matching compoenent

* readme update

* adding matching to core

* adding deployment for matching phase

* mini fixes

* adjusting to the new deployment and env settings
  • Loading branch information
niclasheun authored Jan 18, 2025
1 parent 5dd9102 commit 6092fd6
Show file tree
Hide file tree
Showing 33 changed files with 662 additions and 24 deletions.
21 changes: 18 additions & 3 deletions .github/workflows/build-and-push-clients.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ on:
interview_image_tag:
description: "The tag of the interview component image that was built"
value: ${{ jobs.build-and-push-clients-interview.outputs.image_tag }}
matching_image_tag:
description: "The tag of the matching component image that was built"
value: ${{ jobs.build-and-push-clients-matching.outputs.image_tag }}

jobs:
build-and-push-clients-base:
Expand All @@ -34,7 +37,7 @@ jobs:
docker-context: ./clients/core
build-args: |
"IMAGE_TAG=${{ needs.build-and-push-clients-base.outputs.image_tag }}"
"CORE_HOST"=${{ vars.CORE_HOST }}
"CORE_HOST=${{ vars.CORE_HOST }}"
"KEYCLOAK_HOST=${{ vars.KEYCLOAK_HOST }}"
"KEYCLOAK_REALM_NAME=${{ vars.KEYCLOAK_REALM_NAME }}"
secrets: inherit
Expand All @@ -48,7 +51,7 @@ jobs:
docker-context: ./clients/template_component
build-args: |
"IMAGE_TAG=${{ needs.build-and-push-clients-base.outputs.image_tag }}"
"CORE_HOST"=${{ vars.CORE_HOST }}
"CORE_HOST=${{ vars.CORE_HOST }}"
secrets: inherit

build-and-push-clients-interview:
Expand All @@ -60,5 +63,17 @@ jobs:
docker-context: ./clients/interview_component
build-args: |
"IMAGE_TAG=${{ needs.build-and-push-clients-base.outputs.image_tag }}"
"CORE_HOST"=${{ vars.CORE_HOST }}
"CORE_HOST=${{ vars.CORE_HOST }}"
secrets: inherit

build-and-push-clients-matching:
needs: build-and-push-clients-base
uses: ./.github/workflows/build-and-push-docker-image.yml
with:
image-name: ghcr.io/ls1intum/prompt2/prompt-clients-matching-component
docker-file: clients/matching_component/Dockerfile # Defaults to Dockerfile
docker-context: ./clients/matching_component
build-args: |
"IMAGE_TAG=${{ needs.build-and-push-clients-base.outputs.image_tag }}"
"CORE_HOST=${{ vars.CORE_HOST }}"
secrets: inherit
4 changes: 4 additions & 0 deletions .github/workflows/deploy-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ on:
interview_image_tag:
required: true
type: string
matching_image_tag:
required: true
type: string
server_image_tag:
required: true
type: string
Expand Down Expand Up @@ -133,6 +136,7 @@ jobs:
echo "CORE_IMAGE_TAG=${{ inputs.core_image_tag }}" >> .env.prod
echo "TEMPLATE_IMAGE_TAG=${{ inputs.template_image_tag }}" >> .env.prod
echo "INTERVIEW_IMAGE_TAG=${{ inputs.interview_image_tag }}" >> .env.prod
echo "MATCHING_IMAGE_TAG=${{ inputs.matching_image_tag }}" >> .env.prod
echo "SENDER_EMAIL"=${{ vars.SENDER_EMAIL_ADDRESS }} >> .env.prod
echo "SENDER_NAME"=${{ vars.SENDER_EMAIL_NAME }} >> .env.prod
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ jobs:
core_image_tag: ${{ needs.build-and-push-clients.outputs.core_image_tag }}
template_image_tag: ${{ needs.build-and-push-clients.outputs.template_image_tag }}
interview_image_tag: ${{ needs.build-and-push-clients.outputs.interview_image_tag }}
matching_image_tag: ${{ needs.build-and-push-clients.outputs.matching_image_tag }}
server_image_tag: ${{ needs.build-and-push-server.outputs.server_image_tag }}

1 change: 1 addition & 0 deletions .github/workflows/prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ jobs:
core_image_tag: ${{ needs.build-and-push-clients.outputs.core_image_tag }}
template_image_tag: ${{ needs.build-and-push-clients.outputs.template_image_tag }}
interview_image_tag: ${{ needs.build-and-push-clients.outputs.interview_image_tag }}
matching_image_tag: ${{ needs.build-and-push-clients.outputs.matching_image_tag }}
server_image_tag: ${{ needs.build-and-push-server.outputs.server_image_tag }}
30 changes: 30 additions & 0 deletions clients/core/src/PhaseMapping/ExternalRoutes/MatchingRoutes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Alert, AlertTitle, AlertDescription } from '@/components/ui/alert'
import { AlertCircle } from 'lucide-react'
import React from 'react'
import { ExtendedRouteObject } from '@/interfaces/extended_route_object'
import { ExternalRoutes } from './ExternalRoutes'

export const MatchingRoutes = React.lazy(() =>
import('matching_component/routes')
.then((module): { default: React.FC } => ({
default: () => {
const routes: ExtendedRouteObject[] = module.default || []
return <ExternalRoutes routes={routes} />
},
}))
.catch((): { default: React.FC } => ({
default: () => {
console.warn('Failed to load matching routes')
return (
<Alert variant='destructive'>
<AlertCircle className='h-4 w-4' />
<AlertTitle>Error</AlertTitle>
<AlertDescription>
We&apos;re sorry, but we couldn&apos;t load the matching routes. Please try refreshing
or contact support if the problem persists.
</AlertDescription>
</Alert>
)
},
})),
)
31 changes: 31 additions & 0 deletions clients/core/src/PhaseMapping/ExternalSidebars/MatchingSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'
import { DisabledSidebarMenuItem } from '../../Sidebar/InsideSidebar/components/DisabledSidebarMenuItem'
import { SidebarMenuItemProps } from '@/interfaces/sidebar'
import { ExternalSidebarComponent } from './ExternalSidebar'

interface MatchingSidebarProps {
rootPath: string
title?: string
}

export const MatchingSidebar = React.lazy(() =>
import('matching_component/sidebar')
.then((module): { default: React.FC<MatchingSidebarProps> } => ({
default: ({ title, rootPath }) => {
const sidebarElement: SidebarMenuItemProps = module.default || {}
return (
<ExternalSidebarComponent
title={title}
rootPath={rootPath}
sidebarElement={sidebarElement}
/>
)
},
}))
.catch((): { default: React.FC } => ({
default: () => {
console.warn('Failed to load matching sidebar')
return <DisabledSidebarMenuItem title={'Matching Not Available'} />
},
})),
)
2 changes: 2 additions & 0 deletions clients/core/src/PhaseMapping/PhaseRouterMapping.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { TemplateRoutes } from './ExternalRoutes/TemplateRoutes'
import { ApplicationRoutes } from './ExternalRoutes/ApplicationRoutes'
import { InterviewRoutes } from './ExternalRoutes/InterviewRoutes'
import { Suspense } from 'react'
import { MatchingRoutes } from './ExternalRoutes/MatchingRoutes'

const PhaseRouter: { [key: string]: React.FC } = {
template_component: TemplateRoutes,
Application: ApplicationRoutes,
Interview: InterviewRoutes,
Matching: MatchingRoutes,
}

export const PhaseRouterMapping = (): JSX.Element => {
Expand Down
2 changes: 2 additions & 0 deletions clients/core/src/PhaseMapping/PhaseSidebarMapping.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { TemplateSidebar } from './ExternalSidebars/TemplateSidebar'
import { InterviewSidebar } from './ExternalSidebars/InterviewSidebar'
import { ApplicationSidebar } from './ExternalSidebars/ApplicationSidebar'
import { MatchingSidebar } from './ExternalSidebars/MatchingSidebar'

export const PhaseSidebarMapping: { [key: string]: React.FC<{ rootPath: string; title: string }> } =
{
template_component: TemplateSidebar,
Application: ApplicationSidebar,
Interview: InterviewSidebar,
Matching: MatchingSidebar,
}
2 changes: 2 additions & 0 deletions clients/core/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const config: (env: Record<string, string>) => container.Configuration = (env) =
// Adjust this to match your deployment URL
const templateURL = IS_DEV ? `http://localhost:3001` : `/template`
const interviewURL = IS_DEV ? `http://localhost:3002` : `/interview`
const matchingURL = IS_DEV ? `http://localhost:3003` : `/matching`

return {
target: 'web',
Expand Down Expand Up @@ -87,6 +88,7 @@ const config: (env: Record<string, string>) => container.Configuration = (env) =
remotes: {
template_component: `template_component@${templateURL}/remoteEntry.js`,
interview_component: `interview_component@${interviewURL}/remoteEntry.js`,
matching_component: `matching_component@${matchingURL}/remoteEntry.js`,
},
shared: {
react: { singleton: true, requiredVersion: deps.react },
Expand Down
2 changes: 1 addition & 1 deletion clients/interview_component/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const config: (env: Record<string, string>) => container.Configuration = (env) => {
const getVariable = (name: string) => env[name] ?? process.env[name]
const getVariable = (name: string) => env[name]

const IS_DEV = getVariable('NODE_ENV') !== 'production'
const deps = packageJson.dependencies
Expand Down
1 change: 1 addition & 0 deletions clients/lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"packages": [
"core",
"interview_component",
"matching_component",
"template_component",
"shared_library"
]
Expand Down
1 change: 1 addition & 0 deletions clients/matching_component/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
16 changes: 16 additions & 0 deletions clients/matching_component/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ARG IMAGE_TAG
FROM ghcr.io/ls1intum/prompt2/prompt-clients-base:${IMAGE_TAG} AS core-base

Check warning on line 2 in clients/matching_component/Dockerfile

View workflow job for this annotation

GitHub Actions / build-and-push-clients / build-and-push-clients-matching / Build Docker Image for ghcr.io/ls1intum/prompt2/prompt-clients-matching-component

Default value for global ARG results in an empty or invalid base image name

InvalidDefaultArgInFrom: Default value for ARG ghcr.io/ls1intum/prompt2/prompt-clients-base:${IMAGE_TAG} results in empty or invalid base image name More info: https://docs.docker.com/go/dockerfile/rule/invalid-default-arg-in-from/

WORKDIR /app/matching_component
COPY . ./
RUN yarn install

RUN yarn build

# Build the final image
FROM nginx:stable-alpine

COPY --from=core-base /app/matching_component/build /usr/share/nginx/html
COPY --from=core-base /app/nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
10 changes: 10 additions & 0 deletions clients/matching_component/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import rootConfig from '../eslint.config.mjs'

export default [
...rootConfig,
{
// Optionally add any subfolder-specific rules or settings
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
]
32 changes: 32 additions & 0 deletions clients/matching_component/management/OverviewPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Badge } from '@/components/ui/badge'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Construction } from 'lucide-react'
import { useLocation } from 'react-router-dom'

export const OverviewPage = (): JSX.Element => {
const path = useLocation().pathname

return (
<Card className='w-full max-w-2xl mx-auto'>
<CardHeader>
<div className='flex items-center justify-between'>
<div className='flex items-center space-x-2'>
<Construction className='h-6 w-6 text-yellow-500' />
<CardTitle className='text-2xl'>Matching Component</CardTitle>
</div>
<Badge variant='secondary' className='bg-yellow-200 text-yellow-800'>
In Development
</Badge>
</div>
<CardDescription>This component is currently under development</CardDescription>
</CardHeader>
<CardContent>
<div className='p-4 border-2 border-dashed border-gray-300 rounded-lg'>
You are currently at {path}
</div>
</CardContent>
</Card>
)
}

export default OverviewPage
18 changes: 18 additions & 0 deletions clients/matching_component/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "matching_component",
"version": "1.0.0",
"main": "src/index.ts",
"license": "MIT",
"scripts": {
"dev": "webpack serve --open --mode development",
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
"build": "webpack --mode=production --env NODE_ENV=production",
"check-performance": "webpack --mode=production --env NODE_ENV=production --env BUNDLE_SIZE=true"
},
"devDependencies": {
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"packageManager": "[email protected]"
}
6 changes: 6 additions & 0 deletions clients/matching_component/public/prompt_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions clients/matching_component/public/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/prompt_logo.svg" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TODO: This is a template - please change here</title>
</head>
<body>
<div id="interview-root"></div>
</body>
<html></html>
</html>
Loading

0 comments on commit 6092fd6

Please sign in to comment.