# Project Manager

## Workstation SPA
`frontend-distribution` is part of the workstation single page application. Read up on the framework and tooling by visiting the [frontend-workstation](https://github.com/theorchard/frontend-workstation) repo.

## Setup

Runtime and package manager versions are declared in `package.json` (`engines.node`, `packageManager`) and `.nvmrc`. Those are the source of truth, refer to them instead of hardcoded numbers here.

```bash
nvm use              # picks the node version from .nvmrc
corepack enable pnpm # activates the pnpm version pinned by packageManager
cp .env.shadow .env  # initialize environment configuration
```

Note: if you switch node versions, clear out old `node_modules` and re-run `pnpm install`.

Then:
```bash
pnpm install # installs all pnpm-lock.yaml dependencies or package.json dependencies if no pnpm-lock.yaml is present
pnpm bootstrap_locale # prerequisite to start local dev server - creates messages.json files in all `locale/<language>/LC_MESSAGES/`
pnpm start # starts dev server
```

## Local development, auth and feature flags
Local-dev setup, auth and feature-flag testing are documented in the workstation shell: [frontend-workstation / Local development](https://github.com/theorchard/frontend-workstation/blob/master/docs/local-development.md).

The old `GRASS_TOKEN`, `USER_FEATURES` and `USER_RESTRICTIONS` `.env` knobs are gone. To test a given vendor state, impersonate a vendor that already has it, using the grant-label tooling documented in [qa-automation-tool](https://github.com/theorchard/qa-automation-tool).

## Development

### Tasks

* `pnpm bootstrap_locale` pre-requisite to run local development server - creates messages.json with "{}" as the content in all `<language>/LC_MESSAGES/` folders so local development server can start
* `pnpm start` runs local development server at localhost:8080
* `pnpm test` to run the linter and unit tests (run with SOURCE_MAPS=true for webpack source maps)
* `pnpm lint` to run only the linter
* `pnpm lint:css` to only lint SCSS files
* `pnpm lint:js` to only lint Javascript files
* `pnpm test:unit` to run only the unit tests
* `pnpm watch` to run unit tests every time a change is saved
* `pnpm build` bundles all application js into build/bundle.js

Note: To run a subset use something like:
`NODE_ENV=test NODE_PATH=. jest -u project-highlights --config=jest.config.json`
only add the `-u` to update the snapshot

Note: to see all available tasks, run `pnpm run`.

### Working with internationalization

We define all messages in folder `i18n` using message [descriptors](https://github.com/yahoo/react-intl/wiki/Components#message-descriptor). A message descriptor's description property is optional.

We wrap our map of message descriptors with `defineMessages` so our babel plugin `babel-plugin-react-intl` can find them. We use `babel-plugin-react-intl` aggregate
all of our application's i18n text so it can be exported for translation.

`defineMessages` returns the object it is called with unmodified i.e.: object => object

```
import { defineMessages } from 'react-intl';
export default defineMessages({
    header: {
        defaultMessage: 'Digital Product Form',
        id: 'digital-product-form.header'
    }
});
```

#### Loading other languages

1. Grab the latest translated strings.
    1. Go to the `frontend-distribution-bundle-deploy` job. This job is part of the `frontend-distribution` Jenkins deploy piepline.
    2. Go to the job's workspace.
    3. Go to the locale folder.
    4. Download the files as a zip file.
    5. If this folder has no files in it, the workspace may have been cleared. Rerun the job and when it finishes there should be a `messages.json` file in each folder.
2. Unzip the file and place the items into the [locale](/locale) folder. Replace any files that already exist.
3. Make the application load a different language.
    1. Go to `webpack.config.dev.js` file and find the `localizationPlugin`.
        ```javascript
        const localizationPlugin = new webpack.DefinePlugin({
            'process.env.LOCALE_MESSAGES': JSON.stringify({
                en: webpackInternationalizationHelpers.getMessagesForLocale('en'),
            }),
        });
        ```
    2. Change the argument of `getMessagesForLocale` to the language you want. Example:
        ```javascript
        getMessagesForLocale('ja') // For Japanese language.
        ```
    3. (Optional) If you need accurate pluralization and time displays you will have to load the Common Locale Data Repository (CLDR) for that language.
        1. Instead of modifying the existing entry add a new entry for the language you want.
            ```javascript
            const localizationPlugin = new webpack.DefinePlugin({
                'process.env.LOCALE_MESSAGES': JSON.stringify({
                   en: webpackInternationalizationHelpers.getMessagesForLocale('en'),
                   ja: webpackInternationalizationHelpers.getMessagesForLocale('ja'), // Add your desired language here.
                }),
            });
            ```
        2. Go to the [html layout](src/applications/index.layout.html.pug) file and set the `ORCHARD_LOCALE` on the `window`.
            ```javascript
            window.ORCHARD_LOCALE = 'ja';
            ```

### Developer Tools
* [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
* [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)

### `.env` variables
We define some variables inside .env file and use them with [dotenv](https://www.npmjs.com/package/dotenv) package before bundling any frontend application.

Variable | Description | Example
-------- | ----------- | -------
`APPLICATION_NAME`|Determines which application (entry point in webpack config) should be in `main.bundle.js` and rendered in standalone mode. By default it is set with `project-manager` value, but can have any application name defined in src/applications folder.|

### Feature Flags

See [FEATURES.md](FEATURES.md)


### Troubleshooting
If you are getting a 401 unauthorized error when running pnpm, you may need a packagecloud token.
  * Copy the org-wide packagecloud token from a teammate and append `export PACKAGECLOUD_TOKEN=replace_me` in .zshrc or relevant file
  * This should get picked up in .npmrc next time you run `pnpm install`
