From 69da3ebe0871c78da6ae9be6066e354b36330746 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Fri, 28 Jun 2024 15:14:39 -0500 Subject: [PATCH] Bundle backend as reusable library and create server-doj and server-kansas demos (#231) * Move doj-demo to packages/server, and create an initial app/server-doj application that imports an Express handler from atj/server. TODO: clean up exports, get typings working. * App handler serving content, but not 100% working * Server package rendering existing client-side behavior correctly. * Add a basic test that confirms the home page is rendered on the DOJ custom server. * Remove debug logging from layout component * Server dev tasks - build esm * Make component signatures in spotlight app consistent with updates for @atj/server * Update docker config for new server-doj and server-kansas apps. * Add server-kansas app * Updates to Terraform to accomodate new server package. * Temporary: Add `astro-library` to deploy, to test TF updates * Log deployEnv on error * Temp: hardcode main deploy for testing * Update deploy script to use arguments for target environment rather that directly pulling the git ref * Try to reference via context: env.*. I don't think this will work, but found some suggestions that it might. * Give up trying to globally declare the deploy env, and pass on each users clause * Build the server entrypoint as part of standard build * Use injected site title in header rather than hardcoded DOJ name. * Remove references to "Spotlight" in the form service * Update a couple build labels * Add back FormRouter.stories.ts * Build before testing. Unfortunate, but we need a build to test the demo servers. * Add symlinks to sample-documents and storybook build * Work-around typing issue with svg icons * mask "no explicit any" eslint warning on svg icon hack * Fix comment in Astro App.Locals declaration * Explicitness on context arg passing * Document new structure in READMEs * Remove debug deploys on astro-library branch. * More generic example title * Autoformat --- .github/workflows/_docker-build-image.yml | 5 +- .github/workflows/_validate.yml | 5 + .github/workflows/deploy.yml | 14 +- Dockerfile | 6 +- README.md | 6 +- apps/doj-demo/README.md | 47 -- .../src/components/AppAvailableFormList.tsx | 26 - .../src/components/AppFormManager.tsx | 28 - .../doj-demo/src/components/AppFormRouter.tsx | 18 - apps/doj-demo/src/context.ts | 40 -- apps/doj-demo/src/env.d.ts | 1 - apps/doj-demo/src/pages/forms/index.astro | 8 - apps/doj-demo/src/pages/index.astro | 8 - apps/doj-demo/src/pages/manage/index.astro | 8 - apps/doj-demo/src/routes.ts | 31 - apps/server-doj/.gitignore | 1 + apps/server-doj/README.md | 3 + apps/server-doj/package.json | 22 + apps/server-doj/src/index.ts | 8 + apps/server-doj/src/server.ts | 7 + apps/server-doj/tests/integration.test.ts | 18 + apps/server-doj/tsconfig.json | 11 + apps/server-kansas/.gitignore | 1 + apps/server-kansas/README.md | 3 + apps/server-kansas/package.json | 22 + apps/server-kansas/src/index.ts | 8 + apps/server-kansas/src/server.ts | 7 + apps/server-kansas/tests/integration.test.ts | 18 + apps/server-kansas/tsconfig.json | 11 + .../src/components/AppFormManager.tsx | 11 +- .../src/components/AppFormRouter.tsx | 11 +- infra/src/index.ts | 2 +- infra/src/lib/app-stack.ts | 8 +- infra/src/lib/cloud.gov/node-astro.ts | 10 +- infra/src/lib/cloud.gov/space.ts | 15 +- infra/src/spaces/main.ts | 2 +- infra/src/spaces/staging.ts | 2 +- packages/design/package.json | 2 +- .../Form/components/RadioGroup/RadioGroup.tsx | 4 +- .../FormEdit/AddPatternDropdown.tsx | 5 +- .../components/CheckboxPatternEdit.tsx | 2 +- .../FormEdit/components/FieldsetEdit.tsx | 4 +- .../FormEdit/components/FormSummaryEdit.tsx | 2 +- .../FormEdit/components/InputPatternEdit.tsx | 2 +- .../FormEdit/components/PageEdit.tsx | 6 +- .../components/ParagraphPatternEdit.tsx | 2 +- .../PreviewSequencePattern/DraggableList.tsx | 16 +- .../components/RadioGroupPatternEdit.tsx | 8 +- packages/design/src/FormManager/index.tsx | 34 +- packages/design/src/FormRouter/index.tsx | 17 +- packages/design/src/index.ts | 4 +- {apps/doj-demo => packages/server}/.gitignore | 0 {apps/doj-demo => packages/server}/.nvmrc | 0 packages/server/README.md | 35 ++ .../server}/astro.config.mjs | 2 +- .../doj-demo => packages/server}/package.json | 8 +- packages/server/public/design | 1 + .../server}/public/favicon.ico | Bin .../public/favicon/android-chrome-192x192.png | Bin .../public/favicon/android-chrome-384x384.png | Bin .../public/favicon/android-chrome-512x512.png | Bin .../public/favicon/apple-touch-icon.png | Bin .../server}/public/favicon/favicon-16x16.png | Bin .../server}/public/favicon/favicon-32x32.png | Bin .../server}/public/favicon/favicon.ico | Bin packages/server/public/sample-documents | 1 + .../doj-demo => packages/server}/public/uswds | 0 .../src/components/AppAvailableFormList.tsx | 29 + .../server/src/components/AppFormManager.tsx | 27 + .../server/src/components/AppFormRouter.tsx | 15 + .../server}/src/components/DebugTools.tsx | 0 .../server}/src/components/Footer.astro | 9 +- .../server}/src/components/Header.astro | 15 +- .../server}/src/components/UsaBanner.astro | 0 packages/server/src/context.ts | 32 + packages/server/src/env.d.ts | 14 + packages/server/src/index.ts | 35 ++ .../server}/src/layouts/ContentLayout.astro | 0 .../server}/src/layouts/Layout.astro | 9 +- .../server}/src/lib/github.ts | 0 .../server}/src/lib/initialize.ts | 0 .../server}/src/pages/404.astro | 0 packages/server/src/pages/forms/index.astro | 11 + packages/server/src/pages/index.astro | 11 + .../server}/src/pages/manage/import-pdf.astro | 2 +- packages/server/src/pages/manage/index.astro | 11 + packages/server/src/routes.ts | 23 + .../server}/src/styles.css | 0 .../server}/tsconfig.json | 4 +- pnpm-lock.yaml | 570 ++++++++++++------ tsconfig.json | 3 +- 91 files changed, 906 insertions(+), 521 deletions(-) delete mode 100644 apps/doj-demo/README.md delete mode 100644 apps/doj-demo/src/components/AppAvailableFormList.tsx delete mode 100644 apps/doj-demo/src/components/AppFormManager.tsx delete mode 100644 apps/doj-demo/src/components/AppFormRouter.tsx delete mode 100644 apps/doj-demo/src/context.ts delete mode 100644 apps/doj-demo/src/env.d.ts delete mode 100644 apps/doj-demo/src/pages/forms/index.astro delete mode 100644 apps/doj-demo/src/pages/index.astro delete mode 100644 apps/doj-demo/src/pages/manage/index.astro delete mode 100644 apps/doj-demo/src/routes.ts create mode 100644 apps/server-doj/.gitignore create mode 100644 apps/server-doj/README.md create mode 100644 apps/server-doj/package.json create mode 100644 apps/server-doj/src/index.ts create mode 100644 apps/server-doj/src/server.ts create mode 100644 apps/server-doj/tests/integration.test.ts create mode 100644 apps/server-doj/tsconfig.json create mode 100644 apps/server-kansas/.gitignore create mode 100644 apps/server-kansas/README.md create mode 100644 apps/server-kansas/package.json create mode 100644 apps/server-kansas/src/index.ts create mode 100644 apps/server-kansas/src/server.ts create mode 100644 apps/server-kansas/tests/integration.test.ts create mode 100644 apps/server-kansas/tsconfig.json rename {apps/doj-demo => packages/server}/.gitignore (100%) rename {apps/doj-demo => packages/server}/.nvmrc (100%) create mode 100644 packages/server/README.md rename {apps/doj-demo => packages/server}/astro.config.mjs (97%) rename {apps/doj-demo => packages/server}/package.json (69%) create mode 120000 packages/server/public/design rename {apps/doj-demo => packages/server}/public/favicon.ico (100%) rename {apps/doj-demo => packages/server}/public/favicon/android-chrome-192x192.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/android-chrome-384x384.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/android-chrome-512x512.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/apple-touch-icon.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/favicon-16x16.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/favicon-32x32.png (100%) rename {apps/doj-demo => packages/server}/public/favicon/favicon.ico (100%) create mode 120000 packages/server/public/sample-documents rename {apps/doj-demo => packages/server}/public/uswds (100%) create mode 100644 packages/server/src/components/AppAvailableFormList.tsx create mode 100644 packages/server/src/components/AppFormManager.tsx create mode 100644 packages/server/src/components/AppFormRouter.tsx rename {apps/doj-demo => packages/server}/src/components/DebugTools.tsx (100%) rename {apps/doj-demo => packages/server}/src/components/Footer.astro (87%) rename {apps/doj-demo => packages/server}/src/components/Header.astro (76%) rename {apps/doj-demo => packages/server}/src/components/UsaBanner.astro (100%) create mode 100644 packages/server/src/context.ts create mode 100644 packages/server/src/env.d.ts create mode 100644 packages/server/src/index.ts rename {apps/doj-demo => packages/server}/src/layouts/ContentLayout.astro (100%) rename {apps/doj-demo => packages/server}/src/layouts/Layout.astro (86%) rename {apps/doj-demo => packages/server}/src/lib/github.ts (100%) rename {apps/doj-demo => packages/server}/src/lib/initialize.ts (100%) rename {apps/doj-demo => packages/server}/src/pages/404.astro (100%) create mode 100644 packages/server/src/pages/forms/index.astro create mode 100644 packages/server/src/pages/index.astro rename {apps/doj-demo => packages/server}/src/pages/manage/import-pdf.astro (69%) create mode 100644 packages/server/src/pages/manage/index.astro create mode 100644 packages/server/src/routes.ts rename {apps/doj-demo => packages/server}/src/styles.css (100%) rename {apps/doj-demo => packages/server}/tsconfig.json (71%) diff --git a/.github/workflows/_docker-build-image.yml b/.github/workflows/_docker-build-image.yml index 6e2c7726e..722e80b51 100644 --- a/.github/workflows/_docker-build-image.yml +++ b/.github/workflows/_docker-build-image.yml @@ -12,9 +12,12 @@ on: repo-name: type: string default: ${{ github.event.repository.name }} + tag-name: + type: string + default: ${{ github.ref_name }} env: - TAG_NAME: ${{ github.ref_name }} + TAG_NAME: ${{ inputs.tag-name }} APP_DIR: ${{ inputs.app-name }} REGISTRY_PATH: ghcr.io/${{ inputs.org-name }}/${{ inputs.repo-name }}/${{ inputs.app-name }} COMMIT_SHA: ${{github.sha}} diff --git a/.github/workflows/_validate.yml b/.github/workflows/_validate.yml index 7fbd56919..9b8b1cd4b 100644 --- a/.github/workflows/_validate.yml +++ b/.github/workflows/_validate.yml @@ -45,6 +45,11 @@ jobs: - name: Install dependencies run: pnpm install + # While most of the test suite is self-contained, the tests for the demo + # servers require a prod build of @atj/server. + - name: Build + run: pnpm build + - name: Lint source code shell: bash run: pnpm lint diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 584e285b0..703ed6544 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -12,17 +12,19 @@ jobs: uses: ./.github/workflows/_docker-build-image.yml secrets: inherit with: - app-name: doj-demo + app-name: server-doj + #tag-name: main - build-image-spotlight: + build-image-kansas: uses: ./.github/workflows/_docker-build-image.yml secrets: inherit with: - app-name: spotlight + app-name: server-kansas + #tag-name: main deploy: - needs: [build-image-doj, build-image-spotlight] + needs: [build-image-doj, build-image-kansas] uses: ./.github/workflows/_terraform-apply.yml secrets: inherit - with: - deploy-env: ${{ github.ref_name }} + #with: + # deploy-env: main diff --git a/Dockerfile b/Dockerfile index 5bebf5708..eff4b8c2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,9 +16,9 @@ RUN pnpm build RUN pnpm --filter=$APP_DIR --prod deploy /app/$APP_DIR FROM base AS app -ARG APP_DIR=doj-demo +ARG APP_DIR -LABEL org.opencontainers.image.description 10x-atj DOJ demo +LABEL org.opencontainers.image.description 10x Access to Justice Form Builder COPY --from=build /app/$APP_DIR /app/$APP_DIR COPY --from=build /usr/src/app/apps/$APP_DIR/dist /app/$APP_DIR/dist @@ -28,7 +28,7 @@ ENV HOST=0.0.0.0 ENV PORT=4321 EXPOSE 4321 -CMD [ "node", "./dist/server/entry.mjs" ] +CMD [ "node", "./dist/index.js" ] #HEALTHCHECK --interval=5m --timeout=3s \ # CMD curl -f http://localhost:4321/ || exit 1 diff --git a/README.md b/README.md index 520271306..f8c1d17a4 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ Test bed for ATJ platform tooling, completed as part of the [10x Digital Access ## Overview -The project dependencies within the workspace are: - -![workspace project dependencies](./workspace-dependencies.svg) +The workspace dependencies are depicted in this auto-generated [workspace project dependencies graph](./workspace-dependencies.svg). Additional documentation: @@ -26,7 +24,7 @@ The platform is made up of the following high-level terms. - **Blueprint**: produced by a content author, the blueprint defines the structure of an interactive session between a court and an SRL - **Conversation**: one instance of a blueprint; the interactive session between a court and an SRL. Other terms for this concept include dialogue or session. -- **Pattern**: the building blocks of a blueprint, patterns implement UX best-practices, defining the content and behavior of the user interface. +- **Pattern/template**: the building blocks of a blueprint, patterns implement UX best-practices, defining the content and behavior of the user interface. - **Prompt**: produced by a pattern, the prompt defines what is presented to the end user at single point in a conversation. - **Component**: user interface component that acts as the building block of prompts. diff --git a/apps/doj-demo/README.md b/apps/doj-demo/README.md deleted file mode 100644 index e34a99b44..000000000 --- a/apps/doj-demo/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Astro Starter Kit: Minimal - -```sh -npm create astro@latest -- --template minimal -``` - -[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal) -[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json) - -> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! - -## 🚀 Project Structure - -Inside of your Astro project, you'll see the following folders and files: - -```text -/ -├── public/ -├── src/ -│ └── pages/ -│ └── index.astro -└── package.json -``` - -Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. - -There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. - -Any static assets, like images, can be placed in the `public/` directory. - -## 🧞 Commands - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :------------------------ | :----------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | -| `npm run astro -- --help` | Get help using the Astro CLI | - -## 👀 Want to learn more? - -Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). diff --git a/apps/doj-demo/src/components/AppAvailableFormList.tsx b/apps/doj-demo/src/components/AppAvailableFormList.tsx deleted file mode 100644 index 572161347..000000000 --- a/apps/doj-demo/src/components/AppAvailableFormList.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { ErrorBoundary } from 'react-error-boundary'; - -import { AvailableFormList } from '@atj/design'; -import { getAppContext } from '../context'; -import { getFormUrl } from '../routes'; -import DebugTools from './DebugTools'; - -export default () => { - const ctx = getAppContext(); - return ( - - There was an unexpected error rendering the form list. - - - } - > - - - ); -}; diff --git a/apps/doj-demo/src/components/AppFormManager.tsx b/apps/doj-demo/src/components/AppFormManager.tsx deleted file mode 100644 index 9f4b687ba..000000000 --- a/apps/doj-demo/src/components/AppFormManager.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; - -import { - FormManager, - defaultPatternComponents, - defaultPatternEditComponents, -} from '@atj/design'; - -import { getAppContext } from '../context'; -import { getFormManagerUrlById, getFormUrl } from '../routes'; - -export default function () { - const ctx = getAppContext(); - return ( - - ); -} diff --git a/apps/doj-demo/src/components/AppFormRouter.tsx b/apps/doj-demo/src/components/AppFormRouter.tsx deleted file mode 100644 index 8d3bc81de..000000000 --- a/apps/doj-demo/src/components/AppFormRouter.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -import { FormRouter, defaultPatternComponents } from '@atj/design'; -import { getAppContext } from '../context'; - -export default function AppFormRouter() { - const ctx = getAppContext(); - return ( - - ); -} diff --git a/apps/doj-demo/src/context.ts b/apps/doj-demo/src/context.ts deleted file mode 100644 index 6cd036738..000000000 --- a/apps/doj-demo/src/context.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { FormConfig } from '@atj/forms'; -import { defaultFormConfig } from '@atj/forms'; -import { service } from '@atj/forms'; - -import { type GithubRepository } from './lib/github'; - -export type AppContext = { - baseUrl: `${string}/`; - formConfig: FormConfig; - formService: service.FormService; - github: GithubRepository; - uswdsRoot: `${string}/`; -}; - -let _context: AppContext | null = null; - -export const getAppContext = (): AppContext => { - if (_context === null) { - _context = createAppContext(import.meta.env); - } - return _context; -}; - -const createAppContext = (env: any): AppContext => { - return { - baseUrl: env.BASE_URL, - formConfig: defaultFormConfig, - formService: createAppFormService(), - github: env.GITHUB, - uswdsRoot: `${env.BASE_URL}uswds/`, - }; -}; - -const createAppFormService = () => { - if (globalThis.window) { - return service.createBrowserFormService(); - } else { - return service.createTestFormService(); - } -}; diff --git a/apps/doj-demo/src/env.d.ts b/apps/doj-demo/src/env.d.ts deleted file mode 100644 index f964fe0cf..000000000 --- a/apps/doj-demo/src/env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/apps/doj-demo/src/pages/forms/index.astro b/apps/doj-demo/src/pages/forms/index.astro deleted file mode 100644 index e69c1ada5..000000000 --- a/apps/doj-demo/src/pages/forms/index.astro +++ /dev/null @@ -1,8 +0,0 @@ ---- -import AppFormRouter from '../../components/AppFormRouter'; -import ContentLayout from '../../layouts/ContentLayout.astro'; ---- - - - - diff --git a/apps/doj-demo/src/pages/index.astro b/apps/doj-demo/src/pages/index.astro deleted file mode 100644 index 33b481c43..000000000 --- a/apps/doj-demo/src/pages/index.astro +++ /dev/null @@ -1,8 +0,0 @@ ---- -import AppFormManager from '../components/AppFormManager'; -import Layout from '../layouts/Layout.astro'; ---- - - - - diff --git a/apps/doj-demo/src/pages/manage/index.astro b/apps/doj-demo/src/pages/manage/index.astro deleted file mode 100644 index 46fdd18a3..000000000 --- a/apps/doj-demo/src/pages/manage/index.astro +++ /dev/null @@ -1,8 +0,0 @@ ---- -import AppFormManager from '../../components/AppFormManager'; -import Layout from '../../layouts/Layout.astro'; ---- - - - - diff --git a/apps/doj-demo/src/routes.ts b/apps/doj-demo/src/routes.ts deleted file mode 100644 index f336b9f8a..000000000 --- a/apps/doj-demo/src/routes.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { getAppContext } from './context'; - -export const getFormUrl = (formId: string) => { - const context = getAppContext(); - return `${context.baseUrl}forms#${formId}`; -}; - -export const getFormManagerUrlById = (formId: string) => { - const context = getAppContext(); - return `${context.baseUrl}#/${formId}`; -}; - -export const getManageUrl = () => { - const context = getAppContext(); - return `${context.baseUrl}manage`; -}; - -export const getHomeUrl = () => { - const context = getAppContext(); - return context.baseUrl; -}; - -export const getFaviconUrl = () => { - const context = getAppContext(); - return `${context.baseUrl}favicon.ico`; -}; - -export const getStorybookUrl = () => { - const context = getAppContext(); - return `${context.baseUrl}design/index.html`; -}; diff --git a/apps/server-doj/.gitignore b/apps/server-doj/.gitignore new file mode 100644 index 000000000..849ddff3b --- /dev/null +++ b/apps/server-doj/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/apps/server-doj/README.md b/apps/server-doj/README.md new file mode 100644 index 000000000..0ef185914 --- /dev/null +++ b/apps/server-doj/README.md @@ -0,0 +1,3 @@ +# @atj/server-doj + +Web server to demonstrate forms for DOJ's Office of the Pardon Attorney. diff --git a/apps/server-doj/package.json b/apps/server-doj/package.json new file mode 100644 index 000000000..a897725c0 --- /dev/null +++ b/apps/server-doj/package.json @@ -0,0 +1,22 @@ +{ + "name": "@atj/server-doj", + "version": "1.0.0", + "description": "Form server instance for DOJ", + "type": "module", + "license": "CC0", + "main": "src/index.ts", + "scripts": { + "start": "node dist/index.js", + "build": "tsup src/* --format esm", + "dev": "tsup src/* --watch --format esm", + "test": "vitest run --coverage" + }, + "dependencies": { + "@atj/server": "workspace:*" + }, + "devDependencies": { + "@types/node": "^20.14.8", + "@types/supertest": "^6.0.2", + "supertest": "^7.0.0" + } +} diff --git a/apps/server-doj/src/index.ts b/apps/server-doj/src/index.ts new file mode 100644 index 000000000..82e7c8ced --- /dev/null +++ b/apps/server-doj/src/index.ts @@ -0,0 +1,8 @@ +import { createCustomServer } from './server'; + +const port = process.env.PORT || 4321; +const app = await createCustomServer(); + +app.listen(port, () => { + console.log(`Server running on http://localhost:${port}`); +}); diff --git a/apps/server-doj/src/server.ts b/apps/server-doj/src/server.ts new file mode 100644 index 000000000..0ea9d7364 --- /dev/null +++ b/apps/server-doj/src/server.ts @@ -0,0 +1,7 @@ +import { createServer } from '@atj/server/dist/index.js'; + +export const createCustomServer = () => { + return createServer({ + title: 'DOJ Form Service', + }); +}; diff --git a/apps/server-doj/tests/integration.test.ts b/apps/server-doj/tests/integration.test.ts new file mode 100644 index 000000000..1d535e0dc --- /dev/null +++ b/apps/server-doj/tests/integration.test.ts @@ -0,0 +1,18 @@ +import request from 'supertest'; +import { beforeAll, describe, expect, test } from 'vitest'; + +import { createCustomServer } from '../src/server'; + +describe('DOJ Form Service', () => { + let app: any; + + beforeAll(async () => { + app = await createCustomServer(); + }); + + test('renders the home page', async () => { + const response = await request(app).get('/'); + expect(response.ok).toBe(true); + expect(response.text).toMatch(/DOJ Form Service/); + }); +}); diff --git a/apps/server-doj/tsconfig.json b/apps/server-doj/tsconfig.json new file mode 100644 index 000000000..1e4b75b94 --- /dev/null +++ b/apps/server-doj/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "emitDeclarationOnly": true, + "outDir": "./dist" + }, + "include": ["./src/**/*"], + "exclude": ["./dist"], + "references": [] +} diff --git a/apps/server-kansas/.gitignore b/apps/server-kansas/.gitignore new file mode 100644 index 000000000..849ddff3b --- /dev/null +++ b/apps/server-kansas/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/apps/server-kansas/README.md b/apps/server-kansas/README.md new file mode 100644 index 000000000..c2e6db8c7 --- /dev/null +++ b/apps/server-kansas/README.md @@ -0,0 +1,3 @@ +# @atj/server-kansas + +Web server to demonstrate forms for Kansas State Courts. diff --git a/apps/server-kansas/package.json b/apps/server-kansas/package.json new file mode 100644 index 000000000..576929992 --- /dev/null +++ b/apps/server-kansas/package.json @@ -0,0 +1,22 @@ +{ + "name": "@atj/server-kansas", + "version": "1.0.0", + "description": "Form server instance for Kansas State Courts", + "type": "module", + "license": "CC0", + "main": "src/index.ts", + "scripts": { + "start": "node dist/index.js", + "build": "tsup src/* --format esm", + "dev": "tsup src/* --watch --format esm", + "test": "vitest run --coverage" + }, + "dependencies": { + "@atj/server": "workspace:*" + }, + "devDependencies": { + "@types/node": "^20.14.8", + "@types/supertest": "^6.0.2", + "supertest": "^7.0.0" + } +} diff --git a/apps/server-kansas/src/index.ts b/apps/server-kansas/src/index.ts new file mode 100644 index 000000000..82e7c8ced --- /dev/null +++ b/apps/server-kansas/src/index.ts @@ -0,0 +1,8 @@ +import { createCustomServer } from './server'; + +const port = process.env.PORT || 4321; +const app = await createCustomServer(); + +app.listen(port, () => { + console.log(`Server running on http://localhost:${port}`); +}); diff --git a/apps/server-kansas/src/server.ts b/apps/server-kansas/src/server.ts new file mode 100644 index 000000000..c110b6ff2 --- /dev/null +++ b/apps/server-kansas/src/server.ts @@ -0,0 +1,7 @@ +import { createServer } from '@atj/server/dist/index.js'; + +export const createCustomServer = () => { + return createServer({ + title: 'KS Courts Form Service', + }); +}; diff --git a/apps/server-kansas/tests/integration.test.ts b/apps/server-kansas/tests/integration.test.ts new file mode 100644 index 000000000..97e88fb1d --- /dev/null +++ b/apps/server-kansas/tests/integration.test.ts @@ -0,0 +1,18 @@ +import request from 'supertest'; +import { beforeAll, describe, expect, test } from 'vitest'; + +import { createCustomServer } from '../src/server'; + +describe('Kansas State Courts Form Service', () => { + let app: any; + + beforeAll(async () => { + app = await createCustomServer(); + }); + + test('renders the home page', async () => { + const response = await request(app).get('/'); + expect(response.ok).toBe(true); + expect(response.text).toMatch(/KS Courts Form Service/); + }); +}); diff --git a/apps/server-kansas/tsconfig.json b/apps/server-kansas/tsconfig.json new file mode 100644 index 000000000..1e4b75b94 --- /dev/null +++ b/apps/server-kansas/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "emitDeclarationOnly": true, + "outDir": "./dist" + }, + "include": ["./src/**/*"], + "exclude": ["./dist"], + "references": [] +} diff --git a/apps/spotlight/src/components/AppFormManager.tsx b/apps/spotlight/src/components/AppFormManager.tsx index c06296c24..176ca59fe 100644 --- a/apps/spotlight/src/components/AppFormManager.tsx +++ b/apps/spotlight/src/components/AppFormManager.tsx @@ -1,10 +1,6 @@ import React from 'react'; -import { - FormManager, - defaultPatternComponents, - defaultPatternEditComponents, -} from '@atj/design'; +import { FormManager } from '@atj/design'; import { getAppContext } from '../context'; import { getFormManagerUrlById, getFormUrl } from '../routes'; @@ -15,13 +11,10 @@ export default function () { ); diff --git a/apps/spotlight/src/components/AppFormRouter.tsx b/apps/spotlight/src/components/AppFormRouter.tsx index 8d3bc81de..26849ee96 100644 --- a/apps/spotlight/src/components/AppFormRouter.tsx +++ b/apps/spotlight/src/components/AppFormRouter.tsx @@ -5,14 +5,5 @@ import { getAppContext } from '../context'; export default function AppFormRouter() { const ctx = getAppContext(); - return ( - - ); + return ; } diff --git a/infra/src/index.ts b/infra/src/index.ts index e8a3e91c9..492aeb8ea 100644 --- a/infra/src/index.ts +++ b/infra/src/index.ts @@ -12,7 +12,7 @@ switch (deployEnv) { import('./spaces/staging'); break; default: - throw new Error('Please specify a valid environment'); + throw new Error(`Please specify a valid environment (got: "${deployEnv}")`); } app.synth(); diff --git a/infra/src/lib/app-stack.ts b/infra/src/lib/app-stack.ts index 73116c215..d171b8767 100644 --- a/infra/src/lib/app-stack.ts +++ b/infra/src/lib/app-stack.ts @@ -8,15 +8,15 @@ import { withBackend } from './backend'; import { CloudGovSpace } from './cloud.gov/space'; import { DataAwsSsmParameter } from '../../.gen/providers/aws/data-aws-ssm-parameter'; -export const registerAppStack = (stackPrefix: string) => { +export const registerAppStack = (stackPrefix: string, deployEnv: string) => { const app = new App(); - const stack = new AppStack(app, stackPrefix); + const stack = new AppStack(app, stackPrefix, deployEnv); withBackend(stack, stackPrefix); app.synth(); }; class AppStack extends TerraformStack { - constructor(scope: Construct, id: string) { + constructor(scope: Construct, id: string, deployEnv: string) { super(scope, id); new AwsProvider(this, 'AWS', { @@ -45,7 +45,7 @@ class AppStack extends TerraformStack { password: cfPassword.value, }); - new CloudGovSpace(this, id); + new CloudGovSpace(this, id, deployEnv); //new Docassemble(this, `${id}-docassemble`); //new FormService(this, `${id}-rest-api`); diff --git a/infra/src/lib/cloud.gov/node-astro.ts b/infra/src/lib/cloud.gov/node-astro.ts index be626dccd..d437cdc2a 100644 --- a/infra/src/lib/cloud.gov/node-astro.ts +++ b/infra/src/lib/cloud.gov/node-astro.ts @@ -2,7 +2,12 @@ import { Construct } from 'constructs'; import * as cloudfoundry from '../../../.gen/providers/cloudfoundry'; export class AstroService extends Construct { - constructor(scope: Construct, id: string, spaceId: string) { + constructor( + scope: Construct, + id: string, + spaceId: string, + imageName: `${string}:${string}` + ) { super(scope, id); const domain = @@ -23,8 +28,7 @@ export class AstroService extends Construct { new cloudfoundry.app.App(this, `${id}-app`, { name: `${id}-app`, space: spaceId, - //dockerImage: 'ghcr.io/gsa-tts/tts-10x-atj-dev/doj-demo:latest', - dockerImage: 'ghcr.io/gsa-tts/atj-platform/doj-demo:main', + dockerImage: `ghcr.io/gsa-tts/atj-platform/${imageName}`, memory: 1024, diskQuota: 4096, healthCheckType: 'http', diff --git a/infra/src/lib/cloud.gov/space.ts b/infra/src/lib/cloud.gov/space.ts index d6ee176cc..4e2e42288 100644 --- a/infra/src/lib/cloud.gov/space.ts +++ b/infra/src/lib/cloud.gov/space.ts @@ -5,7 +5,7 @@ import { CLOUD_GOV_ORG_NAME } from './config'; import { AstroService } from './node-astro'; export class CloudGovSpace extends Construct { - constructor(scope: Construct, id: string) { + constructor(scope: Construct, id: string, deployEnv: string) { super(scope, id); const space = new cloudfoundry.dataCloudfoundrySpace.DataCloudfoundrySpace( @@ -17,6 +17,17 @@ export class CloudGovSpace extends Construct { } ); - new AstroService(scope, `${id}-doj-demo`, space.id); + new AstroService( + scope, + `${id}-server-doj`, + space.id, + `server-doj:${deployEnv}` + ); + new AstroService( + scope, + `${id}-server-kansas`, + space.id, + `server-kansas:${deployEnv}` + ); } } diff --git a/infra/src/spaces/main.ts b/infra/src/spaces/main.ts index 71726a044..34ed8c1c4 100644 --- a/infra/src/spaces/main.ts +++ b/infra/src/spaces/main.ts @@ -1,3 +1,3 @@ import { registerAppStack } from '../lib/app-stack'; -registerAppStack('tts-10x-atj-dev'); +registerAppStack('tts-10x-atj-dev', 'main'); diff --git a/infra/src/spaces/staging.ts b/infra/src/spaces/staging.ts index 2a18e55be..d6425f1e9 100644 --- a/infra/src/spaces/staging.ts +++ b/infra/src/spaces/staging.ts @@ -1,3 +1,3 @@ import { registerAppStack } from '../lib/app-stack'; -registerAppStack('tts-10x-atj-staging'); +registerAppStack('tts-10x-atj-staging', 'staging'); diff --git a/packages/design/package.json b/packages/design/package.json index e7a48605d..2c339da7a 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -17,7 +17,7 @@ "dev:styles": "gulp watch", "lint": "eslint --ext ts,tsx --report-unused-disable-directives --max-warnings 0 src", "test:url": "test-storybook --url http://127.0.0.1:9009 --config-dir .storybook", - "test:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"pnpm build:storybook --quiet && npx http-server storybook/public --port 9009 --silent\" \"wait-on tcp:127.0.0.1:9009 && pnpm test:url --maxWorkers=2\"" + "test:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"pnpm build:storybook --quiet && pnpm http-server storybook-static --port 9009 --silent\" \"wait-on tcp:127.0.0.1:9009 && pnpm test:url --maxWorkers=2\"" }, "files": [ "dist/**/*" diff --git a/packages/design/src/Form/components/RadioGroup/RadioGroup.tsx b/packages/design/src/Form/components/RadioGroup/RadioGroup.tsx index 7c4cb3314..267c4ec26 100644 --- a/packages/design/src/Form/components/RadioGroup/RadioGroup.tsx +++ b/packages/design/src/Form/components/RadioGroup/RadioGroup.tsx @@ -9,7 +9,9 @@ export const RadioGroupPattern: PatternComponent = props => { const { register } = useFormContext(); return (
- {props.legend} + + {props.legend} + {props.options.map((option, index) => { return (
diff --git a/packages/design/src/FormManager/FormEdit/AddPatternDropdown.tsx b/packages/design/src/FormManager/FormEdit/AddPatternDropdown.tsx index bb47bdecb..5efaf7b0c 100644 --- a/packages/design/src/FormManager/FormEdit/AddPatternDropdown.tsx +++ b/packages/design/src/FormManager/FormEdit/AddPatternDropdown.tsx @@ -14,7 +14,8 @@ import shortanswerIcon from './images/shortanswer-icon.svg'; import singleselectIcon from './images/singleselect-icon.svg'; import templateIcon from './images/template-icon.svg'; -const icons: Record = { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const icons: Record = { 'block-icon.svg': blockIcon, 'checkbox-icon.svg': checkboxIcon, 'date-icon.svg.svg': dateIcon, @@ -62,7 +63,7 @@ export const AddPatternDropdown = ({ uswdsRoot }: { uswdsRoot: string }) => { }, []); const getIconPath = (iconPath: string) => { - return Object.values(icons[iconPath])[0]; + return Object.values(icons[iconPath])[0] as string; }; return ( diff --git a/packages/design/src/FormManager/FormEdit/components/CheckboxPatternEdit.tsx b/packages/design/src/FormManager/FormEdit/components/CheckboxPatternEdit.tsx index 64655e213..e18ed7c8b 100644 --- a/packages/design/src/FormManager/FormEdit/components/CheckboxPatternEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/CheckboxPatternEdit.tsx @@ -25,7 +25,7 @@ const CheckboxPatternEdit: PatternEditComponent = ({ > ) : (
- +
)} diff --git a/packages/design/src/FormManager/FormEdit/components/FieldsetEdit.tsx b/packages/design/src/FormManager/FormEdit/components/FieldsetEdit.tsx index 5176941ff..76fd2b594 100644 --- a/packages/design/src/FormManager/FormEdit/components/FieldsetEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/FieldsetEdit.tsx @@ -40,7 +40,9 @@ const FieldsetPreview: PatternComponent = props => { <>
{pattern && pattern.data.patterns.length === 0 && ( -
+

diff --git a/packages/design/src/FormManager/FormEdit/components/FormSummaryEdit.tsx b/packages/design/src/FormManager/FormEdit/components/FormSummaryEdit.tsx index b06ede51b..01e9f11b3 100644 --- a/packages/design/src/FormManager/FormEdit/components/FormSummaryEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/FormSummaryEdit.tsx @@ -24,7 +24,7 @@ const FormSummaryEdit: PatternEditComponent = ({ > ) : (

- +
)} diff --git a/packages/design/src/FormManager/FormEdit/components/InputPatternEdit.tsx b/packages/design/src/FormManager/FormEdit/components/InputPatternEdit.tsx index 995b9bfc4..2c1f2fe7a 100644 --- a/packages/design/src/FormManager/FormEdit/components/InputPatternEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/InputPatternEdit.tsx @@ -26,7 +26,7 @@ const InputPatternEdit: PatternEditComponent = ({ > ) : (
- +
)} diff --git a/packages/design/src/FormManager/FormEdit/components/PageEdit.tsx b/packages/design/src/FormManager/FormEdit/components/PageEdit.tsx index 46632a303..24f93e16e 100644 --- a/packages/design/src/FormManager/FormEdit/components/PageEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/PageEdit.tsx @@ -14,7 +14,9 @@ import { PatternPreviewSequence } from './PreviewSequencePattern'; import styles from '../formEditStyles.module.css'; export const PageEdit: PatternEditComponent = props => { - const handleParentClick = (event: React.MouseEvent) => { + const handleParentClick = ( + event: React.MouseEvent + ) => { if (event.target === event.currentTarget) { // Trigger focus or any other action you want when the parent div is clicked event.currentTarget.focus(); @@ -98,4 +100,4 @@ const PageEditComponent = ({ pattern }: { pattern: PagePattern }) => {
); -}; \ No newline at end of file +}; diff --git a/packages/design/src/FormManager/FormEdit/components/ParagraphPatternEdit.tsx b/packages/design/src/FormManager/FormEdit/components/ParagraphPatternEdit.tsx index 9ce5cc181..02f0b23e7 100644 --- a/packages/design/src/FormManager/FormEdit/components/ParagraphPatternEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/components/ParagraphPatternEdit.tsx @@ -26,7 +26,7 @@ const ParagraphPatternEdit: PatternEditComponent = ({ > ) : (
- +
)} diff --git a/packages/design/src/FormManager/FormEdit/components/PreviewSequencePattern/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/components/PreviewSequencePattern/DraggableList.tsx index 035822ac5..e4a919791 100644 --- a/packages/design/src/FormManager/FormEdit/components/PreviewSequencePattern/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/components/PreviewSequencePattern/DraggableList.tsx @@ -41,7 +41,7 @@ export const DraggableList: React.FC = ({ return (
{ + onFocus={event => { // Stop onFocus events from bubbling up to parent elements. event.stopPropagation(); }} @@ -49,10 +49,10 @@ export const DraggableList: React.FC = ({ { + onDragStart={event => { setActiveId(event.active.id); }} - onDragEnd={(event) => { + onDragEnd={event => { const { active, over } = event; setActiveId(null); @@ -98,12 +98,8 @@ export const DraggableList: React.FC = ({ ); }; -const SortableItemOverlay = ({ - children, -}: { - children: React.ReactNode; -}) => { - const context = useFormManagerStore((state) => state.context); +const SortableItemOverlay = ({ children }: { children: React.ReactNode }) => { + const context = useFormManagerStore(state => state.context); return (
{ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id }); - const context = useFormManagerStore((state) => state.context); + const context = useFormManagerStore(state => state.context); return (
= ({ editComponent={} > ) : ( -
- -
+
+ +
)} ); diff --git a/packages/design/src/FormManager/index.tsx b/packages/design/src/FormManager/index.tsx index db0fc78ac..4145535a4 100644 --- a/packages/design/src/FormManager/index.tsx +++ b/packages/design/src/FormManager/index.tsx @@ -7,7 +7,12 @@ import { useSearchParams, } from 'react-router-dom'; -import { type FormConfig, createFormSession, nullSession } from '@atj/forms'; +import { + type FormConfig, + createFormSession, + nullSession, + defaultFormConfig, +} from '@atj/forms'; import { service } from '@atj/forms'; import { type ComponentForPattern } from '../Form'; @@ -28,22 +33,37 @@ import AvailableFormList, { } from '../AvailableFormList'; import styles from './FormEdit/formEditStyles.module.css'; -export type FormManagerContext = { +import { defaultPatternComponents, defaultPatternEditComponents } from '..'; + +export type PatternLessFormManagerContext = { baseUrl: `${string}/`; - components: ComponentForPattern; - config: FormConfig; - editComponents: EditComponentForPattern; formService: service.FormService; uswdsRoot: `${string}/`; urlForForm: UrlForForm; urlForFormManager: UrlForFormManager; }; +export type FormManagerContext = PatternLessFormManagerContext & { + config: FormConfig; + components: ComponentForPattern; + editComponents: EditComponentForPattern; +}; + type FormManagerProps = { - context: FormManagerContext; + //context: FormManagerContext; + context: PatternLessFormManagerContext; }; -export default function FormManager({ context }: FormManagerProps) { +export default function FormManager(props: FormManagerProps) { + // For now, hardcode the pattern React components. + // If these are user-configurable, we'll likely need to, in some manner, + // inject a compiled bundle into the application. + const context: FormManagerContext = { + ...props.context, + components: defaultPatternComponents, + config: defaultFormConfig, + editComponents: defaultPatternEditComponents, + }; return ( diff --git a/packages/design/src/FormRouter/index.tsx b/packages/design/src/FormRouter/index.tsx index ca50c04df..1ece77e0c 100644 --- a/packages/design/src/FormRouter/index.tsx +++ b/packages/design/src/FormRouter/index.tsx @@ -1,20 +1,29 @@ import React from 'react'; import { useParams, HashRouter, Route, Routes } from 'react-router-dom'; -import { service } from '@atj/forms'; +import { defaultFormConfig, service } from '@atj/forms'; import { createFormSession } from '@atj/forms'; -import Form, { type FormUIContext } from '../Form'; import { useQueryString } from './hooks'; +import { defaultPatternComponents } from '..'; +import Form, { FormUIContext } from '../Form'; // Wrapper around Form that includes a client-side router for loading forms. export default function FormRouter({ - context, + uswdsRoot, formService, }: { - context: FormUIContext; + uswdsRoot: `${string}/`; formService: service.FormService; }) { + // For now, hardcode the pattern configuration. + // If these are user-configurable, we'll likely need to, in some manner, + // inject a compiled bundle into the application. + const context: FormUIContext = { + config: defaultFormConfig, + components: defaultPatternComponents, + uswdsRoot, + }; return ( diff --git a/packages/design/src/index.ts b/packages/design/src/index.ts index c0eb5ede1..fd9ebfcdd 100644 --- a/packages/design/src/index.ts +++ b/packages/design/src/index.ts @@ -1,8 +1,8 @@ -import '@uswds/uswds'; +//import '@uswds/uswds'; export { default as AvailableFormList } from './AvailableFormList'; export { default as Form } from './Form'; export { defaultPatternComponents } from './Form/components'; -export { default as FormManager } from './FormManager'; +export { default as FormManager, type FormManagerContext } from './FormManager'; export { defaultPatternEditComponents } from './FormManager/FormEdit/components'; export { default as FormRouter } from './FormRouter'; diff --git a/apps/doj-demo/.gitignore b/packages/server/.gitignore similarity index 100% rename from apps/doj-demo/.gitignore rename to packages/server/.gitignore diff --git a/apps/doj-demo/.nvmrc b/packages/server/.nvmrc similarity index 100% rename from apps/doj-demo/.nvmrc rename to packages/server/.nvmrc diff --git a/packages/server/README.md b/packages/server/README.md new file mode 100644 index 000000000..640bfb6de --- /dev/null +++ b/packages/server/README.md @@ -0,0 +1,35 @@ +# @atj/server + +The form platform's web server. + +## Build + +The build consists of Astro's node.js adapter's output, as well as a constructor for running the web server with user-provided configuration. The build target produces both: + +```bash +pnpm build +``` + +## Development + +```bash +pnpm dev +``` + +## Usage example + +To start the provided Express server: + +```typescript +import { createServer } from '@atj/server/dist/index.js'; + +const port = process.env.PORT || 4321; + +const app = createServer({ + title: 'Example Form Service', +}); + +app.listen(port, () => { + console.log(`Server running on http://localhost:${port}`); +}); +``` diff --git a/apps/doj-demo/astro.config.mjs b/packages/server/astro.config.mjs similarity index 97% rename from apps/doj-demo/astro.config.mjs rename to packages/server/astro.config.mjs index 662ad374a..ca1aac85a 100644 --- a/apps/doj-demo/astro.config.mjs +++ b/packages/server/astro.config.mjs @@ -12,7 +12,7 @@ export default defineConfig({ trailingSlash: 'never', base: addTrailingSlash(process.env.BASEURL || ''), adapter: node({ - mode: 'standalone', + mode: 'middleware', }), integrations: [ react({ diff --git a/apps/doj-demo/package.json b/packages/server/package.json similarity index 69% rename from apps/doj-demo/package.json rename to packages/server/package.json index 06e607c06..1bb32792c 100644 --- a/apps/doj-demo/package.json +++ b/packages/server/package.json @@ -1,11 +1,13 @@ { - "name": "doj-demo", + "name": "@atj/server", "type": "module", "version": "0.0.1", + "main": "dist/server/index.js", "scripts": { "dev": "astro dev", "start": "astro dev", - "build": "astro check && astro build", + "build": "astro check && astro build && pnpm build:entry", + "build:entry": "tsup --dts --format esm src/index.ts", "preview": "astro preview", "astro": "astro" }, @@ -16,12 +18,14 @@ "@atj/design": "workspace:*", "@atj/forms": "workspace:*", "astro": "^4.10.3", + "express": "^4.19.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-error-boundary": "^4.0.12", "typescript": "^5.3.3" }, "devDependencies": { + "@types/express": "^4.17.21", "@types/react": "^18.2.62" } } diff --git a/packages/server/public/design b/packages/server/public/design new file mode 120000 index 000000000..32b8ef7c5 --- /dev/null +++ b/packages/server/public/design @@ -0,0 +1 @@ +../../../packages/design/storybook-static \ No newline at end of file diff --git a/apps/doj-demo/public/favicon.ico b/packages/server/public/favicon.ico similarity index 100% rename from apps/doj-demo/public/favicon.ico rename to packages/server/public/favicon.ico diff --git a/apps/doj-demo/public/favicon/android-chrome-192x192.png b/packages/server/public/favicon/android-chrome-192x192.png similarity index 100% rename from apps/doj-demo/public/favicon/android-chrome-192x192.png rename to packages/server/public/favicon/android-chrome-192x192.png diff --git a/apps/doj-demo/public/favicon/android-chrome-384x384.png b/packages/server/public/favicon/android-chrome-384x384.png similarity index 100% rename from apps/doj-demo/public/favicon/android-chrome-384x384.png rename to packages/server/public/favicon/android-chrome-384x384.png diff --git a/apps/doj-demo/public/favicon/android-chrome-512x512.png b/packages/server/public/favicon/android-chrome-512x512.png similarity index 100% rename from apps/doj-demo/public/favicon/android-chrome-512x512.png rename to packages/server/public/favicon/android-chrome-512x512.png diff --git a/apps/doj-demo/public/favicon/apple-touch-icon.png b/packages/server/public/favicon/apple-touch-icon.png similarity index 100% rename from apps/doj-demo/public/favicon/apple-touch-icon.png rename to packages/server/public/favicon/apple-touch-icon.png diff --git a/apps/doj-demo/public/favicon/favicon-16x16.png b/packages/server/public/favicon/favicon-16x16.png similarity index 100% rename from apps/doj-demo/public/favicon/favicon-16x16.png rename to packages/server/public/favicon/favicon-16x16.png diff --git a/apps/doj-demo/public/favicon/favicon-32x32.png b/packages/server/public/favicon/favicon-32x32.png similarity index 100% rename from apps/doj-demo/public/favicon/favicon-32x32.png rename to packages/server/public/favicon/favicon-32x32.png diff --git a/apps/doj-demo/public/favicon/favicon.ico b/packages/server/public/favicon/favicon.ico similarity index 100% rename from apps/doj-demo/public/favicon/favicon.ico rename to packages/server/public/favicon/favicon.ico diff --git a/packages/server/public/sample-documents b/packages/server/public/sample-documents new file mode 120000 index 000000000..edc7ca954 --- /dev/null +++ b/packages/server/public/sample-documents @@ -0,0 +1 @@ +../../../packages/forms/sample-documents \ No newline at end of file diff --git a/apps/doj-demo/public/uswds b/packages/server/public/uswds similarity index 100% rename from apps/doj-demo/public/uswds rename to packages/server/public/uswds diff --git a/packages/server/src/components/AppAvailableFormList.tsx b/packages/server/src/components/AppAvailableFormList.tsx new file mode 100644 index 000000000..90ab59322 --- /dev/null +++ b/packages/server/src/components/AppAvailableFormList.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; + +import { AvailableFormList } from '@atj/design'; +import { service } from '@atj/forms'; + +import { type AppContext } from '../context'; +import { getFormManagerUrlById, getFormUrl } from '../routes'; +import DebugTools from './DebugTools'; + +export default ({ ctx }: { ctx: AppContext }) => { + const formService = service.createBrowserFormService(); + return ( + + There was an unexpected error rendering the form list. + +
+ } + > + getFormManagerUrlById(ctx.baseUrl, formId)} + formService={formService} + urlForForm={formId => getFormUrl(ctx.baseUrl, formId)} + /> + + ); +}; diff --git a/packages/server/src/components/AppFormManager.tsx b/packages/server/src/components/AppFormManager.tsx new file mode 100644 index 000000000..8039c5426 --- /dev/null +++ b/packages/server/src/components/AppFormManager.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +import { FormManager } from '@atj/design'; +import { service } from '@atj/forms'; + +import { type AppContext } from '../context'; +import { getFormManagerUrlById, getFormUrl } from '../routes'; + +type AppFormManagerContext = { + baseUrl: AppContext['baseUrl']; + uswdsRoot: AppContext['uswdsRoot']; +}; + +export default function ({ ctx }: { ctx: AppFormManagerContext }) { + const formService = service.createBrowserFormService(); + return ( + getFormUrl(ctx.baseUrl, formId), + urlForFormManager: formId => getFormManagerUrlById(ctx.baseUrl, formId), + }} + /> + ); +} diff --git a/packages/server/src/components/AppFormRouter.tsx b/packages/server/src/components/AppFormRouter.tsx new file mode 100644 index 000000000..92042ecb0 --- /dev/null +++ b/packages/server/src/components/AppFormRouter.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import { FormRouter } from '@atj/design'; +import { service } from '@atj/forms'; + +import { type AppContext } from '../context'; + +export default function AppFormRouter({ + uswdsRoot, +}: { + uswdsRoot: AppContext['uswdsRoot']; +}) { + const formService = service.createBrowserFormService(); + return ; +} diff --git a/apps/doj-demo/src/components/DebugTools.tsx b/packages/server/src/components/DebugTools.tsx similarity index 100% rename from apps/doj-demo/src/components/DebugTools.tsx rename to packages/server/src/components/DebugTools.tsx diff --git a/apps/doj-demo/src/components/Footer.astro b/packages/server/src/components/Footer.astro similarity index 87% rename from apps/doj-demo/src/components/Footer.astro rename to packages/server/src/components/Footer.astro index f11a34214..a9e769999 100644 --- a/apps/doj-demo/src/components/Footer.astro +++ b/packages/server/src/components/Footer.astro @@ -1,11 +1,8 @@ --- -import { type GithubRepository, getBranchTreeUrl } from '../lib/github'; +import { getBranchTreeUrl } from '../lib/github'; -type Props = { - github: GithubRepository; -}; - -const { github } = Astro.props; +import { getAstroAppContext } from '../context'; +const { github } = getAstroAppContext(Astro); ---