diff --git a/.github/workflows/test_build.yml b/.github/workflows/test_build.yml new file mode 100644 index 0000000..53cad24 --- /dev/null +++ b/.github/workflows/test_build.yml @@ -0,0 +1,42 @@ +name: Jest & Build Tests + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Runs on any open or reopened pull request + pull_request: + types: [opened, reopened, synchronize] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: "20" + cache: npm + - name: Restore cache + uses: actions/cache@v3 + with: + path: | + .next/cache + # Generate a new cache whenever packages or source files change. + key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/package.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }} + # If source files changed but packages didn't, rebuild from a prior cache. + restore-keys: | + ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/package.json') }}- + - name: Install dependencies + run: npm ci + - name: Test + run: npm run test + - name: Build Test + run: npm run build diff --git a/README.md b/README.md index 71a0064..fdc4049 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Calima EHR +# Calima Sanar EHR - Medplum Dashboard Fork + +Welcome to the **Calima Sanar EHR** project! The following project is a medplum interface. @@ -16,19 +18,68 @@ Read [LICENSE](./LICENSE). Explore some features in our demo version [sanar.calimania.org](https://sanar.calimania.org). -Contact our team for support, custom integrations and enterprise plans. +## 🌟 Features + +- **Custom Branding**: Change logos and other visual elements to match your needs. +- **Cloud Ready**: Easily deployable on any cloud provider. +- **Extended Functionality**: Additional features and enhancements for seamless healthcare operations. +- **Environment Config**: Connect effortlessly to your existing Medplum dashboard using the `.env` file. + +We build with: +- **Vite** +- **Jest** +- **Babel** +- **Typescript** +- **Mantine 7** +- **Medplum 3** + +## ❤️ Open Source Interoperability + +At **Calima Sanar**, we believe in the power of **open source** and **interoperability**. We're passionate about creating a **healthtech ecosystem** that thrives on collaboration and innovation. + +We love **Medplum** and all the work they've done to advance healthcare solutions. Our goal is to build tools that expand upon their great foundation to create a more connected, flexible, and powerful EHR solution. + +## Links + +> A curar a la curanderia + +[Kalima Health Homepage](https://kalima.health/) + +[Calima EHR](https://ehr.caliman.org) + +[Medplum Docs](https://www.medplum.com/docs) + +[HIPAA with Digital Ocean](https://www.digitalocean.com/trust/hipaa-at-do) -This project was forked from [medplum/app](https://app.medplum.com) +[HIPAA Compliance with AWS](https://aws.amazon.com/compliance/hipaa-compliance/) + +# Medplum App + +This is the code for [https://app.medplum.com](https://app.medplum.com) + +## Deployment + +Medplum publishes the app package with placeholders for configuration settings. You can use the Medplum CLI to deploy the app, which will automatically replace the placeholders with your settings. + +For example: + +```bash +# Deploy the latest version of the app to your Medplum AWS environment named "staging" +medplum aws deploy-app staging +``` ## Config Settings +When deploying from the Medplum CLI, config settings are loaded from the corresponding JSON config file. + When building and running the app from source, config settings are loaded from environment variables or the `.env` file. | Name | Description | Required | | -------------------------- | ------------------------------------------------------------------------------------------ | -------- | | `MEDPLUM_BASE_URL` | The base URL of the API server for all API calls. For example, "https://api.medplum.com/". | yes | -| `CALIMA_BASE_URL` | The base URL of the API server for all API calls. For example, "https://api.medplum.com/". | no | | `MEDPLUM_CLIENT_ID` | Optional Medplum client application ID. | no | +| `GOOGLE_CLIENT_ID` | Optional Google client application ID for Google Auth. | no | +| `RECAPTCHA_SITE_KEY` | Optional reCAPTCHA site key for reCAPTCHA user verification. | no | | `MEDPLUM_REGISTER_ENABLED` | Optional flag to enable or disable open registration for new projects. | no | ## Developing @@ -44,3 +95,9 @@ Production build: ```bash npm run build ``` + +For more information, refer to the [Developer Instructions](https://www.medplum.com/docs/contributing/run-the-stack). + +# LICENSE + +Available under the [TSL](./LICENSE) license. diff --git a/jest.config.json b/jest.config.json index 67c4889..fc99809 100644 --- a/jest.config.json +++ b/jest.config.json @@ -6,6 +6,7 @@ }, "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"], "moduleNameMapper": { + "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/mocks/fileMock.js", "\\.css$": "identity-obj-proxy" }, "testMatch": ["**/src/**/*.test.ts", "**/src/**/*.test.tsx"], diff --git a/mocks/fileMock.js b/mocks/fileMock.js new file mode 100644 index 0000000..9dc5fc1 --- /dev/null +++ b/mocks/fileMock.js @@ -0,0 +1 @@ +module.exports = ''; diff --git a/src/App.css b/src/App.css index 193d74f..6de36ba 100644 --- a/src/App.css +++ b/src/App.css @@ -10,3 +10,41 @@ body, .grecaptcha-badge { visibility: hidden; } + +a.Navbar_link { + padding: 8px 12px; + border-radius: var(--mantine-radius-sm); + font-weight: 500; + display: flex; + align-items: center; + text-decoration: none; + font-size: var(--mantine-font-size-sm); + color: var(--mantine-color-gray-7); +} + +a.Navbar_link svg { + margin-right: var(--mantine-spacing-sm); + stroke-width: 1.5; + width: 18px; + height: 18px; +} + +.Header_logoButton:hover { + background-color: var(--mantine-color-blue-6); + border-radius: var(--mantine-radius-sm); +} + +a.Navbar_link:hover { + background-color: var(--mantine-color-blue-6); + color: var(--mantine-color-white); + text-decoration: none; +} + +a.Navbar_linkActive { + color: var(--mantine-color-blue-6); +} + +.Panel_paper { + margin: var(--mantine-spacing-xl) auto; + padding: 1em; +} \ No newline at end of file diff --git a/src/App.test.tsx b/src/App.test.tsx index 3298c2b..3efe3f0 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -119,7 +119,7 @@ function isNavOpen(): boolean { async function openNav(): Promise { if (!isNavOpen()) { await act(async () => { - fireEvent.click(screen.getByTitle('Calima Logo')); + fireEvent.click(screen.getByTitle('Calima Sanar logo')); }); } } diff --git a/src/RegisterPage.tsx b/src/RegisterPage.tsx index e5da182..5a6288d 100644 --- a/src/RegisterPage.tsx +++ b/src/RegisterPage.tsx @@ -36,7 +36,8 @@ export function RegisterPage(): JSX.Element | null { recaptchaSiteKey={config.recaptchaSiteKey} > - Create a new account + {config.appName} + Create a new account ); } diff --git a/src/SignInPage.test.tsx b/src/SignInPage.test.tsx index e3aa8ca..7380d35 100644 --- a/src/SignInPage.test.tsx +++ b/src/SignInPage.test.tsx @@ -33,7 +33,7 @@ describe('SignInPage', () => { }); function expectSigninPageRendered(): void { - expect(screen.getByText('Sign in to Medplum')).toBeInTheDocument(); + expect(screen.getByText('Sign in to Calima EHR')).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Next' })).toBeInTheDocument(); } diff --git a/src/SignInPage.tsx b/src/SignInPage.tsx index 07aaa1f..e16016b 100644 --- a/src/SignInPage.tsx +++ b/src/SignInPage.tsx @@ -34,7 +34,7 @@ export function SignInPage(): JSX.Element { projectId={searchParams.get('project') || undefined} > - Sign in to Calima EHR + Sign in to {config.appName} {searchParams.get('project') === 'new' &&
Sign in again to create a new project
} ); diff --git a/src/assets/sanar-logo-160x160.png b/src/assets/sanar-logo-160x160.png new file mode 100644 index 0000000..c267e40 Binary files /dev/null and b/src/assets/sanar-logo-160x160.png differ diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx index aaef3d8..dca91ca 100644 --- a/src/components/Logo.tsx +++ b/src/components/Logo.tsx @@ -1,7 +1,25 @@ -const Logo = (props: { size?: number; }): JSX.Element => { +import SanarLogo from '../assets/sanar-logo-160x160.png'; + +export interface LogoProps { + children?: React.ReactNode; + size?: number; +} + +/** + * Logo component - renders the Calima Sanar logo + * TODO: Customize logo using .env or remote configuration from an endpoint + * + * @param props - {LogoProps} - size? children? + * @returns Logo component + */ +export default function Logo(props: LogoProps): JSX.Element { + return ( - + Calima Sanar logo ); -}; - -export default Logo; +} diff --git a/src/config.ts b/src/config.ts index 347e63f..25ab0a2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,6 +5,7 @@ export interface MedplumAppConfig { recaptchaSiteKey?: string; registerEnabled?: boolean | string; awsTextractEnabled?: boolean | string; + appName?: string; } const config: MedplumAppConfig = { @@ -14,6 +15,7 @@ const config: MedplumAppConfig = { recaptchaSiteKey: import.meta.env?.RECAPTCHA_SITE_KEY, registerEnabled: import.meta.env?.MEDPLUM_REGISTER_ENABLED, awsTextractEnabled: import.meta.env?.MEDPLUM_AWS_TEXTRACT_ENABLED, + appName: import.meta.env?.APP_NAME || 'Calima EHR', }; export function getConfig(): MedplumAppConfig {