Skip to content
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

Feature/ci 86bz9nnbf channels #662

Merged
merged 19 commits into from
Aug 30, 2024

Conversation

marvinIsSacul
Copy link
Collaborator

@marvinIsSacul marvinIsSacul commented Aug 23, 2024

Summary by CodeRabbit

  • New Features

    • Introduced multiple new React components for managing dialogs, alerts, and loading indicators to enhance user interaction.
    • Added context providers for alerts, backdrops, confirmations, and dialogs to streamline state management across the application.
    • Implemented a multi-step form for adding channels, including validation and dynamic settings.
  • Documentation

    • Added TypeScript declarations for various image formats and modules to enhance type safety.
  • Bug Fixes

    • Improved error handling and validation across various components to enhance user experience.
  • Chores

    • Established ESLint, Prettier, and Babel configurations for code quality and consistency.
    • Added a comprehensive .gitignore to exclude unnecessary files from version control.
    • Created a Webpack configuration tailored for a Single Page Application using React and TypeScript.

@marvinIsSacul marvinIsSacul self-assigned this Aug 23, 2024
Copy link

coderabbitai bot commented Aug 23, 2024

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes introduce a new channels-app package with a comprehensive setup for a React application using TypeScript. Key components include configuration files for ESLint, Babel, Jest, and Webpack, as well as various React components for managing channels, dialogs, and backdrops. The addition of context providers enhances state management for alerts and confirmations. The project is structured to facilitate a microfrontend architecture with proper routing and API integration for channel management.

Changes

File(s) Change Summary
packages/channels-app/.eslintrc New ESLint configuration file with rules for TypeScript and React, integrating Prettier.
packages/channels-app/.gitignore New .gitignore file to exclude unnecessary files from version control.
packages/channels-app/.prettierignore New .prettierignore file specifying files to be ignored by Prettier.
packages/channels-app/babel.config.json New Babel configuration for JavaScript, React, and TypeScript.
packages/channels-app/jest.config.js New Jest configuration for testing with React components.
packages/channels-app/package.json New package.json file defining dependencies and scripts for the project.
packages/channels-app/src/components/... Multiple new React components for dialogs, backdrops, loaders, and error handling.
packages/channels-app/src/contexts/... New context providers for managing alerts, backdrops, confirmations, and dialogs.
packages/channels-app/src/services/api.ts New API functions for managing channels, including fetching and modifying channel data.
packages/channels-app/src/types/index.ts New TypeScript type definitions for channels and related entities.
packages/channels-app/tsconfig.json New TypeScript configuration file for the project.
packages/channels-app/webpack.config.js New Webpack configuration for building the application.
packages/openhim-core-api/src/jembi-openhim-core-api.ts New function for creating channels via the API.
packages/root-config/src/index.ejs Updated to include a new entry for the channels-app in the application configuration.
packaging/import-maps-server/importmap.json Updated to add mapping for @jembi/channels-app.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant AlertProvider
    participant ConfirmationProvider
    participant API

    User->>App: Trigger action (e.g., add channel)
    App->>ConfirmationProvider: Show confirmation dialog
    ConfirmationProvider-->>User: Display dialog
    User->>ConfirmationProvider: Click Yes
    ConfirmationProvider->>API: Call createChannel()
    API-->>ConfirmationProvider: Response (success or error)
    ConfirmationProvider-->>App: Update state based on response
    App->>AlertProvider: Show success or error alert
Loading

Poem

🐰 In the garden of code, new features bloom,
Channels and dialogs, dispelling the gloom.
With hops of delight, we manage with care,
A tapestry woven, each function laid bare.
With every new change, our project takes flight,
Together we flourish, in morning's soft light! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@marvinIsSacul marvinIsSacul added the microfrontend-poc OpenHIM Console Microfrontend Proof of Concept label Aug 23, 2024
@drizzentic
Copy link
Collaborator

@coderabbitai review

Copy link

coderabbitai bot commented Aug 27, 2024

Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Outside diff range, codebase verification and nitpick comments (21)
packages/channels-app/src/components/helpers/loader.component.tsx (1)

4-14: Consider using the sx prop for styling and review the use of 100vh.

The component is correctly implemented, but using the sx prop for styling can improve readability. Additionally, setting the height to 100vh might not always be desirable.

Consider applying this diff for better readability:

 const Loader: React.FC = () => {
   return (
-    <Box
-      display="flex"
-      justifyContent="center"
-      alignItems="center"
-      height="100vh"
-    >
+    <Box 
+      sx={{ 
+        display: 'flex', 
+        justifyContent: 'center', 
+        alignItems: 'center', 
+        height: '100vh' 
+      }}
+    >
       <CircularProgress />
     </Box>
   )
 }
packages/channels-app/src/jembi-channels-app.tsx (1)

6-14: Improve the error boundary.

The error boundary currently returns null. It is recommended to provide more information or a fallback UI to improve the user experience and debugging.

Consider applying this diff to improve the error boundary:

 const lifecycles = singleSpaReact({
   React,
   ReactDOM,
   rootComponent: Root,
   errorBoundary(err, info, props) {
-    // Customize the root error boundary for your microfrontend here.
-    return null
+    // Customize the root error boundary for your microfrontend here.
+    return (
+      <div>
+        <h1>Something went wrong.</h1>
+        <details style={{ whiteSpace: 'pre-wrap' }}>
+          {err && err.toString()}
+          <br />
+          {info.componentStack}
+        </details>
+      </div>
+    )
   }
 })
packages/channels-app/src/screens/add.channel.screen.tsx (2)

1-11: Consider optimizing imports.

The imports are well-organized, but consider importing specific components directly from @mui/material to potentially reduce bundle size.

