Documentation for the RoundingWell frontend can be found within README.md files throughout this repo.
We use npm for our package manager
You will need Node.js. It is recommended that devs install nvm the node version manager. NVM allows you to change node versions on the fly.
Once NVM is installed, activate the right Node version with:
$ nvm useWith existing Git read access to RoundingWell/pkg-icons, install with:
$ npm ciReleases are tag-based. CircleCI publishes a release artifact from version tags, and deploys consume that artifact.
Deployment steps for local and CircleCI runs are documented in docs/deploy.md.
Allowed release sources:
- local branch
develop - local branch matching
release/*
Release command:
$ npm run releaseDry run (runs checks and prints the next tag without creating/pushing):
$ npm run release -- --dry-runTag format:
vYYMMDD.N(UTC date, sequence starts at1)- Example:
v260212.1
Tag immutability:
- release tags are treated as immutable
- existing remote release tags are never reused or moved
Release behavior changes:
- release no longer creates/pushes release branches
- release no longer commits
dist
All development work should branch off of and PR into the develop branch.
To develop against a remote AWS dev organization:
-
Deploy your backend organization (replace
johnwith your organization slug):bin/console deploy:dev john
-
After your first login, prepare a clinician account:
bin/remote <organization> console clinician:prepare <email>
For example, if your organization is
johnand your email isjohn.doe@roundingwell.com:bin/remote john console clinician:prepare john.doe@roundingwell.com
Create a .env file in the project root with your dev organization URL:
VITE_DEV_API_URL=https://john.roundingwell.devNote: Replace john with your organization slug.
There are two npm commands most useful for development:
Use this for local development with the Vite dev server against your remote care-ops-backend environment:
$ npm run devUse this to develop in the Cypress GUI:
$ npm testOccasionally the Vite server does not release the port, so development in either environment will use the wrong port and fail. To fix this, try:
$ npm stopIf this doesn't work try turning your computer off and then on again π
Follow AGENTS.md and the src/js guide for
local ownership, View, and DOM conventions. The
Marionette application context records
the installed integrations and how to retrieve version-matched framework API
docs with Marionette's upstream marionette plugin and skill. See the
agent tooling guide for setup.
- Backbone.Store A small but important library that ensures there is only a single instance of a model in memory. It is used for both server models and to sync state models across applications.
const MyModel = Backbone.Model.extend({...});
const MyUniqueModel = Backbone.Store(MyModel);
const myUniqueModel = new MyUniqueModel({ id: '1', foo: 'bar' });
const sameModel = new MyUniqueModel({ id: '1' });
sameModel.get('foo') === 'bar'; // true
const nonUnique = new MyModel({ id: '1' });
nonUnique.get('foo') === 'bar'; // false- Store.js A library for accessing localstorage across browsers
Add app icons to root icons.json, then build normally:
{ "far": ["check"], "fas": ["check"], "fal": ["acorn"], "fat": [] }flowchart LR
A["pkg-icons π"] --> B["App icons.json β inline SVG"]
npm ci uses your existing Git read access to the private
pkg-icons toolbox. No App setup is
needed locally. For SSH-only Git auth, configure this checkout once:
git config --local url."git@github.com:RoundingWell/pkg-icons.git".insteadOf \
https://github.com/RoundingWell/pkg-icons.git
npm ciCI uses HTTPS with node scripts/install-icons-ci.mjs. A small, scripts-disabled
public bootstrap loads Octokit for GitHub App authentication.
CircleCI supplies PKG_ICONS_APP_CLIENT_ID, PKG_ICONS_APP_INSTALLATION_ID and
PKG_ICONS_APP_PRIVATE_KEY_BASE64. Encode the downloaded RSA PEM on macOS:
base64 < /path/to/app-private-key.pem | tr -d '\r\n' | pbcopySave the clipboard as PKG_ICONS_APP_PRIVATE_KEY_BASE64 in CircleCI. The bootstrap
decodes it in memory and mints a short-lived pkg-icons-only Contents: read token.
Invalid credentials fail before installation; keys never reach install hooks.
This app pins an immutable @roundingwell/icons revision in package-lock.json.
That revision currently contains Font Awesome 7.2.0 (7.2.0-rw.0). Only selected
manifest icons enter the browser bundle; ordinary installs make no FontAwesome
requests. Catalog, provenance and update instructions live in the toolbox README.
Handlebars templates and stylesheets should be imported directly into the modules they're used. Handlebars can also be made inline using the ``hbs```` template literal
import CompiledTemplate from './template-file.hbs';
import 'some-styles.scss';
const OtherTemplate = hbs`
<div class="other-template">
This multi-line template will be precompiled during the build process.
</div>
`;Feature Flags are intended to protect users from new code that isn't fully baked or to allow for gradual rollout. Right now we have one flag for development purposes.
if (_DEVELOP_) {
// new code
}Flags are best used such that a minimal amount of changes are made when the flag is being removed.
// Bad
function foo() {
if (flag) {
doNew();
} else {
doOld();
}
}
// Good
function foo() {
if (!flag) {
doOld();
return;
}
doNew();
}It also may be better to duplicate larger areas of code for fewer easier to remove flags.
// Bad
function foo() {
if (flag) foo();
bar();
baz();
if (!flag) bazinga();
quxx();
}
// Good
function foo() {
if (!flag) {
bar();
baz();
bazinga();
quxx();
return;
}
foo();
bar();
baz();
quxx();
}Outside of linting there are some recommendations for code standards that will help in long term maintenance.
- SASS follows a general BEM format. Ideally do not make deep elements, but start a new block if additional descriptors are needed.
- Favor object composition over class inheritance
- Within reason functions should ideally accomplish one task in less than 10 lines unless logically trivial. If it is getting to big, break up the function.
- Similarly modules should ideally get no larger than 300 lines or so. This is a general guideline and not a rule.
- Use only .js- prefixed selectors if at all possible from the code. Do not use style classes, ids, or tagnames if it can be avoided.
- Define template element selectors in a View's
uihash and access them withgetUIrather than querying selectors from View methods. - The view should have say over only the DOM inside its own template or in the case of a CollectionView sometimes its direct children. Avoid allowing deep reaching within the DOM or anything external changing the DOM besides the view itself.
- Anything AJAX should happen within the entities service only.
- Generally it is better to store state on a state model than to append a property to an instance.
- Events and handlers should be named
verb:subjectorcontext:verb:subjectbased on what happened not what will happen ie:
triggers: {
'click .js-button1': 'show:modal' // bad
'click .js-button2': 'click:button2' // good
},
childViewTriggers: {
'click:button': 'button:clicked', // bad
'click:button': 'listItem:click:button' //good
},
onShowModal() {
console.log('The naming of this handler suggest a modal was just shown');
},
onClickButton2() {
this.showModal(); // It's ok for a handler to simply call a single action
}Use guards to handle the exception on functions when possible ie:
// Good
doFoo(options) {
if (!options.bar) {
this.doSomethingElse();
return;
}
return 'Foo:' + options.bar;
}
// Bad
doFoo(options) {
if (options.bar) {
return 'Foo:' + options.bar
} else {
this.doSomethingElse()
}
}It is our intention to open source by default. Ideally any generic solution can be extracted, well documented, and tested. Open sourcing encourages better code, collaboration with outside developers, and potentially free battle-testing, bugfixes and features from the public.
Libraries for public consumption are licensed with the MIT License.
Currently our OS projects are available mainly at https://github.com/RoundingWellOS
Each project contains its own documentation for contributions.
Additionally we actively encourage contributing to other projects. Don't know where to start? Look at documentation or tests for any of the libraries we use.