Skip to content

Commit

Permalink
Merge branch 'main' into wml-test-api-jwt-access
Browse files Browse the repository at this point in the history
  • Loading branch information
macrael committed Jan 25, 2024
2 parents 6c9cca9 + 2d4897a commit c3bc752
Show file tree
Hide file tree
Showing 131 changed files with 7,975 additions and 8,845 deletions.
4 changes: 2 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/bash
. "$(dirname "$0")/_/husky.sh"

# In a continuing effort to print errors when they are needed, we check for
# all pre-commit dependency requirements here.
# In a continuing effort to print errors when they are needed, we check for
# all pre-commit dependency requirements here.
requirements=("protolint" "shellcheck" "detect-secrets")

for req in "${requirements[@]}"; do
Expand Down
Binary file added .images/contract-and-rate-history-diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions dev_tool/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
]
},
"dependencies": {
"@aws-sdk/client-cloudfront": "^3.450.0",
"@aws-sdk/client-ec2": "^3.441.0",
"@aws-sdk/client-secrets-manager": "^3.441.0",
"@aws-sdk/client-cloudfront": "^3.485.0",
"@aws-sdk/client-ec2": "^3.485.0",
"@aws-sdk/client-secrets-manager": "^3.485.0",
"node-ssh": "^13.1.0",
"yargs": "^17.2.1"
},
Expand Down
38 changes: 32 additions & 6 deletions docs/technical-design/contract-rate-change-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@ Change history is the feature of MC-Review where the application stores full cop

This document details how the change history is calculated for contract and rate data and which database fields are used.

## Diagram
[Miro link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764574794469060&cot=14)\
![contract-and-rate-history-diagram](../../.images/contract-and-rate-history-diagram.png)

In this diagram when a contract or rate is unlocked, a new draft revision version is created from the previous submitted revision. When submitted the draft revision is turned into a submitted revision that is then a part of the revision history.

### Reading history
[Miro Link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764574799194467&cot=14)\
![reading-contract-history](../../.images/read-contract-and-rate-history-diagram.png)

#### Example 1
In example 1, we are fetching the contract data on 1/20/2024 (pretend that proceeding actions have not occurred yet).
On this date, the contract has been unlocked and Rate B was removed from the contract.
When unlocking a contract or rate, a new draft revision is made. Any changes made to the contract or rate is reflected in these draft revisions.
Until the contract or rate is submitted, the draft revision will remain in the data when we fetch.
So when fetching on the unlocked contract on 1/20/2024 the data will return with a draft revision for the contract, then the revision history in reverse order.

#### Example 2
In example 2, we are fetching the contract on 1/21/2024 in a submitted state.
In this example there are no draft revisions, so the data returned is just the revision history.
You will notice that in at this date and time the contract, Contract Rev 4, that was in draft state on 1/20/2024 is no longer in draft state and now in the contract history column. When a contract or rate that is unlocked gets resubmitted its drafts are turned into a historical revision.