-import {
-  Box,
-  Button,
-  Divider,
-  Grid,
-  Paper,
-  Step,
-  StepLabel,
-  Stepper,
-  Typography
-} from '@mui/material'
+import Box from '@mui/material/Box'
+import Button from '@mui/material/Button'
+import Divider from '@mui/material/Divider'
+import Grid from '@mui/material/Grid'
+import Paper from '@mui/material/Paper'
+import Step from '@mui/material/Step'
+import StepLabel from '@mui/material/StepLabel'
+import Stepper from '@mui/material/Stepper'
+import Typography from '@mui/material/Typography'

60-76: Consider using TypeScript for theme in makeStyles.

The _theme parameter in makeStyles can be typed to improve type safety and IntelliSense support.

-const useStyles = makeStyles(_theme => ({
+const useStyles = makeStyles((theme: Theme) => ({

Ensure you import Theme from @mui/material/styles.

+import { Theme } from '@mui/material/styles'
packages/channels-app/src/screens/steps/routes/ChannelRoutes.tsx (3)

1-16: Consider optimizing imports.

The imports are well-organized, but consider importing specific components directly from @mui/material to potentially reduce bundle size.

-import {
-  Box,
-  Button,
-  Chip,
-  Divider,
-  Grid,
-  IconButton,
-  Paper,
-  Table,
-  TableBody,
-  TableCell,
-  TableContainer,
-  TableHead,
-  TableRow,
-  Typography
-} from '@mui/material'
+import Box from '@mui/material/Box'
+import Button from '@mui/material/Button'
+import Chip from '@mui/material/Chip'
+import Divider from '@mui/material/Divider'
+import Grid from '@mui/material/Grid'
+import IconButton from '@mui/material/IconButton'
+import Paper from '@mui/material/Paper'
+import Table from '@mui/material/Table'
+import TableBody from '@mui/material/TableBody'
+import TableCell from '@mui/material/TableCell'
+import TableContainer from '@mui/material/TableContainer'
+import TableHead from '@mui/material/TableHead'
+import TableRow from '@mui/material/TableRow'
+import Typography from '@mui/material/Typography'

28-61: Consider using TypeScript for theme in makeStyles.

The _theme parameter in makeStyles can be typed to improve type safety and IntelliSense support.

-const useStyles = makeStyles(_theme => ({
+const useStyles = makeStyles((theme: Theme) => ({

Ensure you import Theme from @mui/material/styles.

+import { Theme } from '@mui/material/styles'

63-66: Consider destructuring props.

Destructuring props can improve readability and make it clear what props are expected.

-export function ChannelRoutes(props: {
-  channel: Channel
-  onChange: (event: {channel: Channel; isValid: boolean}) => unknown
-}) {
+export function ChannelRoutes({
+  channel: initialChannel,
+  onChange
+}: {
+  channel: Channel
+  onChange: (event: {channel: Channel; isValid: boolean}) => unknown
+}) {
packages/channels-app/src/screens/manage.channels.screen.tsx (2)

1-18: Consider optimizing imports.

The imports are well-organized, but consider importing specific components directly from @mui/material to potentially reduce bundle size.

-import {
-  Box,
-  Button,
-  Chip,
-  Divider,
-  Grid,
-  IconButton,
-  Menu,
-  MenuItem,
-  Paper,
-  Typography
-} from '@mui/material'
+import Box from '@mui/material/Box'
+import Button from '@mui/material/Button'
+import Chip from '@mui/material/Chip'
+import Divider from '@mui/material/Divider'
+import Grid from '@mui/material/Grid'
+import IconButton from '@mui/material/IconButton'
+import Menu from '@mui/material/Menu'
+import MenuItem from '@mui/material/MenuItem'
+import Paper from '@mui/material/Paper'
+import Typography from '@mui/material/Typography'

33-40: Consider using TypeScript for theme in makeStyles.

The _theme parameter in makeStyles can be typed to improve type safety and IntelliSense support.

-const useStyles = makeStyles(_theme => ({
+const useStyles = makeStyles((theme: Theme) => ({

Ensure you import Theme from @mui/material/styles.

+import { Theme } from '@mui/material/styles'
packages/channels-app/src/screens/steps/BasicInfo.tsx (7)

1-2: Import Optimization

Consider importing only the necessary icons from @mui/icons-material to reduce bundle size.

-import ArrowDropDown from '@mui/icons-material/ArrowDropDown'
-import ArrowDropUp from '@mui/icons-material/ArrowDropUp'
+import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'

3-16: Import Optimization

Consider importing only the necessary components from @mui/material to reduce bundle size.

-import {
-  Box,
-  Checkbox,
-  Divider,
-  FormControlLabel,
-  Grid,
-  IconButton,
-  Paper,
-  Radio,
-  RadioGroup,
-  Switch,
-  TextField,
-  Typography
-} from '@mui/material'
+import Box from '@mui/material/Box'
+import Checkbox from '@mui/material/Checkbox'
+import Divider from '@mui/material/Divider'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import Grid from '@mui/material/Grid'
+import IconButton from '@mui/material/IconButton'
+import Paper from '@mui/material/Paper'
+import Radio from '@mui/material/Radio'
+import RadioGroup from '@mui/material/RadioGroup'
+import Switch from '@mui/material/Switch'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'

21-45: Style Consistency

The styles defined in useStyles are consistent and follow a clear pattern. However, consider using a theme for consistent spacing and colors.

const useStyles = makeStyles(theme => ({
  divider: {
    marginTop: theme.spacing(1),
    margin: 0,
    width: '100%',
    marginBottom: theme.spacing(1),
    overflow: 'visible'
  },
  divider2: {
    marginTop: theme.spacing(1),
    margin: 0,
    width: '100%',
    marginBottom: theme.spacing(3),
    overflow: 'visible'
  },
  allowedMethodsContainer: {
    padding: theme.spacing(1)
  },
  optionalSettingsContainer: {
    borderRadius: theme.shape.borderRadius,
    padding: theme.spacing(1.5)
  },
  channelTypeRadioGroup: {
    padding: theme.spacing(1)
  }
}))

53-74: State Management

The state management for the channel is well-implemented. However, consider using a reducer for more complex state updates.

const [channel, setChannel] = React.useState(props.channel)
const allowedMethods: Array<ChannelMethod> = [
  'GET', 'HEAD', 'POST', 'TRACE', 'DELETE', 'CONNECT', 'PUT', 'PATCH', 'OPTIONS'
]
const channelTypes: Array<ChannelType> = ['http', 'tcp', 'tls', 'polling']
const [expandOptionalSettings, setExpandOptionalSettings] = React.useState(false)

React.useEffect(() => {
  props.onChange({
    channel: channel,
    isValid: !!channel.name.trim()
  })
}, [channel])

76-88: Method Handling

The handleCheckToggle function is well-implemented. However, consider using a Set for better performance when managing the methods array.

const handleCheckToggle = (method: ChannelMethod, checked: boolean) => {
  let methods = new Set(channel.methods || [])

  if (checked) {
    methods.add(method)
  } else {
    methods.delete(method)
  }

  setChannel({...channel, methods: Array.from(methods)})
}

101-116: Form Validation

The form validation for the channel name is well-implemented. However, consider extracting the validation logic into a separate function for better readability.

const validateChannelName = (name: string) => {
  return name.trim() === ''
}

<TextField
  label="Channel Name"
  variant="outlined"
  fullWidth
  margin="normal"
  value={channel.name}
  onChange={e => setChannel({...channel, name: e.target.value})}
  error={validateChannelName(channel.name)}
  helperText={
    validateChannelName(channel.name) ? 'Channel Name cannot be empty' : undefined
  }
/>

119-139: Dynamic Rendering

The dynamic rendering of allowed methods is well-implemented. However, consider memoizing the allowedMethods array for better performance.

const allowedMethods = React.useMemo(() => [
  'GET', 'HEAD', 'POST', 'TRACE', 'DELETE', 'CONNECT', 'PUT', 'PATCH', 'OPTIONS'
], [])

<Grid container>
  {allowedMethods.map(method => (
    <Grid item xs={6} key={method}>
      <FormControlLabel
        control={
          <Checkbox
            checked={channel.methods?.includes(method)}
            onChange={e => handleCheckToggle(method, e.target.checked)}
          />
        }
        label={method}
      />
    </Grid>
  ))}
</Grid>
packages/channels-app/src/screens/steps/routes/ChannelRoute.tsx (5)

1-12: Import Optimization

Consider importing only the necessary components from @mui/material to reduce bundle size.

-import {
-  Box,
-  Button,
-  FormControlLabel,
-  FormHelperText,
-  Grid,
-  Radio,
-  RadioGroup,
-  Switch,
-  TextField,
-  Typography
-} from '@mui/material'
+import Box from '@mui/material/Box'
+import Button from '@mui/material/Button'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import FormHelperText from '@mui/material/FormHelperText'
+import Grid from '@mui/material/Grid'
+import Radio from '@mui/material/Radio'
+import RadioGroup from '@mui/material/RadioGroup'
+import Switch from '@mui/material/Switch'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'

17-30: Style Consistency

The styles defined in useStyles are consistent and follow a clear pattern. However, consider using a theme for consistent spacing and colors.

const useStyles = makeStyles(theme => ({
  divider: {
    marginTop: theme.spacing(1),
    margin: 0,
    width: '100%',
    marginBottom: theme.spacing(1),
    overflow: 'visible'
  },
  switchHelperText: {
    marginLeft: theme.spacing(5.625)
  },
  routeTypeRadioGroup: {
    paddingLeft: theme.spacing(1)
  }
}))

43-48: State Management

The state management for the route is well-implemented. However, consider using a reducer for more complex state updates.

const [route, setRoute] = React.useState(
  structuredClone(props.route ?? defaultRoute)
)

50-54: Dynamic Title

The dynamic title for the form is well-implemented. However, consider extracting it into a separate function for better readability.

const getTitle = (isCreateMode: boolean) => {
  return isCreateMode ? 'Add New Route' : 'Edit Route'
}

<Typography variant="h5">
  {getTitle(isCreateMode)}
</Typography>

56-71: Form Validation

The form validation for the route name is well-implemented. However, consider extracting the validation logic into a separate function for better readability.

const validateRouteName = (name: string) => {
  return name.trim() === ''
}

<TextField
  label="Route Name"
  variant="outlined"
  fullWidth
  margin="normal"
  value={route.name}
  onChange={e => setRoute({...route, name: e.target.value})}
  error={validateRouteName(route.name)}
  helperText={
    validateRouteName(route.name) ? 'Route Name cannot be empty' : undefined
  }
/>
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 3bd9c34 and 003b08d.

Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
Files selected for processing (38)
  • packages/channels-app/.eslintrc (1 hunks)
  • packages/channels-app/.gitignore (1 hunks)
  • packages/channels-app/.prettierignore (1 hunks)
  • packages/channels-app/babel.config.json (1 hunks)
  • packages/channels-app/jest.config.js (1 hunks)
  • packages/channels-app/package.json (1 hunks)
  • packages/channels-app/src/components/dialogs/alert.dialog.component.tsx (1 hunks)
  • packages/channels-app/src/components/dialogs/basic.backdrop.component.tsx (1 hunks)
  • packages/channels-app/src/components/dialogs/basic.dialog.component.tsx (1 hunks)
  • packages/channels-app/src/components/dialogs/confirmation.dialog.component.tsx (1 hunks)
  • packages/channels-app/src/components/helpers/custom.toolbar.tsx (1 hunks)
  • packages/channels-app/src/components/helpers/error.component.tsx (1 hunks)
  • packages/channels-app/src/components/helpers/loader.component.tsx (1 hunks)
  • packages/channels-app/src/components/helpers/tags.input.autocomplete.tsx (1 hunks)
  • packages/channels-app/src/contexts/alert.context.tsx (1 hunks)
  • packages/channels-app/src/contexts/backdrop.context.tsx (1 hunks)
  • packages/channels-app/src/contexts/confirmation.context.tsx (1 hunks)
  • packages/channels-app/src/contexts/dialog.context.tsx (1 hunks)
  • packages/channels-app/src/declarations.d.ts (1 hunks)
  • packages/channels-app/src/jembi-channels-app.tsx (1 hunks)
  • packages/channels-app/src/root.component.test.tsx (1 hunks)
  • packages/channels-app/src/root.component.tsx (1 hunks)
  • packages/channels-app/src/router/index.tsx (1 hunks)
  • packages/channels-app/src/screens/add.channel.screen.tsx (1 hunks)
  • packages/channels-app/src/screens/edit.channel.screen.tsx (1 hunks)
  • packages/channels-app/src/screens/manage.channels.screen.tsx (1 hunks)
  • packages/channels-app/src/screens/steps/BasicInfo.tsx (1 hunks)
  • packages/channels-app/src/screens/steps/RequestMatching.tsx (1 hunks)
  • packages/channels-app/src/screens/steps/routes/ChannelRoute.tsx (1 hunks)
  • packages/channels-app/src/screens/steps/routes/ChannelRoutes.tsx (1 hunks)
  • packages/channels-app/src/services/api.ts (1 hunks)
  • packages/channels-app/src/types/index.ts (1 hunks)
  • packages/channels-app/tsconfig.json (1 hunks)
  • packages/channels-app/webpack.config.js (1 hunks)
  • packages/openhim-core-api/src/jembi-openhim-core-api.ts (1 hunks)
  • packages/root-config/src/index.ejs (1 hunks)
  • packages/root-config/src/microfrontend-layout.html (2 hunks)
  • packaging/import-maps-server/importmap.json (1 hunks)
Files skipped from review due to trivial changes (7)
  • packages/channels-app/.eslintrc
  • packages/channels-app/.gitignore
  • packages/channels-app/.prettierignore
  • packages/channels-app/babel.config.json
  • packages/channels-app/jest.config.js
  • packages/channels-app/src/root.component.test.tsx
  • packages/channels-app/tsconfig.json
Additional comments not posted (78)
packages/channels-app/webpack.config.js (1)

1-15: LGTM!

The Webpack configuration is correctly implemented and follows best practices.

The code changes are approved.

packages/channels-app/src/components/dialogs/basic.backdrop.component.tsx (2)

1-2: LGTM!

The import statements are correct and necessary for the component.


4-8: LGTM!

The type definition for BasicBackdropProps is clear and correctly typed.

packages/channels-app/src/router/index.tsx (1)

1-5: LGTM!

The import statements are correct and necessary for the router setup.

packages/channels-app/src/components/dialogs/basic.dialog.component.tsx (3)

1-2: LGTM!

The import statements are correct and necessary for the component.


4-11: LGTM!

The type definition for BasicDialogProps is clear and correctly typed.


13-23: Remove unused defaultContentWrapper prop.

The component is correctly implemented, but the defaultContentWrapper prop is not used. Consider removing it if it's not needed.

 export type BasicDialogProps = {
   title?: string
   open: boolean
   onClose: () => void
   children: React.ReactNode
   size?: DialogProps['maxWidth']
-  defaultContentWrapper?: boolean
 }

 export function BasicDialog(props: BasicDialogProps) {
   return (
     <Dialog
       open={props.open}
       onClose={props.onClose}
       maxWidth={props.size ?? 'lg'}
     >
       {props.title && <DialogTitle>{props.title}</DialogTitle>}
       <DialogContent>{props.children}</DialogContent>
     </Dialog>
   )
 }

Likely invalid or redundant comment.

packages/channels-app/src/components/helpers/custom.toolbar.tsx (3)

1-7: LGTM!

The import statements are correct and necessary for the component.


9-15: LGTM!

The style definitions are straightforward and appropriate for the component.


17-29: LGTM!

The CustomToolbar component is well-structured and correctly uses the imported components and styles.

packages/channels-app/src/declarations.d.ts (2)

1-39: LGTM!

The module declarations for various file types are correct and necessary for TypeScript to handle these file types.


41-42: LGTM!

The module declarations for @jembi/openhim-core-api and @jembi/openhim-theme are correct and necessary for TypeScript to handle these specific modules.

packages/channels-app/src/components/dialogs/alert.dialog.component.tsx (3)

1-4: LGTM!

The import statements are correct and necessary for the component.


6-12: LGTM!

The type definitions for AlertDialogProps are correct and appropriate for the component.


14-29: LGTM!

The AlertDialog component is well-structured and correctly uses the imported components and types.

packaging/import-maps-server/importmap.json (1)

13-13: LGTM!

The new entry for @jembi/channels-app is correctly formatted and follows the existing pattern.

The code changes are approved.

packages/channels-app/src/services/api.ts (4)

9-16: LGTM!

The function is correctly implemented and handles errors appropriately.

The code changes are approved.


18-25: LGTM!

The function is correctly implemented and handles errors appropriately.

The code changes are approved.


27-34: LGTM!

The function is correctly implemented and handles errors appropriately.

The code changes are approved.


36-43: LGTM!

The function is correctly implemented and handles errors appropriately.

The code changes are approved.

packages/channels-app/src/components/helpers/error.component.tsx (1)

1-33: LGTM!

The component is correctly implemented and follows best practices for React components.

The code changes are approved.

packages/channels-app/src/root.component.tsx (3)

1-10: LGTM!

The imports are necessary and correctly implemented.

The code changes are approved.


12-12: LGTM!

The QueryClient instantiation is necessary and correctly implemented.

The code changes are approved.


14-31: LGTM!

The Root component function is correctly implemented and wraps the application with necessary providers.

The code changes are approved.

packages/channels-app/src/components/dialogs/confirmation.dialog.component.tsx (3)

1-8: LGTM!

The imports are necessary and correctly implemented.

The code changes are approved.


10-17: LGTM!

The type definition for the confirmation dialog props is necessary and correctly implemented.

The code changes are approved.


19-38: LGTM!

The ConfirmationDialog component is correctly implemented and handles dialog state and actions as expected.

The code changes are approved.

packages/channels-app/src/components/helpers/tags.input.autocomplete.tsx (3)

1-2: LGTM!

The imports are necessary and correctly implemented.

The code changes are approved.


4-11: LGTM!

The type definition for the tag input autocomplete props is necessary and correctly implemented.

The code changes are approved.


13-51: LGTM!

The TagInputAutocomplete component is correctly implemented and handles input state and actions as expected.

The code changes are approved.

packages/channels-app/src/contexts/alert.context.tsx (5)

1-3: LGTM!

The imports are appropriate and necessary for the functionality.

The code changes are approved.


5-8: LGTM!

The AlertContextProps interface is well-defined and provides a clear contract for the context value.

The code changes are approved.


10-10: LGTM!

The AlertContext is correctly created with an appropriate default value.

The code changes are approved.


12-49: LGTM!

The AlertProvider is well-implemented, managing the alert state and providing necessary methods.

The code changes are approved.


51-57: LGTM!

The useAlert custom hook is correctly implemented, ensuring it is used within the AlertProvider.

The code changes are approved.

packages/channels-app/src/contexts/backdrop.context.tsx (5)

1-2: LGTM!

The imports are appropriate and necessary for the functionality.

The code changes are approved.


4-7: LGTM!

The BasicBackdropContextProps interface is well-defined and provides a clear contract for the context value.

The code changes are approved.


9-11: LGTM!

The BasicBackdropContext is correctly created with an appropriate default value.

The code changes are approved.


13-45: LGTM!

The BasicBackdropProvider is well-implemented, managing the backdrop state and providing necessary methods.

The code changes are approved.


47-55: LGTM!

The useBasicBackdrop custom hook is correctly implemented, ensuring it is used within the BasicBackdropProvider.

The code changes are approved.

packages/channels-app/src/contexts/dialog.context.tsx (5)

1-2: LGTM!

The imports are appropriate and necessary for the functionality.

The code changes are approved.


4-11: LGTM!

The BasicDialogContextProps interface is well-defined and provides a clear contract for the context value.

The code changes are approved.


13-15: LGTM!

The BasicDialogContext is correctly created with an appropriate default value.

The code changes are approved.


17-57: LGTM!

The BasicDialogProvider is well-implemented, managing the dialog state and providing necessary methods.

The code changes are approved.


59-65: LGTM!

The useBasicDialog custom hook is correctly implemented, ensuring it is used within the BasicDialogProvider.

The code changes are approved.

packages/channels-app/src/contexts/confirmation.context.tsx (3)

1-17: LGTM!

The imports and context definition are correct.

The code changes are approved.


19-71: LGTM!

The ConfirmationProvider component is well-structured and correctly manages the state of the confirmation dialog.

The code changes are approved.


73-81: LGTM!

The custom hook useConfirmation is correctly implemented and ensures that it is used within the provider.

The code changes are approved.

packages/channels-app/package.json (3)

1-16: LGTM!

The package metadata and scripts are correctly defined and follow standard practices.

The code changes are approved.


17-48: LGTM!

The devDependencies are correctly defined and include necessary tools for development.

The code changes are approved.


49-70: LGTM!

The dependencies are correctly defined and include necessary libraries for the project.

The code changes are approved.

packages/root-config/src/microfrontend-layout.html (2)

12-13: LGTM!

The reordering of routes does not affect the functionality but may improve readability or organization.

The code changes are approved.


78-82: LGTM!

The addition of the new route for channels is correctly implemented and ensures that the channels application is rendered only when the URL matches exactly.

The code changes are approved.

packages/channels-app/src/types/index.ts (11)

1-4: LGTM!

The type definition for UpdatedByDef is correctly implemented.

The code changes are approved.


6-10: LGTM!

The type definition for ContactUserDef is correctly implemented.

The code changes are approved.


12-18: LGTM!

The type definition for RewriteRuleDef is correctly implemented.

The code changes are approved.


20-26: LGTM!

The type definition for AlertsDef is correctly implemented.

The code changes are approved.


32-50: LGTM!

The type definition for ChannelRoute is correctly implemented.

The code changes are approved.


52-61: LGTM!

The type definition for ChannelMethod is correctly implemented.

The code changes are approved.


63-63: LGTM!

The type definition for ChannelType is correctly implemented.

The code changes are approved.


65-65: LGTM!

The type definition for ChannelStatus is correctly implemented.

The code changes are approved.


67-67: LGTM!

The type definition for ChannelAuthType is correctly implemented.

The code changes are approved.


69-108: LGTM!

The type definition for Channel is correctly implemented.

The code changes are approved.


110-114: LGTM!

The enum definition for Routes is correctly implemented.

The code changes are approved.

packages/channels-app/src/screens/edit.channel.screen.tsx (3)

1-24: LGTM!

The imports are correctly defined and necessary for the component.

The code changes are approved.


29-43: LGTM!

The styles are correctly defined and appropriate for the component.

The code changes are approved.


45-173: LGTM!

The component EditChannelScreen is correctly implemented with appropriate state management and UI rendering.

The code changes are approved.

packages/root-config/src/index.ejs (1)

88-89: LGTM!

The import map is correctly defined with the new entry for @jembi/channels-app.

The code changes are approved.

packages/channels-app/src/screens/add.channel.screen.tsx (1)

118-231: Ensure accessibility and usability.

The component uses various MUI components, but ensure that all interactive elements are accessible and usable. For example, add aria-labels to buttons and ensure proper keyboard navigation.

Verify the accessibility of the component using tools like Lighthouse or aXe.

packages/channels-app/src/screens/steps/routes/ChannelRoutes.tsx (2)

158-242: Ensure accessibility and usability.

The component uses various MUI components, but ensure that all interactive elements are accessible and usable. For example, add aria-labels to buttons and ensure proper keyboard navigation.

Verify the accessibility of the component using tools like Lighthouse or aXe.


134-149: Consider adding a confirmation dialog for deleting routes.

The handleDeleteRoute function deletes a route without confirmation. Consider adding a confirmation dialog to prevent accidental deletions.

const handleDeleteRoute = (route: ChannelRoute) => () => {
  showConfirmation(
    'Are you sure you want to delete this route?',
    'Delete Route',
    () => {
      setChannel(
        structuredClone({
          ...channel,
          routes: channel.routes?.filter(r => r.name !== route.name)
        })
      )
      hideConfirmation()
    },
    hideConfirmation
  )
}

Likely invalid or redundant comment.

packages/channels-app/src/screens/manage.channels.screen.tsx (1)

137-194: Ensure accessibility and usability.

The component uses various MUI components, but ensure that all interactive elements are accessible and usable. For example, add aria-labels to buttons and ensure proper keyboard navigation.

Verify the accessibility of the component using tools like Lighthouse or aXe.

packages/channels-app/src/screens/steps/BasicInfo.tsx (1)

48-51: Prop Types

Consider using TypeScript interfaces or PropTypes to define the prop types for better type checking and documentation.

export function BasicInfo(props: {
  channel: Channel
  onChange: (event: {channel: Channel; isValid: boolean}) => unknown
}) {
+  BasicInfo.propTypes = {
+    channel: PropTypes.shape({
+      name: PropTypes.string.isRequired,
+      methods: PropTypes.arrayOf(PropTypes.string),
+      description: PropTypes.string,
+      type: PropTypes.string,
+      timeout: PropTypes.number,
+      status: PropTypes.string
+    }).isRequired,
+    onChange: PropTypes.func.isRequired
+  }

Likely invalid or redundant comment.

packages/openhim-core-api/src/jembi-openhim-core-api.ts (1)

171-176: LGTM!

The function is correctly implemented. It ensures that the API client is initialized before making the request and returns the response data.

The code changes are approved.

packages/channels-app/src/screens/steps/routes/ChannelRoute.tsx (1)

38-42: Prop Types

Consider using TypeScript interfaces or PropTypes to define the prop types for better type checking and documentation.

export function ChannelRoute(props: {
  route?: ChannelRouteDef
  onChange?: (event: {route: ChannelRouteDef; isValid: boolean}) => unknown
  onCancel?: () => unknown
}) {
+  ChannelRoute.propTypes = {
+    route: PropTypes.shape({
+      name: PropTypes.string.isRequired,
+      type: PropTypes.string.isRequired,
+      primary: PropTypes.bool,
+      waitPrimaryResponse: PropTypes.bool,
+      status: PropTypes.string,
+      secured: PropTypes.bool,
+      host: PropTypes.string,
+      port: PropTypes.number,
+      path: PropTypes.string,
+      pathTransform: PropTypes.string,
+      username: PropTypes.string,
+      password: PropTypes.string,
+      forwardAuthHeader: PropTypes.bool,
+      kafkaClientId: PropTypes.string,
+      kafkaTopic: PropTypes.string
+    }),
+    onChange: PropTypes.func,
+    onCancel: PropTypes.func
+  }

Likely invalid or redundant comment.

packages/channels-app/src/screens/steps/RequestMatching.tsx (3)

1-25: LGTM!

The import statements are appropriate and well-organized.

The code changes are approved.


26-54: LGTM!

The styles are well-defined and follow a consistent naming convention.

The code changes are approved.


56-57: LGTM!

The type definition is clear and appropriate for the use case.

The code changes are approved.

Comment on lines +7 to +22
const router = createMemoryRouter([
{
path: Routes.MANAGE_CHANNELS,
element: <ManageChannelsScreen />
},
{
path: Routes.CREATE_CHANNEL,
element: <AddChannelScreen />
},
{
path: Routes.EDIT_CHANNEL,
element: <EditChannelScreen />
}
])

export default router
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a fallback route.

The router setup is correct, but adding a fallback route for handling unknown paths could improve user experience.

 const router = createMemoryRouter([
   {
     path: Routes.MANAGE_CHANNELS,
     element: <ManageChannelsScreen />
   },
   {
     path: Routes.CREATE_CHANNEL,
     element: <AddChannelScreen />
   },
   {
     path: Routes.EDIT_CHANNEL,
     element: <EditChannelScreen />
+  },
+  {
+    path: '*',
+    element: <NotFoundScreen />
   }
 ])
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const router = createMemoryRouter([
{
path: Routes.MANAGE_CHANNELS,
element: <ManageChannelsScreen />
},
{
path: Routes.CREATE_CHANNEL,
element: <AddChannelScreen />
},
{
path: Routes.EDIT_CHANNEL,
element: <EditChannelScreen />
}
])
export default router
const router = createMemoryRouter([
{
path: Routes.MANAGE_CHANNELS,
element: <ManageChannelsScreen />
},
{
path: Routes.CREATE_CHANNEL,
element: <AddChannelScreen />
},
{
path: Routes.EDIT_CHANNEL,
element: <EditChannelScreen />
},
{
path: '*',
element: <NotFoundScreen />
}
])
export default router

Comment on lines +78 to +104
function AddChannelScreen() {
const classes = useStyles()
const navigate = useNavigate()
const {showAlert, hideAlert} = useAlert()
const {showBackdrop, hideBackdrop} = useBasicBackdrop()
const [activeStep, setActiveStep] = React.useState(0)
const [channel, setChannel] = React.useState(structuredClone(defaultChannel))
const [isFormValid, setIsFormValid] = React.useState(false)
const mutation = useMutation({
mutationFn: addChannel,
onMutate: () => {
showBackdrop(<Loader />, true)
},
onSuccess: () => {
hideBackdrop()
navigate(Routes.MANAGE_CHANNELS)
},
onError: (error: any) => {
console.error(error)
hideBackdrop()
showAlert(
'Error creating a new channel. ' + error?.response?.data,
'Error',
'error'
)
}
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper error handling in useMutation.

The onError callback logs the error but does not handle different error types or statuses. Consider adding more robust error handling.

-onError: (error: any) => {
-  console.error(error)
-  hideBackdrop()
-  showAlert(
-    'Error creating a new channel. ' + error?.response?.data,
-    'Error',
-    'error'
-  )
-}
+onError: (error: any) => {
+  console.error(error)
+  hideBackdrop()
+  const errorMessage = error?.response?.data || 'An unexpected error occurred.'
+  showAlert(
+    `Error creating a new channel. ${errorMessage}`,
+    'Error',
+    'error'
+  )
+}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function AddChannelScreen() {
const classes = useStyles()
const navigate = useNavigate()
const {showAlert, hideAlert} = useAlert()
const {showBackdrop, hideBackdrop} = useBasicBackdrop()
const [activeStep, setActiveStep] = React.useState(0)
const [channel, setChannel] = React.useState(structuredClone(defaultChannel))
const [isFormValid, setIsFormValid] = React.useState(false)
const mutation = useMutation({
mutationFn: addChannel,
onMutate: () => {
showBackdrop(<Loader />, true)
},
onSuccess: () => {
hideBackdrop()
navigate(Routes.MANAGE_CHANNELS)
},
onError: (error: any) => {
console.error(error)
hideBackdrop()
showAlert(
'Error creating a new channel. ' + error?.response?.data,
'Error',
'error'
)
}
})
function AddChannelScreen() {
const classes = useStyles()
const navigate = useNavigate()
const {showAlert, hideAlert} = useAlert()
const {showBackdrop, hideBackdrop} = useBasicBackdrop()
const [activeStep, setActiveStep] = React.useState(0)
const [channel, setChannel] = React.useState(structuredClone(defaultChannel))
const [isFormValid, setIsFormValid] = React.useState(false)
const mutation = useMutation({
mutationFn: addChannel,
onMutate: () => {
showBackdrop(<Loader />, true)
},
onSuccess: () => {
hideBackdrop()
navigate(Routes.MANAGE_CHANNELS)
},
onError: (error: any) => {
console.error(error)
hideBackdrop()
const errorMessage = error?.response?.data || 'An unexpected error occurred.'
showAlert(
`Error creating a new channel. ${errorMessage}`,
'Error',
'error'
)
}
})

Comment on lines +151 to +156
React.useEffect(() => {
props.onChange({
channel: structuredClone(channel),
isValid: channel.routes?.length > 0
})
}, [channel])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper cleanup in useEffect.

The useEffect hook updates the parent component when the channel changes. Ensure proper cleanup to prevent memory leaks.

React.useEffect(() => {
  props.onChange({
    channel: structuredClone(channel),
    isValid: channel.routes?.length > 0
  })
  return () => {
    // Cleanup code if necessary
  }
}, [channel])

Committable suggestion was skipped due to low confidence.

Comment on lines +74 to +122
<FormControlLabel
control={
<Switch
checked={route.primary}
onChange={e => setRoute({...route, primary: e.target.checked})}
/>
}
label="Primary Route?"
/>
<FormHelperText className={classes.switchHelperText}>
Toggle on if this is the primary route.
</FormHelperText>
</Grid>
<Grid item xs={12}>
<FormControlLabel
control={
<Switch
checked={route.waitPrimaryResponse}
onChange={e =>
setRoute({...route, waitPrimaryResponse: e.target.checked})
}
/>
}
label="Wait for Primary Response?"
/>
<FormHelperText className={classes.switchHelperText}>
Toggle on to wait for the response from the primary route before
proceeding.
</FormHelperText>
</Grid>
<Grid item xs={12}>
<FormControlLabel
control={
<Switch
checked={route.status === 'enabled'}
onChange={e =>
setRoute({
...route,
status: e.target.checked ? 'enabled' : 'disabled'
})
}
/>
}
label="Status"
/>
<FormHelperText className={classes.switchHelperText}>
Toggle on to enable this route.
</FormHelperText>
</Grid>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch Components

The switch components for various settings are well-implemented. However, consider extracting them into separate components for better readability and reusability.

const SwitchWithLabel = ({ checked, onChange, label, helperText }) => (
  <>
    <FormControlLabel
      control={<Switch checked={checked} onChange={onChange} />}
      label={label}
    />
    <FormHelperText className

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +90 to +111
<TextField
label="URL Patterns"
variant="outlined"
fullWidth
margin="normal"
InputProps={{
startAdornment: (
<span className={classes.urlPatternStartAdornment}>^</span>
),
endAdornment: (
<span className={classes.urlPatternEndAdornment}>$</span>
)
}}
value={channel.urlPattern}
onChange={e => setChannel({...channel, urlPattern: e.target.value})}
error={channel.urlPattern.trim() === ''}
helperText={
channel.urlPattern.trim() === ''
? 'URL patterns cannot be empty'
: undefined
}
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add validation and error handling for matchBodyType TextField components.

Ensure that the TextField components for matchBodyType have proper validation and error handling.

Comment on lines +132 to +152
<TagInputAutocomplete
tags={channel.txViewAcl}
onChange={txViewAcl => setChannel({...channel, txViewAcl})}
label="Which user groups are allowed to view this channel's transactions?"
/>
</Grid>

<Grid item xs={12}>
<TagInputAutocomplete
tags={channel.txViewAcl}
onChange={txViewFullAcl => setChannel({...channel, txViewFullAcl})}
label="Which user groups are allowed to view this channel's transactions full request/response body?"
/>
</Grid>

<Grid item xs={12}>
<TagInputAutocomplete
tags={channel.txViewAcl}
onChange={txRerunAcl => setChannel({...channel, txRerunAcl})}
label="Which user groups are allowed to rerun this channel's transactions?"
/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider creating a helper function for TagInputAutocomplete components.

The TagInputAutocomplete component is used multiple times with similar props. Consider creating a helper function to reduce redundancy.

Comment on lines +58 to +77
export function RequestMatching(props: {
channel: Channel
onChange: (event: {channel: Channel; isValid: boolean}) => unknown
}) {
const classes = useStyles()
const navigate = useNavigate()
const [channel, setChannel] = React.useState(props.channel)
const [expandOptionalSettings, setExpandOptionalSettings] =
React.useState(false)
const [isMatchSpecificRequestContent, setIsMatchSpecificRequestContent] =
React.useState(false)
const [matchBodyType, setMatchBodyType] =
React.useState<MatchBodyType>('NO MATCHING')

React.useEffect(() => {
props.onChange({
channel: channel,
isValid: !!channel.urlPattern.trim()
})
}, [channel])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add props.onChange to the useEffect dependency array.

To avoid potential issues, include props.onChange in the useEffect dependency array.

-}, [channel])
+}, [channel, props.onChange])
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function RequestMatching(props: {
channel: Channel
onChange: (event: {channel: Channel; isValid: boolean}) => unknown
}) {
const classes = useStyles()
const navigate = useNavigate()
const [channel, setChannel] = React.useState(props.channel)
const [expandOptionalSettings, setExpandOptionalSettings] =
React.useState(false)
const [isMatchSpecificRequestContent, setIsMatchSpecificRequestContent] =
React.useState(false)
const [matchBodyType, setMatchBodyType] =
React.useState<MatchBodyType>('NO MATCHING')
React.useEffect(() => {
props.onChange({
channel: channel,
isValid: !!channel.urlPattern.trim()
})
}, [channel])
export function RequestMatching(props: {
channel: Channel
onChange: (event: {channel: Channel; isValid: boolean}) => unknown
}) {
const classes = useStyles()
const navigate = useNavigate()
const [channel, setChannel] = React.useState(props.channel)
const [expandOptionalSettings, setExpandOptionalSettings] =
React.useState(false)
const [isMatchSpecificRequestContent, setIsMatchSpecificRequestContent] =
React.useState(false)
const [matchBodyType, setMatchBodyType] =
React.useState<MatchBodyType>('NO MATCHING')
React.useEffect(() => {
props.onChange({
channel: channel,
isValid: !!channel.urlPattern.trim()
})
}, [channel, props.onChange])

Comment on lines +110 to +115
export enum Routes {
MANAGE_CHANNELS = '/',
CREATE_CHANNEL = '/create-channel',
EDIT_CHANNEL = '/edit-channel',
CREATE_ROUTE = '/create-route'
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check on the hash router implemented here? #663

Comment on lines 189 to 191
{/* <TableCell padding="checkbox">
<Checkbox />
</TableCell> */}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the commented codes still necessary?

Comment on lines +29 to +60
divider: {
marginTop: '10px',
margin: '0px',
width: '100%',
marginBottom: '10px',
overflow: 'visible'
},
divider2: {
marginTop: '10px',
margin: '0px',
width: '100%',
marginBottom: '30px',
overflow: 'visible'
},
addNewRouteContainer: {
padding: '10px'
},
emptyState: {
padding: '20px',
textAlign: 'center',
color: '#999',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '200px'
},
emptyStateIcon: {
fontSize: '48px',
marginBottom: '10px',
color: '#999'
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we move this to a css file

Copy link
Collaborator Author

@marvinIsSacul marvinIsSacul Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To take advantage of TypeScript and that only works if the styles are defined in a .ts file.

I think perhaps I can move it to a separate ts file?

@drizzentic drizzentic marked this pull request as ready for review August 27, 2024 13:16
@drizzentic drizzentic merged commit c3082ec into poc-microfrontends Aug 30, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
microfrontend-poc OpenHIM Console Microfrontend Proof of Concept
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants