@@ -151,7 +157,7 @@ function RingdownForm({ className }) {
onPrimary={handleConfirmCancel}
/>
)}
-
+
)}
{ringdowns && ringdowns.length > 0 && (
diff --git a/src/Models/Ringdown.js b/src/Models/Ringdown.js
index 05851ae7..ca6020f5 100644
--- a/src/Models/Ringdown.js
+++ b/src/Models/Ringdown.js
@@ -1,69 +1,73 @@
+// eslint-disable func-names
import { DateTime } from 'luxon';
import PropTypes from 'prop-types';
import { PatientFieldData, ValidationState } from './PatientFieldData';
-
-const DeliveryStatus = {
- RINGDOWN_SENT: 'RINGDOWN SENT',
- RINGDOWN_RECEIVED: 'RINGDOWN RECEIVED',
- RINGDOWN_CONFIRMED: 'RINGDOWN CONFIRMED',
- ARRIVED: 'ARRIVED',
- OFFLOADED: 'OFFLOADED',
- OFFLOADED_ACKNOWLEDGED: 'OFFLOADED ACKNOWLEDGED',
- RETURNED_TO_SERVICE: 'RETURNED TO SERVICE',
- CANCELLED: 'CANCELLED',
- CANCEL_ACKNOWLEDGED: 'CANCEL ACKNOWLEDGED',
- REDIRECTED: 'REDIRECTED',
- REDIRECT_ACKNOWLEDGED: 'REDIRECT ACKNOWLEDGED',
-};
-
-DeliveryStatus.ALL_STATUSES = Object.values(DeliveryStatus);
-
-DeliveryStatus.is = (status, target) => DeliveryStatus.ALL_STATUSES.indexOf(status) >= DeliveryStatus.ALL_STATUSES.indexOf(target);
-
-Object.freeze(DeliveryStatus);
+import * as metadata from '../shared/metadata';
+import convertToPropType from '../shared/convertToPropType';
+import DeliveryStatus from '../shared/constants/DeliveryStatus';
+
+// define the fields that must all have valid input to make the ringdown valid. the second array item is an optional function to determine
+// whether the field's current value is valid as input. by default, the field is counted as having input if its value is truthy. the
+// array order should be the same as the field order in PatientFields.
+const validatedFields = [
+ ['ambulanceIdentifier'],
+ ['dispatchCallNumber'],
+ ['emergencyServiceResponseType'],
+ ['age'],
+ ['sex'],
+ ['chiefComplaintDescription'],
+ ['stableIndicator', (value) => typeof value === 'boolean'],
+ ['all', () => ValidationState.NO_INPUT],
+];
+
+// define the names of the objects that will be added to the Ringdown payload property, and the list of its fields for which getters/setters
+// will be added. if the object name is an array, the second string is used as the object name.
+const payloadModels = [
+ ['ambulance', ['ambulanceIdentifier']],
+ [['emergencyMedicalServiceCall', 'emsCall'], ['dispatchCallNumber']],
+ // we want to expose the hospital id field under a different name, so we'll define it in the class below instead of here
+ ['hospital', []],
+ ['patient', metadata.patient.getObjectFields()],
+ ['patientDelivery', ['etaMinutes', 'currentDeliveryStatus']],
+];
+
+// build a hash with an empty default object for each sub-object in the payload
+function createDefaultPayload() {
+ const emptyPayload = payloadModels.reduce((result, [name]) => {
+ const objectName = name instanceof Array ? name[1] : name;
+ result[objectName] = {};
+ return result;
+ }, {});
+
+ return {
+ ...emptyPayload,
+ // default the urgency to Code 2 for a fresh ringdown if the Code 3 option has been disabled
+ patient: (window.env.REACT_APP_DISABLE_CODE_3 && { emergencyServiceResponseType: 'CODE 2' }) || {},
+ };
+}
class Ringdown {
static get Status() {
return DeliveryStatus;
}
+ static ascendingByOrder(a, b) {
+ if (a.order < b.order) {
+ return -1;
+ }
+ if (a.order === b.order) {
+ return 0;
+ }
+ return 1;
+ }
+
constructor(payload, validationData) {
- this.payload = payload || {};
- this.payload.ambulance = this.payload.ambulance || {};
- this.payload.emsCall = this.payload.emsCall || {};
- this.payload.hospital = this.payload.hospital || {};
- this.payload.patient = this.payload.patient || {};
- this.payload.patientDelivery = this.payload.patientDelivery || {};
- this.validationData = validationData || {
- ambulanceIdentifier: new PatientFieldData(
- 'ambulanceIdentifier',
- 0,
- this.ambulanceIdentifier ? ValidationState.INPUT : ValidationState.NO_INPUT
- ),
- dispatchCallNumber: new PatientFieldData(
- 'dispatchCallNumber',
- 1,
- this.dispatchCallNumber ? ValidationState.INPUT : ValidationState.NO_INPUT
- ),
- age: new PatientFieldData('age', 2, this.age ? ValidationState.INPUT : ValidationState.NO_INPUT),
- sex: new PatientFieldData('sex', 3, this.sex ? ValidationState.INPUT : ValidationState.NO_INPUT),
- emergencyServiceResponseType: new PatientFieldData(
- 'emergencyServiceResponseType',
- 4,
- this.emergencyServiceResponseType ? ValidationState.INPUT : ValidationState.NO_INPUT
- ),
- chiefComplaintDescription: new PatientFieldData(
- 'chiefComplaintDescription',
- 5,
- this.chiefComplaintDescription ? ValidationState.INPUT : ValidationState.NO_INPUT
- ),
- stableIndicator: new PatientFieldData(
- 'stableIndicator',
- 6,
- typeof this.stableIndicator === 'boolean' ? ValidationState.INPUT : ValidationState.NO_INPUT
- ),
- all: new PatientFieldData('all', 7, ValidationState.NO_INPUT),
+ this.payload = {
+ ...createDefaultPayload(),
+ ...payload,
};
+
+ this.setValidationData(validationData);
}
clone() {
@@ -79,40 +83,9 @@ class Ringdown {
return this.payload.id;
}
- // Ambulance
-
- get ambulance() {
- return this.payload.ambulance ?? {};
- }
-
- get ambulanceIdentifier() {
- return this.payload.ambulance.ambulanceIdentifier ?? '';
- }
-
- set ambulanceIdentifier(newValue) {
- this.payload.ambulance.ambulanceIdentifier = newValue;
- }
-
- // EMS Call
-
- get emsCall() {
- return this.payload.emsCall ?? {};
- }
-
- get dispatchCallNumber() {
- return this.payload.emsCall.dispatchCallNumber ?? '';
- }
-
- set dispatchCallNumber(newValue) {
- this.payload.emsCall.dispatchCallNumber = newValue;
- }
-
// Hospital
- get hospital() {
- return this.payload.hospital ?? {};
- }
-
+ // special-case this field, since the field name (id) is getting mapped to a different name on the Ringdown (hospitalId)
get hospitalId() {
return this.payload.hospital.id ?? null;
}
@@ -123,115 +96,6 @@ class Ringdown {
// Patient Info
- get age() {
- return this.payload.patient.age ?? null;
- }
-
- set age(newValue) {
- this.payload.patient.age = newValue;
- }
-
- get sex() {
- return this.payload.patient.sex ?? null;
- }
-
- set sex(newValue) {
- this.payload.patient.sex = newValue;
- }
-
- get emergencyServiceResponseType() {
- return this.payload.patient.emergencyServiceResponseType ?? null;
- }
-
- set emergencyServiceResponseType(newValue) {
- this.payload.patient.emergencyServiceResponseType = newValue;
- }
-
- get chiefComplaintDescription() {
- return this.payload.patient.chiefComplaintDescription ?? null;
- }
-
- set chiefComplaintDescription(newValue) {
- this.payload.patient.chiefComplaintDescription = newValue;
- }
-
- get stableIndicator() {
- return this.payload.patient.stableIndicator ?? null;
- }
-
- set stableIndicator(newValue) {
- this.payload.patient.stableIndicator = newValue;
- }
-
- // Vitals
-
- get systolicBloodPressure() {
- return this.payload.patient.systolicBloodPressure ?? null;
- }
-
- set systolicBloodPressure(newValue) {
- this.payload.patient.systolicBloodPressure = newValue;
- }
-
- get diastolicBloodPressure() {
- return this.payload.patient.diastolicBloodPressure ?? null;
- }
-
- set diastolicBloodPressure(newValue) {
- this.payload.patient.diastolicBloodPressure = newValue;
- }
-
- get heartRateBpm() {
- return this.payload.patient.heartRateBpm ?? null;
- }
-
- set heartRateBpm(newValue) {
- this.payload.patient.heartRateBpm = newValue;
- }
-
- get respiratoryRate() {
- return this.payload.patient.respiratoryRate ?? null;
- }
-
- set respiratoryRate(newValue) {
- this.payload.patient.respiratoryRate = newValue;
- }
-
- get oxygenSaturation() {
- return this.payload.patient.oxygenSaturation ?? null;
- }
-
- set oxygenSaturation(newValue) {
- this.payload.patient.oxygenSaturation = newValue;
- }
-
- get lowOxygenResponseType() {
- return this.payload.patient.lowOxygenResponseType ?? null;
- }
-
- set lowOxygenResponseType(newValue) {
- this.payload.patient.lowOxygenResponseType = newValue;
- if (newValue !== 'SUPPLEMENTAL OXYGEN') {
- this.supplementalOxygenAmount = null;
- }
- }
-
- get supplementalOxygenAmount() {
- return this.payload.patient.supplementalOxygenAmount ?? null;
- }
-
- set supplementalOxygenAmount(newValue) {
- this.payload.patient.supplementalOxygenAmount = newValue;
- }
-
- get temperature() {
- return this.payload.patient.temperature ?? null;
- }
-
- set temperature(newValue) {
- this.payload.patient.temperature = newValue;
- }
-
get hasVitals() {
return (
this.systolicBloodPressure ||
@@ -247,73 +111,9 @@ class Ringdown {
// Addtl Notes
- get etohSuspectedIndicator() {
- return this.payload.patient.etohSuspectedIndicator ?? false;
- }
-
- set etohSuspectedIndicator(newValue) {
- this.payload.patient.etohSuspectedIndicator = newValue;
- }
-
- get drugsSuspectedIndicator() {
- return this.payload.patient.drugsSuspectedIndicator ?? false;
- }
-
- set drugsSuspectedIndicator(newValue) {
- this.payload.patient.drugsSuspectedIndicator = newValue;
- }
-
- get psychIndicator() {
- return this.payload.patient.psychIndicator ?? false;
- }
-
- set psychIndicator(newValue) {
- this.payload.patient.psychIndicator = newValue;
- }
-
- get combativeBehaviorIndicator() {
- return this.payload.patient.combativeBehaviorIndicator ?? false;
- }
-
- set combativeBehaviorIndicator(newValue) {
- this.payload.patient.combativeBehaviorIndicator = newValue;
- this.restraintIndicator = newValue && this.restraintIndicator;
- }
-
- get restraintIndicator() {
- return this.payload.patient.restraintIndicator ?? false;
- }
-
- set restraintIndicator(newValue) {
- this.payload.patient.restraintIndicator = newValue;
- }
-
- get covid19SuspectedIndicator() {
- return this.payload.patient.covid19SuspectedIndicator ?? false;
- }
-
- set covid19SuspectedIndicator(newValue) {
- this.payload.patient.covid19SuspectedIndicator = newValue;
- }
-
- get ivIndicator() {
- return this.payload.patient.ivIndicator ?? false;
- }
-
- set ivIndicator(newValue) {
- this.payload.patient.ivIndicator = newValue;
- }
-
- get otherObservationNotes() {
- return this.payload.patient.otherObservationNotes ?? null;
- }
-
- set otherObservationNotes(newValue) {
- this.payload.patient.otherObservationNotes = newValue;
- }
-
get hasAdditionalNotes() {
return (
+ this.treatmentNotes ||
this.etohSuspectedIndicator ||
this.drugsSuspectedIndicator ||
this.psychIndicator ||
@@ -321,6 +121,7 @@ class Ringdown {
this.restraintIndicator ||
this.covid19SuspectedIndicator ||
this.ivIndicator ||
+ this.glasgowComaScale ||
this.otherObservationNotes
);
}
@@ -335,22 +136,6 @@ class Ringdown {
: null;
}
- get etaMinutes() {
- return this.payload.patientDelivery.etaMinutes ?? null;
- }
-
- set etaMinutes(newValue) {
- this.payload.patientDelivery.etaMinutes = newValue;
- }
-
- get currentDeliveryStatus() {
- return this.payload.patientDelivery.currentDeliveryStatus ?? null;
- }
-
- set currentDeliveryStatus(newValue) {
- this.payload.patientDelivery.currentDeliveryStatus = newValue;
- }
-
get timestamps() {
return this.payload.patientDelivery.timestamps ?? {};
}
@@ -385,14 +170,21 @@ class Ringdown {
// Form validation
- static ascendingByOrder(a, b) {
- if (a.order < b.order) {
- return -1;
- }
- if (a.order === b.order) {
- return 0;
+ setValidationData(validationData) {
+ if (validationData) {
+ this.validationData = validationData;
+ } else {
+ this.validationData = validatedFields.reduce((result, field, i) => {
+ const [name, validator] = field;
+ const fieldValue = this[name];
+ const value = typeof validator === 'function' ? validator(fieldValue) : fieldValue;
+ const state = value ? ValidationState.INPUT : ValidationState.NO_INPUT;
+
+ result[name] = new PatientFieldData(name, i, state);
+
+ return result;
+ }, {});
}
- return 1;
}
validatePatientFields(updatedField, inputValue) {
@@ -430,38 +222,89 @@ class Ringdown {
}
getValidationState(fieldName) {
- return this.validationData[fieldName].validationState;
+ return this.validationData[fieldName]?.validationState;
+ }
+}
+
+function attachFields(target, objectName, fields) {
+ const props = {};
+
+ fields.forEach((field) => {
+ props[field.name] = {
+ get() {
+ return this.payload[objectName][field.name] ?? field.defaultValue;
+ },
+ set(newValue) {
+ this.payload[objectName][field.name] = newValue;
+ },
+ configurable: true,
+ enumerable: true,
+ };
+ });
+
+ Object.defineProperties(target, props);
+}
+
+function overrideSetter(target, key, setter) {
+ const descriptor = Object.getOwnPropertyDescriptor(target, key);
+
+ if (!descriptor || !descriptor.set) {
+ throw new Error(`setter for '${key}' does not exist on the target.`);
}
+
+ Object.defineProperty(target, key, {
+ ...descriptor,
+ set: setter,
+ });
}
+// add the getters and setters to the Ringdown prototype for each field of each object in the payload
+payloadModels.forEach(([modelInfo, fieldNames]) => {
+ let metadataName = modelInfo;
+ let objectName = modelInfo;
+
+ if (modelInfo instanceof Array) {
+ // this model is being aliased under a different name on the Ringdown
+ [metadataName, objectName] = modelInfo;
+ }
+
+ // get the ModelMetadata fields, either filtering by the list of strings in payloadModels or the prefetched array
+ const fields =
+ typeof fieldNames[0] === 'string' ? metadata[metadataName].getFields(undefined, ({ name }) => fieldNames.includes(name)) : fieldNames;
+
+ // add a getter/setter for each field
+ attachFields(Ringdown.prototype, objectName, fields);
+
+ // add a getter to return this payload sub-object
+ Object.defineProperties(Ringdown.prototype, {
+ [objectName]: {
+ get() {
+ return this.payload[objectName];
+ },
+ configurable: true,
+ enumerable: true,
+ },
+ });
+});
+
+// add custom setters for these payload fields, since their values affect other fields
+overrideSetter(Ringdown.prototype, 'lowOxygenResponseType', function (newValue) {
+ this.payload.patient.lowOxygenResponseType = newValue;
+ if (newValue !== 'SUPPLEMENTAL OXYGEN') {
+ this.supplementalOxygenAmount = null;
+ }
+});
+overrideSetter(Ringdown.prototype, 'combativeBehaviorIndicator', function (newValue) {
+ this.payload.patient.combativeBehaviorIndicator = newValue;
+ this.restraintIndicator = newValue && this.restraintIndicator;
+});
+
Ringdown.propTypes = {
ambulanceIdentifier: PropTypes.string.isRequired,
dispatchCallNumber: PropTypes.number.isRequired,
hospitalId: PropTypes.string.isRequired,
// Patient Info
- age: PropTypes.number.isRequired,
- sex: PropTypes.oneOf(['MALE', 'FEMALE', 'NON-BINARY']).isRequired,
- emergencyServiceResponseType: PropTypes.oneOf(['CODE 2', 'CODE 3']).isRequired,
- chiefComplaintDescription: PropTypes.string.isRequired,
- stableIndicator: PropTypes.bool.isRequired,
- // Vitals
- systolicBloodPressure: PropTypes.number,
- diastolicBloodPressure: PropTypes.number,
- heartRateBpm: PropTypes.number,
- respiratoryRate: PropTypes.number,
- oxygenSaturation: PropTypes.number,
- lowOxygenResponseType: PropTypes.oneOf(['ROOM AIR', 'SUPPLEMENTAL OXYGEN']),
- supplementalOxygenAmount: PropTypes.number,
- temperature: PropTypes.number,
- // Addtl. Notes
- etohSuspectedIndicator: PropTypes.bool,
- drugsSuspectedIndicator: PropTypes.bool,
- psychIndicator: PropTypes.bool,
- combativeBehaviorIndicator: PropTypes.bool,
- restraintIndicator: PropTypes.bool,
- covid19SuspectedIndicator: PropTypes.bool,
- ivIndicator: PropTypes.bool,
- otherObservationNotes: PropTypes.string,
+ ...metadata.patient.getFieldHash(convertToPropType),
// Status
etaMinutes: PropTypes.number.isRequired,
currentDeliveryStatus: PropTypes.oneOf(DeliveryStatus.ALL_STATUSES),
diff --git a/src/shared/FieldMetadata.js b/src/shared/FieldMetadata.js
new file mode 100644
index 00000000..7dff4f25
--- /dev/null
+++ b/src/shared/FieldMetadata.js
@@ -0,0 +1,34 @@
+const Suffixes = {
+ uuid: '_uuid',
+ enum: 'enum',
+};
+const NonParamTypes = ['uuid', 'date'];
+
+function createColName({ name, type }) {
+ return name.toLowerCase() + (Suffixes[type] || '');
+}
+
+class FieldMetadata {
+ constructor(field) {
+ Object.assign(
+ this,
+ // assign these default values first so the field can override them below
+ {
+ colName: createColName(field),
+ isParam: !NonParamTypes.includes(field.type),
+ defaultValue: field.defaultValue ?? field.type === 'boolean' ? false : null,
+ },
+ field
+ );
+ }
+
+ toString() {
+ return `FieldMetadata: ${this.name}`;
+ }
+
+ get [Symbol.toStringTag]() {
+ return this.toString();
+ }
+}
+
+module.exports = FieldMetadata;
diff --git a/src/shared/ModelMetadata.js b/src/shared/ModelMetadata.js
new file mode 100644
index 00000000..2144fdd2
--- /dev/null
+++ b/src/shared/ModelMetadata.js
@@ -0,0 +1,61 @@
+const FieldMetadata = require('./FieldMetadata');
+
+const identity = (field) => field;
+const keyValue = (field) => [field.name, field];
+const all = () => true;
+
+const createdUpdatedFields = [
+ {
+ name: 'createdAt',
+ colName: 'recordcreatetimestamp',
+ type: 'date',
+ },
+ {
+ name: 'CreatedById',
+ colName: 'recordcreateuser_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'updatedAt',
+ colName: 'recordupdatetimestamp',
+ type: 'date',
+ },
+ {
+ name: 'UpdatedById',
+ colName: 'recordupdateuser_uuid',
+ type: 'uuid',
+ },
+];
+
+class ModelMetadata {
+ constructor({ modelName, tableName = modelName.toLowerCase(), fields }) {
+ this.modelName = modelName;
+ this.tableName = tableName;
+ // append the standard created and updated fields to all models
+ this.fields = Object.freeze([...fields, ...createdUpdatedFields].map((field) => new FieldMetadata(field)));
+ this.params = Object.freeze(
+ this.getFields(
+ ({ name }) => name,
+ ({ isParam }) => isParam
+ )
+ );
+ }
+
+ getFields(convertField = identity, filter = all) {
+ return this.fields.filter(filter).map(convertField);
+ }
+
+ getFieldHash(convertField = keyValue, filter = all) {
+ return Object.fromEntries(this.getFields(convertField, filter));
+ }
+
+ getParams() {
+ return this.params;
+ }
+
+ getObjectFields() {
+ return this.getFields(undefined, ({ type, isParam }) => isParam || type === 'enum');
+ }
+}
+
+module.exports = ModelMetadata;
diff --git a/src/shared/constants/DeliveryStatus.js b/src/shared/constants/DeliveryStatus.js
new file mode 100644
index 00000000..520cac2a
--- /dev/null
+++ b/src/shared/constants/DeliveryStatus.js
@@ -0,0 +1,19 @@
+const DeliveryStatus = {
+ RINGDOWN_SENT: 'RINGDOWN SENT',
+ RINGDOWN_RECEIVED: 'RINGDOWN RECEIVED',
+ RINGDOWN_CONFIRMED: 'RINGDOWN CONFIRMED',
+ ARRIVED: 'ARRIVED',
+ OFFLOADED: 'OFFLOADED',
+ OFFLOADED_ACKNOWLEDGED: 'OFFLOADED ACKNOWLEDGED',
+ RETURNED_TO_SERVICE: 'RETURNED TO SERVICE',
+ CANCELLED: 'CANCELLED',
+ CANCEL_ACKNOWLEDGED: 'CANCEL ACKNOWLEDGED',
+ REDIRECTED: 'REDIRECTED',
+ REDIRECT_ACKNOWLEDGED: 'REDIRECT ACKNOWLEDGED',
+};
+
+DeliveryStatus.ALL_STATUSES = Object.values(DeliveryStatus);
+
+DeliveryStatus.is = (status, target) => DeliveryStatus.ALL_STATUSES.indexOf(status) >= DeliveryStatus.ALL_STATUSES.indexOf(target);
+
+module.exports = Object.freeze(DeliveryStatus);
diff --git a/src/shared/constants/index.js b/src/shared/constants/index.js
new file mode 100644
index 00000000..f22046bb
--- /dev/null
+++ b/src/shared/constants/index.js
@@ -0,0 +1 @@
+exports.DeliveryStatus = require('./DeliveryStatus');
diff --git a/src/shared/convertToPropType.js b/src/shared/convertToPropType.js
new file mode 100644
index 00000000..7783c048
--- /dev/null
+++ b/src/shared/convertToPropType.js
@@ -0,0 +1,32 @@
+const PropTypes = require('prop-types');
+
+const PropTypeLookup = {
+ text: 'string',
+ integer: 'number',
+ decimal: 'number',
+ boolean: 'bool',
+};
+
+module.exports = function convertToPropType(field) {
+ const { name, type, isParam, typeArgs, required } = field;
+ // if the field isn't something we want to convert to a propType, then return an empty array so
+ // getFieldHash() won't include this field
+ let result = [];
+
+ if (isParam || type === 'enum') {
+ const reactType = PropTypeLookup[type];
+ let propType = PropTypes[reactType];
+
+ if (type === 'enum') {
+ propType = PropTypes.oneOf(typeArgs);
+ }
+
+ if (required) {
+ propType = propType.isRequired;
+ }
+
+ result = [name, propType];
+ }
+
+ return result;
+};
diff --git a/src/shared/convertToSequelizeField.js b/src/shared/convertToSequelizeField.js
new file mode 100644
index 00000000..8027a71a
--- /dev/null
+++ b/src/shared/convertToSequelizeField.js
@@ -0,0 +1,33 @@
+const { DataTypes } = require('sequelize');
+
+const SequelizeKeys = ['allowNull', 'autoIncrement', 'defaultValue', 'get', 'primaryKey', 'set', 'unique', 'validate'];
+
+const pick = (obj, keys) => Object.fromEntries(keys.filter((key) => key in obj).map((key) => [key, obj[key]]));
+
+const getDataType = (typeName) => DataTypes[typeName.toUpperCase()];
+
+module.exports = function convertToSequelizeField(field) {
+ const { name, colName, typeArgs, type: typeName } = field;
+ const sqlAttributes = pick(field, SequelizeKeys);
+ let type = getDataType(typeName);
+
+ if (typeName === 'enum') {
+ type = new DataTypes.ENUM(typeArgs);
+ } else if (typeName === 'virtual' && typeArgs) {
+ const [returnType, fields] = typeArgs;
+
+ type = new DataTypes.VIRTUAL(returnType && getDataType(returnType), fields);
+ }
+
+ // virtual fields don't have a column name in the db
+ if (typeName !== 'virtual') {
+ sqlAttributes.field = colName;
+ }
+
+ const convertedField = {
+ type,
+ ...sqlAttributes,
+ };
+
+ return [name, convertedField];
+};
diff --git a/src/shared/metadata/ambulance.js b/src/shared/metadata/ambulance.js
new file mode 100644
index 00000000..16809615
--- /dev/null
+++ b/src/shared/metadata/ambulance.js
@@ -0,0 +1,32 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'ambulance_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'OrganizationId',
+ colName: 'emsorganization_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'ambulanceIdentifier',
+ type: 'string',
+ unique: true,
+ allowNull: false,
+ defaultValue: '',
+ },
+ {
+ name: 'isActive',
+ colName: 'activeindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'Ambulance', fields });
diff --git a/src/shared/metadata/emergencyMedicalServiceCall.js b/src/shared/metadata/emergencyMedicalServiceCall.js
new file mode 100644
index 00000000..9e6bc366
--- /dev/null
+++ b/src/shared/metadata/emergencyMedicalServiceCall.js
@@ -0,0 +1,24 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'emergencymedicalservicecall_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'dispatchCallNumber',
+ type: 'integer',
+ allowNull: false,
+ defaultValue: '',
+ },
+ {
+ name: 'startDateTimeLocal',
+ type: 'date',
+ allowNull: false,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'EmergencyMedicalServiceCall', fields });
diff --git a/src/shared/metadata/emergencyMedicalServiceCallAmbulance.js b/src/shared/metadata/emergencyMedicalServiceCallAmbulance.js
new file mode 100644
index 00000000..935eab68
--- /dev/null
+++ b/src/shared/metadata/emergencyMedicalServiceCallAmbulance.js
@@ -0,0 +1,28 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'emergencymedicalservicecallambulance_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'EmergencyMedicalServiceCallId',
+ colName: 'emergencymedicalservicecall_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'AmbulanceId',
+ colName: 'ambulance_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'startDateTimeLocal',
+ type: 'date',
+ allowNull: false,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'EmergencyMedicalServiceCallAmbulance', fields });
diff --git a/src/shared/metadata/hospital.js b/src/shared/metadata/hospital.js
new file mode 100644
index 00000000..4e455ccd
--- /dev/null
+++ b/src/shared/metadata/hospital.js
@@ -0,0 +1,47 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ // this is the value used to determine who each nurse belongs to
+ name: 'id',
+ colName: 'hospital_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'OrganizationId',
+ colName: 'healthcareorganization_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'name',
+ colName: 'hospitalname',
+ type: 'string',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'state',
+ colName: 'hospitalstate',
+ type: 'string',
+ },
+ {
+ name: 'stateFacilityCode',
+ colName: 'hospitalstatefacilitycode',
+ type: 'string',
+ },
+ {
+ name: 'sortSequenceNumber',
+ type: 'integer',
+ },
+ {
+ name: 'isActive',
+ colName: 'activeindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'Hospital', fields });
diff --git a/src/shared/metadata/hospitalStatusUpdate.js b/src/shared/metadata/hospitalStatusUpdate.js
new file mode 100644
index 00000000..54983616
--- /dev/null
+++ b/src/shared/metadata/hospitalStatusUpdate.js
@@ -0,0 +1,65 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'hospitalstatusupdate_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'HospitalId',
+ colName: 'hospital_uuid',
+ type: 'uuid',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'EdAdminUserId',
+ colName: 'edadminuser_uuid',
+ type: 'uuid',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'updateDateTimeLocal',
+ type: 'date',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'openEdBedCount',
+ type: 'integer',
+ allowNull: false,
+ },
+ {
+ name: 'openPsychBedCount',
+ type: 'integer',
+ allowNull: false,
+ },
+ {
+ name: 'bedCountUpdateDateTimeLocal',
+ type: 'date',
+ },
+ {
+ name: 'divertStatusIndicator',
+ type: 'boolean',
+ allowNull: false,
+ },
+ {
+ name: 'divertStatusUpdateDateTimeLocal',
+ type: 'date',
+ },
+ {
+ name: 'additionalServiceAvailabilityNotes',
+ type: 'text',
+ allowNull: true,
+ },
+ {
+ name: 'notesUpdateDateTimeLocal',
+ type: 'date',
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'HospitalStatusUpdate', fields });
diff --git a/src/shared/metadata/hospitalUser.js b/src/shared/metadata/hospitalUser.js
new file mode 100644
index 00000000..92560c19
--- /dev/null
+++ b/src/shared/metadata/hospitalUser.js
@@ -0,0 +1,48 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'hospitaluser_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'HospitalId',
+ colName: 'hospital_uuid',
+ type: 'uuid',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'EdAdminUserId',
+ colName: 'edadminuser_uuid',
+ type: 'uuid',
+ unique: true,
+ allowNull: false,
+ },
+ {
+ name: 'isActive',
+ colName: 'activeindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+ {
+ name: 'isInfoUser',
+ colName: 'infouserindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+ {
+ name: 'isRingdownUser',
+ colName: 'ringdownuserindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'HospitalUser', fields });
diff --git a/src/shared/metadata/index.js b/src/shared/metadata/index.js
new file mode 100644
index 00000000..2863b5c5
--- /dev/null
+++ b/src/shared/metadata/index.js
@@ -0,0 +1,25 @@
+const ambulance = require('./ambulance');
+const emergencyMedicalServiceCall = require('./emergencyMedicalServiceCall');
+const emergencyMedicalServiceCallAmbulance = require('./emergencyMedicalServiceCallAmbulance');
+const hospital = require('./hospital');
+const hospitalStatusUpdate = require('./hospitalStatusUpdate');
+const hospitalUser = require('./hospitalUser');
+const organization = require('./organization');
+const patient = require('./patient');
+const patientDeliveryUpdate = require('./patientDeliveryUpdate');
+const patientDelivery = require('./patientDelivery');
+const user = require('./user');
+
+module.exports = {
+ ambulance,
+ emergencyMedicalServiceCall,
+ emergencyMedicalServiceCallAmbulance,
+ hospital,
+ hospitalStatusUpdate,
+ hospitalUser,
+ organization,
+ patient,
+ patientDelivery,
+ patientDeliveryUpdate,
+ user,
+};
diff --git a/src/shared/metadata/organization.js b/src/shared/metadata/organization.js
new file mode 100644
index 00000000..0b3db79a
--- /dev/null
+++ b/src/shared/metadata/organization.js
@@ -0,0 +1,48 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'organization_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'name',
+ colName: 'organizationname',
+ type: 'string',
+ allowNull: false,
+ },
+ {
+ name: 'type',
+ colName: 'organizationtypeenum',
+ type: 'enum',
+ typeArgs: ['EMS', 'HEALTHCARE', 'C4SF'],
+ allowNull: false,
+ },
+ {
+ name: 'state',
+ colName: 'organizationstate',
+ type: 'string',
+ },
+ {
+ name: 'stateUniqueId',
+ colName: 'organizationstateuniqueid',
+ type: 'string',
+ },
+ {
+ name: 'timeZoneIsoCode',
+ type: 'string',
+ defaultValue: 'PST',
+ },
+ {
+ name: 'isActive',
+ colName: 'activeindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'Organization', fields });
diff --git a/src/shared/metadata/patient.js b/src/shared/metadata/patient.js
new file mode 100644
index 00000000..f6809227
--- /dev/null
+++ b/src/shared/metadata/patient.js
@@ -0,0 +1,155 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'patient_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'EmergencyMedicalServiceCallId',
+ colName: 'emergencymedicalservicecall_uuid',
+ type: 'uuid',
+ allowNull: false,
+ unique: true,
+ },
+ {
+ name: 'emergencyServiceResponseType',
+ type: 'enum',
+ typeArgs: ['CODE 2', 'CODE 3'],
+ required: true,
+ },
+ {
+ name: 'age',
+ type: 'integer',
+ label: 'Age (estimated)',
+ unit: 'years',
+ required: true,
+ range: { min: 0, max: 130 },
+ },
+ {
+ name: 'sex',
+ type: 'enum',
+ typeArgs: ['MALE', 'FEMALE', 'NON-BINARY'],
+ required: true,
+ },
+ {
+ name: 'chiefComplaintDescription',
+ type: 'text',
+ label: 'Chief Complaint',
+ required: true,
+ },
+ {
+ name: 'stableIndicator',
+ type: 'boolean',
+ // though this is stored as a boolean, it's rendered in the UI as two radio buttons, not a
+ // checkbox, so use null as the default so neither radio is selected
+ defaultValue: null,
+ required: true,
+ },
+ {
+ name: 'systolicBloodPressure',
+ type: 'integer',
+ range: { min: 90, max: 180 },
+ },
+ {
+ name: 'diastolicBloodPressure',
+ type: 'integer',
+ range: { min: 60, max: 120 },
+ },
+ {
+ name: 'heartRateBpm',
+ type: 'integer',
+ label: 'Pulse',
+ unit: 'beats/min',
+ range: { min: 40, max: 200 },
+ },
+ {
+ name: 'respiratoryRate',
+ type: 'integer',
+ label: 'Respiratory Rate',
+ unit: 'breaths/min',
+ range: { min: 12, max: 25 },
+ },
+ {
+ name: 'oxygenSaturation',
+ type: 'integer',
+ label: 'SpO2',
+ unit: '%',
+ range: { min: 0, max: 100 },
+ },
+ {
+ name: 'lowOxygenResponseType',
+ type: 'enum',
+ typeArgs: ['ROOM AIR', 'SUPPLEMENTAL OXYGEN'],
+ },
+ {
+ name: 'supplementalOxygenAmount',
+ type: 'integer',
+ unit: 'L',
+ range: { min: 1, max: 1000 },
+ },
+ {
+ name: 'temperature',
+ type: 'decimal',
+ label: 'Temperature',
+ unit: '°F',
+ range: { min: 80, max: 150 },
+ },
+ {
+ name: 'treatmentNotes',
+ type: 'text',
+ label: 'Treatments Administered',
+ },
+ {
+ name: 'etohSuspectedIndicator',
+ type: 'boolean',
+ label: 'ETOH suspected',
+ },
+ {
+ name: 'drugsSuspectedIndicator',
+ type: 'boolean',
+ label: 'Drugs suspected',
+ },
+ {
+ name: 'psychIndicator',
+ type: 'boolean',
+ label: 'Behavioral health needs',
+ },
+ {
+ name: 'combativeBehaviorIndicator',
+ type: 'boolean',
+ label: 'Combative',
+ },
+ {
+ name: 'restraintIndicator',
+ type: 'boolean',
+ label: '4-point restraint',
+ },
+ {
+ name: 'covid19SuspectedIndicator',
+ colName: 'covid-19suspectedindicator',
+ type: 'boolean',
+ label: 'COVID-19 suspected',
+ },
+ {
+ name: 'ivIndicator',
+ type: 'boolean',
+ },
+ {
+ name: 'glasgowComaScale',
+ type: 'integer',
+ label: 'GCS',
+ unit: '/ 15',
+ range: { min: 3, max: 15 },
+ },
+ {
+ name: 'otherObservationNotes',
+ type: 'text',
+ label: 'Other',
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'Patient', fields });
diff --git a/src/shared/metadata/patientDelivery.js b/src/shared/metadata/patientDelivery.js
new file mode 100644
index 00000000..06ca52ab
--- /dev/null
+++ b/src/shared/metadata/patientDelivery.js
@@ -0,0 +1,56 @@
+const ModelMetadata = require('../ModelMetadata');
+const { DeliveryStatus } = require('../constants');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'patientdelivery_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'AmbulanceId',
+ colName: 'ambulance_uuid',
+ type: 'uuid',
+ allowNull: false,
+ },
+ {
+ name: 'PatientId',
+ colName: 'patient_uuid',
+ type: 'uuid',
+ allowNull: false,
+ },
+ {
+ name: 'HospitalId',
+ colName: 'hospital_uuid',
+ type: 'uuid',
+ allowNull: false,
+ },
+ {
+ name: 'ParamedicUserId',
+ colName: 'paramedicuser_uuid',
+ type: 'uuid',
+ allowNull: false,
+ },
+ {
+ name: 'currentDeliveryStatus',
+ type: 'enum',
+ typeArgs: DeliveryStatus.ALL_STATUSES,
+ allowNull: false,
+ isParam: true,
+ },
+ {
+ name: 'currentDeliveryStatusDateTimeLocal',
+ type: 'date',
+ isParam: true,
+ },
+ {
+ name: 'etaMinutes',
+ type: 'integer',
+ range: { min: 0 },
+ isParam: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'PatientDelivery', fields });
diff --git a/src/shared/metadata/patientDeliveryUpdate.js b/src/shared/metadata/patientDeliveryUpdate.js
new file mode 100644
index 00000000..eb2ea3cc
--- /dev/null
+++ b/src/shared/metadata/patientDeliveryUpdate.js
@@ -0,0 +1,30 @@
+const ModelMetadata = require('../ModelMetadata');
+const { DeliveryStatus } = require('../constants');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'patientdeliveryupdate_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'PatientDeliveryId',
+ colName: 'patientdelivery_uuid',
+ type: 'uuid',
+ allowNull: false,
+ },
+ {
+ name: 'deliveryStatus',
+ type: 'enum',
+ typeArgs: DeliveryStatus.ALL_STATUSES,
+ allowNull: false,
+ },
+ {
+ name: 'deliveryStatusDateTimeLocal',
+ type: 'date',
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'PatientDeliveryUpdate', fields });
diff --git a/src/shared/metadata/user.js b/src/shared/metadata/user.js
new file mode 100644
index 00000000..ae13beac
--- /dev/null
+++ b/src/shared/metadata/user.js
@@ -0,0 +1,99 @@
+const ModelMetadata = require('../ModelMetadata');
+
+const fields = [
+ {
+ name: 'id',
+ colName: 'user_uuid',
+ type: 'uuid',
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ {
+ name: 'OrganizationId',
+ colName: 'organization_uuid',
+ type: 'uuid',
+ },
+ {
+ name: 'firstName',
+ type: 'string',
+ allowNull: false,
+ },
+ {
+ name: 'lastName',
+ type: 'string',
+ allowNull: false,
+ },
+ {
+ name: 'name',
+ type: 'virtual',
+ typeArgs: ['string', ['firstName', 'lastName']],
+ get() {
+ return `${this.firstName} ${this.lastName}`.trim();
+ },
+ },
+ {
+ name: 'email',
+ type: 'citext',
+ unique: {
+ msg: 'This email address has already been used.',
+ },
+ validate: {
+ isEmail: {
+ msg: 'This is not a valid email address.',
+ },
+ },
+ },
+ {
+ name: 'subjectId',
+ type: 'string',
+ },
+ {
+ name: 'password',
+ type: 'virtual',
+ typeArgs: ['string'],
+ validate: {
+ is: {
+ args: [/^(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z]).{8,}$/],
+ msg: 'At least 8 characters, including upper and lowercase letters, a number, and a symbol.',
+ },
+ },
+ },
+ {
+ name: 'hashedPassword',
+ type: 'string',
+ },
+ {
+ name: 'ssoData',
+ type: 'jsonb',
+ },
+ {
+ name: 'isOperationalUser',
+ colName: 'operationaluserindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: false,
+ },
+ {
+ name: 'isAdminUser',
+ colName: 'administrativeuserindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: false,
+ },
+ {
+ name: 'isSuperUser',
+ colName: 'superuserindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: false,
+ },
+ {
+ name: 'isActive',
+ colName: 'activeindicator',
+ type: 'boolean',
+ allowNull: false,
+ defaultValue: true,
+ },
+];
+
+module.exports = new ModelMetadata({ modelName: 'User', tableName: 'batsuser', fields });
diff --git a/test/integration/api/ringdowns.js b/test/integration/api/ringdowns.js
index c3c8ab3a..d476943a 100644
--- a/test/integration/api/ringdowns.js
+++ b/test/integration/api/ringdowns.js
@@ -5,7 +5,7 @@ const session = require('supertest-session');
const helper = require('../../helper');
const app = require('../../../app');
const models = require('../../../models');
-const { DeliveryStatus } = require('../../../constants');
+const { DeliveryStatus } = require('../../../src/shared/constants');
describe('/api/ringdowns', () => {
let testSession;
@@ -82,12 +82,14 @@ describe('/api/ringdowns', () => {
lowOxygenResponseType: 'SUPPLEMENTAL OXYGEN',
supplementalOxygenAmount: 2,
temperature: 99.4,
+ treatmentNotes: 'Gave px lollipop',
etohSuspectedIndicator: false,
drugsSuspectedIndicator: true,
psychIndicator: false,
combativeBehaviorIndicator: false,
restraintIndicator: false,
covid19SuspectedIndicator: true,
+ glasgowComaScale: 3,
ivIndicator: false,
otherObservationNotes: 'Needs assistance walking',
};
@@ -407,13 +409,15 @@ describe('/api/ringdowns', () => {
lowOxygenResponseType: null,
supplementalOxygenAmount: null,
temperature: null,
- etohSuspectedIndicator: null,
- drugsSuspectedIndicator: null,
- psychIndicator: null,
- combativeBehaviorIndicator: null,
- restraintIndicator: null,
- covid19SuspectedIndicator: null,
- ivIndicator: null,
+ treatmentNotes: null,
+ etohSuspectedIndicator: false,
+ drugsSuspectedIndicator: false,
+ psychIndicator: false,
+ combativeBehaviorIndicator: false,
+ restraintIndicator: false,
+ covid19SuspectedIndicator: false,
+ ivIndicator: false,
+ glasgowComaScale: null,
otherObservationNotes: null,
},
patientDelivery: {
diff --git a/test/unit/models/patientDelivery.js b/test/unit/models/patientDelivery.js
index a35620b2..932f5366 100644
--- a/test/unit/models/patientDelivery.js
+++ b/test/unit/models/patientDelivery.js
@@ -1,7 +1,7 @@
const assert = require('assert');
const helper = require('../../helper');
const models = require('../../../models');
-const { DeliveryStatus } = require('../../../constants');
+const { DeliveryStatus } = require('../../../src/shared/constants');
describe('models.PatientDelivery', () => {
beforeEach(async () => {
@@ -204,13 +204,15 @@ describe('models.PatientDelivery', () => {
lowOxygenResponseType: null,
supplementalOxygenAmount: null,
temperature: null,
- etohSuspectedIndicator: null,
- drugsSuspectedIndicator: null,
- psychIndicator: null,
- combativeBehaviorIndicator: null,
- restraintIndicator: null,
- covid19SuspectedIndicator: null,
- ivIndicator: null,
+ treatmentNotes: null,
+ etohSuspectedIndicator: false,
+ drugsSuspectedIndicator: false,
+ psychIndicator: false,
+ combativeBehaviorIndicator: false,
+ restraintIndicator: false,
+ covid19SuspectedIndicator: false,
+ ivIndicator: false,
+ glasgowComaScale: null,
otherObservationNotes: null,
},
patientDelivery: {
diff --git a/theme/_uswds-theme-custom-styles.scss b/theme/_uswds-theme-custom-styles.scss
index 776f9b58..0af64020 100644
--- a/theme/_uswds-theme-custom-styles.scss
+++ b/theme/_uswds-theme-custom-styles.scss
@@ -211,6 +211,11 @@ $spinner-border-width-sm: 0.2em;
@include u-margin-top(2);
}
+textarea + .usa-checkbox > .usa-checkbox__label,
+textarea + .usa-radio > .usa-radio__label {
+ @include u-margin-top(4);
+}
+
.usa-combo-box__clear-input {
display: none !important;
}
diff --git a/wss.js b/wss.js
index 67f01588..497e1759 100644
--- a/wss.js
+++ b/wss.js
@@ -2,7 +2,7 @@ const querystring = require('querystring');
const { Op } = require('sequelize');
const url = require('url');
const WebSocket = require('ws');
-const DeliveryStatus = require('./constants/deliveryStatus');
+const DeliveryStatus = require('./src/shared/constants/DeliveryStatus');
const models = require('./models');
const userServer = new WebSocket.Server({ noServer: true });
diff --git a/yarn.lock b/yarn.lock
index c3770c73..8c3cb748 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10363,10 +10363,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
-prettier@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6"
- integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==
+prettier@2.7.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
+ integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
pretty-bytes@^5.1.0:
version "5.3.0"