## Contraints
- MC-Review must track version history once a contract or rate is submitted.
- This includes all actions on contract or a rate (submit, unlock, resubmit) alongside the related form data present at that point in time in the database.
Expand All @@ -30,18 +52,22 @@ At the Postgres Table level, draft revisions and submitted revisions live in the
The list of revisions returned from prisma is run through [Zod](https://zod.dev/) to return [domain mode types](../../services/app-api/src/domain-models/contractAndRates). This is initiated by the `*WithHistory` database functions. See [parseContractWithHistory](../../services/app-api/src/postgres/contractAndRates/parseContractWithHistory.ts) and [parseRateWithHistory](../../services/app-api/src/postgres/contractAndRates/parseRateWithHistory.ts).

#### Contract History
- **Below a temporary approach to finding the contract history. The correct way to build the actual contract and rate history will be done in the [Rate Change History epic](https://qmacbis.atlassian.net/browse/MCR-3607)**
- `parseContractWithHistory` takes our prisma contract data and parses into our domain `ContractType`. In `ContractType` the `revisions` is an array of **contract** **revisions**; this is the contract history.
- `revisions` differs from `draftRevision` in the `ContractType`. The `draftRevision` is a singular revision that is not submitted and this data has no historical significance until it is submitted. Most of the data in this revision can be updated.
- Each **contract revision** in `revisions` is submitted and retains data at the time of the submission. These revision's data will never be updated to retain its historical integrity.
- An important note about the `rateRevisions` field in each contract revision in `revision`.
- Like contracts, rates also have **rate revisions** which are used to construct a rate history through submissions, but the purpose of `rateRevisions` on a contract revision is not for rate history.
- The purpose of `rateRevisions` is to retain the data of a rate linked to this contract revision at the time of submission.
- For that we need the single rate revision that was submitted at the time this contract revision was submitted.
- Like contracts, rates also have **rate revisions** which are used to construct a rate history through submissions, **but the purpose of `rateRevisions` on a contract revision is not for rate history**.
- The purpose of `rateRevisions` is to retain the latest data of a rate linked to this contract revision before the proceeding contract revision.
- For that we need the single rate revision that was submitted before the proceeding contract revision was unlocked.
- Here are some guidelines for each rate revision in `rateRevisions` of a contract revision.
- Rate can be unlocked and resubmitted independently of the contract. This means that for a rate that belongs to a contract, the number of rate revisions on that contract revision is not 1-to-1.
- If a contract is submitted with a rate, that rate can be unlocked and resubmitted many times so there would be many revisions.
- Each revision would belong to that contract revision up until proceeding contract revision, where it would be a new point in the contract history.
- This will retain the latest rate data up until the next point in the contract history and ensure that when fetching a contract, the correct rate data will be returned.
- Each rate revision in `rateRevisions` is unique by rate id, meaning there will never be two rate revisions with the same rate id in `rateRevisions`
- Each rate revision is the latest submitted up till the contract revision submitted time.
- Like contract revision, rate revision is read only and cannot be updated to retain its historical integrity.

- Each rate revision is the latest submitted up till the proceeding contract revision unlocked time.
- If the rate revision has a `true` value for the field `isRemoval` then, it is not included in the contract. This field signifies that the rate has been removed from the contract.

*Dev Note*: If the `draftRevision` field has a value and the `revisions` field is an empty array, we know the Contract or Rate we are looking at is an initial draft that has never been submitted.

Expand Down
11 changes: 7 additions & 4 deletions docs/technical-design/howto-migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ This type of migration is run as standalone lambda that developers must manually
- Start with DEV. Follow similar steps Step #4 but now using the `main` lambda for your migration.
- Run the migration DEV > VAL > PROD in order, verifying in the application (or via reporting output) after each run.

## How to dump VAL data for local testing
## How to dump deployed data for local testing

1. use `./dev jumpbox clone val` to clone the val database to your local machine
1. Connect to Aurora Postgres via AWS Jump Box. [Instructions](../../services/postgres/README.md#access-to-aurora-postgres-via-aws-jump-box)

2. Load that db dump into your local running postgres instance
- `pg_restore -h localhost -p 5432 -U postgres -d postgres --clean val-[date].sqlfc`. You will be promoted to enter in local db password `shhhsecret`. You will see print out errors but the database has spun up successfully.
2. Use `./dev jumpbox clone [environment]` to clone the environment database to your local machine. This command will log into the jumpbox, dump the db into a file in the format `dbdump-[environment]-[date].sqlfc`, and copy that file locally.

2. Load that db dump into your local running postgres instance.
- Copy the dump file to the `mc-postgress` docker container by running the command `docker cp dbdump-[env]-[date].sqlfc mc-postgres:/` from where the file is located.
- Then run the command `docker exec -it mc-postgres pg_restore -h localhost -p 5432 -U postgres -d postgres --clean dbdump-[env]-[date].sqlfc`. You will be promoted to enter in local db password `shhhsecret`. You will see print out errors but the database has spun up successfully.
105 changes: 105 additions & 0 deletions docs/technical-design/howto-style-css-scss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# How to style with CSS and SCSS

## Colors

MC-Review has an application specific color palette written in SCSS. All color variables in the palette are prefixed with `$mcr-`. The palette is viewable in Storybook as well (`Global/Colors`). Anytime you need a color prefer the variable - e.g. $mcr-gold-base. Avoid using color hex codes directly or using random design system variables for color.

The colors variables are defined in `styles/mcrColors.scss`. By reusing color variables from one place, we make future refactors easy and reduce styles tech debt. For example, if we needed to add a dark mode in the application or do a re-design, we start from one place. Note that we have colors in the application coming from both USWDS and CMDS currently in the application. These patterns are easier to see when our colors are defined in one place.

## Containers

Containers are the presentational elements that position content on the page. Look at designs and note the background color,the overall width of the content, and any obvious gutters between or margin/padding around content.

We currently have ~three types of containers in the application. See our `custom.scss` for scss variables and mixins related to containers. Whenever you create a new page, one of your first considerations should be the container, making sure it is using `flex`, and determining which type of container you need. Make sure your container stretches the height and width you expect by expanding and shrinking the viewport and seeing how content inside behaves. There should not be gaps, for example, between the bottom of the page container and the footer. Also note the background color of the container and the margin. If areas have a lot of gray space, that is likely the base color of our main HTML document body. If the background looks white, that's probably `$mcr-foundation-white`.

## Text

Make sure heading levels (`h2`, `h3` etc) are properly used for text content. There are clear [guidelines](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements) around heading levels to follow. For example, page titles should always have some kind of heading, use only one h1 per page, headings should be nested by level, etc. If the heading is not styled the way you expect by default, CSS can be used to override things like font weight, size, etc. If you are noticing something with heading that need to be overridden across the app, this likely calls for global styles.

Note also that there is a specific color to be used for links (`$$mcr-foundation-link`) and hint text (`$mcr-foundation-hint`).

## Technologies related to styles in MC-Review

### Sass / SCSS stylesheets

[Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html) is the way we write styles in the project. It is an extension of CSS. All files that `.scss` extension use Sass. Some basic concepts of Sass that are good to understand/review that are listed below.

- How to [load SCSS](https://sass-lang.com/documentation/at-rules/use#loading-members)
- How to [use nested selectors](https://sass-lang.com/documentation/style-rules#nesting)
- How to [structure a Sass stylesheet](https://sass-lang.com/documentation/syntax/structure)

### United States Web Design System

See the ADR on [`Use USWDS as the design system`](../architectural-decision-records/014-use-uswds-design-system.md).

What this means for styling the application is that you will see some USWDS language and patterns. This can also be used a common language between design and engineering. For example, the names of our components follow [USWDS names for components](https://designsystem.digital.gov/components/overview/). And when you look at our application in the dev tool, every class with `usa-*` in front of it is coming from USWDS. USWDS has [design tokens](https://designsystem.digital.gov/design-tokens/) and mixins we can rely on as well.

## Style patterns in MC-Review

### Styles should be as narrowly scoped as possible

This is 101 but easy to forget. Please read [this section](https://github.com/trussworks/Engineering-Playbook/blob/main/docs/web/frontend/developing-ui.md#style-with-css-modules) of the Truss eng playbook for a good summary.

TL;DR Less is more with styles. In our application, the preferred way to style React code is via locally scoped [CSS module](https://github.com/css-modules/css-modules), written as a `<component>.module.scss` file. This is stored alongside React component files. We also use [CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference#selectors) to further target styles. Tightly scoped styles and CSS [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) ensure separation of concerns.

Example of scoped styles in use:
- Shared styles live close to the workflow they apply to. For example, directories in `/pages` folder may share a `*.module.scss` stylesheet if needed for templates in that area of the application. CSS selectors should be used to further scope down styles.
- Re-useable atomic components (see `/components` folder) have self contained styles. There is a named `*.module.scss` file for each component.


### Global styles live in `styles/custom.scss`

Global styles should be uncommmon. They generally change only during a styles refactor across the application.

The `styles/custom.scss` is also the main file imported into components to reference global SCSS variables. This file `@forward`s the MCR color palette and USWDS sass variables to the rest of the application.

### Import styles with `@use`
- Prefer namespaced scss imports with [`@use`](https://sass-lang.com/documentation/at-rules/use/) over [`@import`](https://sass-lang.com/documentation/at-rules/import/) for scss to reduce loading styles multiple times. Sass team is deprecating [`@import`](https://github.com/sass/sass/blob/main/accepted/module-system.md#timeline).

In `*.module.scss` files this looks like (at top of file):
```
@use '../../styles/custom.scss' as custom;
@use '../../styles/uswdsImports.scss' as uswds;
```

and then referring to varibles and mixins inline with the [namespace](https://sass-lang.com/documentation/at-rules/use/#choosing-a-namespace) - such as `custom.$mcr-foundation-white` or `@include uswds.uswds-at-media(tablet)`

### Watch out for global style overrides that can impact UI across the application.

Always nest your scss styles code in a css class to benefit from [the advantages of CSS/SCSS modules](https://css-tricks.com/css-modules-part-1-need/). Eencapsulates styles in classes throughout `[component].module.scss`. Do not use html and `usa-*` class overrides at the top level of the module files. This will override global styles across the application.

If you must, make global overrides changes in (`overrides.scss`). Here are concrete examples where global style overrides are needed:

1. We are dealing with container elements that repeat throughout the application outside of a specific component (divs, cards, display tables)
2. We need override a behavior in USWDS that we can't control via settings throughout the application
3. We want to hide an element from the screen using our global screenreader only class


### Compose together styles in React component files using the `classnames` package

- Sometimes React components have complex logic related to styles. To assist with this and follow patterns from `@trussworks/react-uswds` we use [`classnames`](https://github.com/JedWatson/classnames) package to compose together styles from different places. In the future if desired, we could make a similar utility in code and remove this dependency.

Example of complex conditional styles from ActionButton:

```react
const classes = classnames(
{
'usa-button--outline-disabled': isDisabled && isOutline,
'usa-button--disabled': isDisabled,
'usa-button--active': isLoading && !isSuccess,
[styles.successButton]: isSuccess && !isDisabled,
[styles.disabledCursor]: isDisabled || isLoading,
},
className
)
```

In this example, ActionButton has different states (loading, disabled,success) that can be combined and there are is secondary visual variant (outline) to consider.

The `'usa-button---'` classes are string literals for the class coming directly from USWDS. We want to use these in some cases. Then there are variables like `styles.disabledCursor` which come from the component module SCSS file. Finally, there is the `className` is coming from React props passed into the component from the parent. Ut is a best practice is to apply any consumer defined `className` styles last in re-useable components.

The logic can be understood as

1. USWDS styles are conditionally applied
2. component specific styles from the module `styles` object are conditionally applied
3. `className` prop is applied to all instances of the component (also overriding anything applied earlier if styles reference to the same CSS attribute).
4 changes: 2 additions & 2 deletions docs/technical-design/resovler-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Many of these functions are accessible from the resolver via [dependency injecti
Errors from these functions propagate up to the resolver where it will be handled and a response sent to the client. See docs about [error handling](error-handling.md) for details.

### Diagram
[Miro link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764573512051070&cot=14)
[Miro link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764573512051070&cot=14)\
![resolver-design-diagram](../../.images/resolver-design-diagram.png)

## General Guidance
Expand All @@ -34,7 +34,7 @@ Resolvers are passed Postgres handlers via [dependency injection](design-pattern

The diagram below is the data flow diagram for `createHealthPlanPackage` resolver.

[Miro link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764573517610448&cot=14)
[Miro link](https://miro.com/app/board/o9J_lS5oLDk=/?moveToWidget=3458764573517610448&cot=14)\
![postgres-handler-diagram](../../.images/postgres-handler-diagram.png)

Form the diagram above, you can see that `createHealthPlanPackage` resolver calls `insertDraftContract` handler function in the Postgres Module to create a new draft contract.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"devDependencies": {
"@bahmutov/cypress-esbuild-preprocessor": "^2.2.0",
"@cypress-audit/pa11y": "^1.3.0",
"chromedriver": "^119.0.1",
"chromedriver": "^120.0.1",
"cypress": "^12.16.0",
"cypress-pipe": "^2.0.0",
"danger": "^11.2.6",
Expand Down
3 changes: 2 additions & 1 deletion scripts/destroy_stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ListObjectVersionsCommand,
DeleteObjectsCommand,
PutBucketVersioningCommand,
PutBucketVersioningCommandInput,
} from '@aws-sdk/client-s3'

const AWSConfig = {
Expand Down Expand Up @@ -234,7 +235,7 @@ async function turnOffVersioningOnBucket(
`Turning off bucket versioning on bucket: ${bucket.PhysicalResourceId}`
)

const versionParams = {
const versionParams: PutBucketVersioningCommandInput = {
Bucket: bucket.PhysicalResourceId ?? '',
VersioningConfiguration: { Status: 'Suspended' },
}
Expand Down
Loading

0 comments on commit c3bc752

Please sign in to comment.