diff --git a/.eslintrc.js b/.eslintrc.js
index 63f3dd64..f9f4cd97 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -38,6 +38,85 @@ const tsBase = {
'plugin:@typescript-eslint/recommended',
"plugin:react-hooks/recommended",
],
+ rules: {
+ '@typescript-eslint/member-ordering': ['error',
+ {
+ // this is the default from @typescript-eslint itself
+ "default": {
+ "memberTypes": [
+ // Index signature
+ "signature",
+
+ // Fields
+ "public-static-field",
+ "protected-static-field",
+ "private-static-field",
+
+ "public-decorated-field",
+ "protected-decorated-field",
+ "private-decorated-field",
+
+ "public-instance-field",
+ "protected-instance-field",
+ "private-instance-field",
+
+ "public-abstract-field",
+ "protected-abstract-field",
+ "private-abstract-field",
+
+ "public-field",
+ "protected-field",
+ "private-field",
+
+ "static-field",
+ "instance-field",
+ "abstract-field",
+
+ "decorated-field",
+
+ "field",
+
+ // Constructors
+ "public-constructor",
+ "protected-constructor",
+ "private-constructor",
+
+ "constructor",
+
+ // Methods
+ "public-static-method",
+ "protected-static-method",
+ "private-static-method",
+
+ "public-decorated-method",
+ "protected-decorated-method",
+ "private-decorated-method",
+
+ "public-instance-method",
+ "protected-instance-method",
+ "private-instance-method",
+
+ "public-abstract-method",
+ "protected-abstract-method",
+ "private-abstract-method",
+
+ "public-method",
+ "protected-method",
+ "private-method",
+
+ "static-method",
+ "instance-method",
+ "abstract-method",
+
+ "decorated-method",
+
+ "method",
+ ],
+ "order": "alphabetically",
+ },
+ },
+ ],
+ },
};
const tsSettings = _.cloneDeep(tsBase);
@@ -79,9 +158,9 @@ module.exports = {
"always",
],
"no-trailing-spaces": ["error"],
- "indent": ["error", "tab", {"SwitchCase": 1}], // we use tabs for accessibility
+ "indent": ["error", "tab", { "SwitchCase": 1 }], // we use tabs for accessibility
"comma-dangle": ["error", "always-multiline"],
- "@typescript-eslint/no-unused-vars": ['error', {"args": "all", "argsIgnorePattern": "^_"}],
+ "@typescript-eslint/no-unused-vars": ['error', { "args": "all", "argsIgnorePattern": "^_" }],
},
"settings": {
"react": {
diff --git a/app/javascript/common/money.ts b/app/javascript/common/money.ts
index 4cef4849..240285b3 100644
--- a/app/javascript/common/money.ts
+++ b/app/javascript/common/money.ts
@@ -28,6 +28,13 @@ type MoneyAsJson = { amount: number, currency: string }
*/
export class Money {
+ /**
+ * Create a `Money` object with the given number if smallest monetary units and the ISO currency. Another name for the `fromCents` function.
+ * @static
+ * @memberof Money
+ */
+ static fromSMU = Money.fromCents
+
readonly currency: string
protected constructor(readonly amount: number, currency: string) {
@@ -63,28 +70,6 @@ export class Money {
return new Money(amount.amount, amount.currency);
}
-
- /**
- * Create a `Money` object with the given number if smallest monetary units and the ISO currency. Another name for the `fromCents` function.
- * @static
- * @memberof Money
- */
- static fromSMU = Money.fromCents
-
- /**
- * Returns true if the two instances of Money are equal, false otherwise.
- *
- * @param {Money} other
- * @returns {Boolean}
- */
- equals(other: Money): boolean {
-
- assertType(other);
-
- return this.amount === other.amount &&
- this.currency === other.currency;
- }
-
/**
* Adds the two objects together creating a new Money instance that holds the result of the operation.
*
@@ -99,54 +84,6 @@ export class Money {
return new Money(this.amount + other.amount, this.currency);
}
- /**
- * Subtracts the two objects creating a new Money instance that holds the result of the operation.
- *
- * @param {Money} other
- * @returns {Money}
- */
- subtract(other: Money): Money {
-
- assertType(other);
- assertSameCurrency(this, other);
-
- return new Money(this.amount - other.amount, this.currency);
- }
-
- /**
- * Multiplies the object by the multiplier returning a new Money instance that holds the result of the operation.
- *
- * @param {number} multiplier
- * @param {(x:number) => number} [fn=Math.round]
- * @returns {Money}
- */
- multiply(multiplier: number, roundingFunction: (x: number) => number): Money {
- if (!isFunction(roundingFunction))
- roundingFunction = Math.round;
-
- assertOperand(multiplier);
- const amount = roundingFunction(this.amount * multiplier);
-
- return new Money(amount, this.currency);
- }
-
- /**
- * Divides the object by the multiplier returning a new Money instance that holds the result of the operation.
- *
- * @param {Number} divisor
- * @param {(x:number) => number} [fn=Math.round]
- * @returns {Money}
- */
- divide(divisor: number, fn?: (x: number) => number): Money {
- if (!isFunction(fn))
- fn = Math.round;
-
- assertOperand(divisor);
- const amount = fn(this.amount / divisor);
-
- return new Money(amount, this.currency);
- }
-
/**
* Allocates fund bases on the ratios provided returing an array of objects as a product of the allocation.
*
@@ -195,6 +132,38 @@ export class Money {
return this.amount > other.amount ? 1 : -1;
}
+ /**
+ * Divides the object by the multiplier returning a new Money instance that holds the result of the operation.
+ *
+ * @param {Number} divisor
+ * @param {(x:number) => number} [fn=Math.round]
+ * @returns {Money}
+ */
+ divide(divisor: number, fn?: (x: number) => number): Money {
+ if (!isFunction(fn))
+ fn = Math.round;
+
+ assertOperand(divisor);
+ const amount = fn(this.amount / divisor);
+
+ return new Money(amount, this.currency);
+ }
+
+
+ /**
+ * Returns true if the two instances of Money are equal, false otherwise.
+ *
+ * @param {Money} other
+ * @returns {Boolean}
+ */
+ equals(other: Money): boolean {
+
+ assertType(other);
+
+ return this.amount === other.amount &&
+ this.currency === other.currency;
+ }
+
/**
* Checks whether the value represented by this object is greater than the other.
*
@@ -215,6 +184,28 @@ export class Money {
return 0 <= this.compare(other);
}
+ isNegative(): boolean {
+ return this.amount < 0;
+ }
+
+ /**
+ * Returns true if the amount is positive.
+ *
+ * @returns {boolean}
+ */
+ isPositive(): boolean {
+ return this.amount > 0;
+ }
+
+ /**
+ * Returns true if the amount is zero.
+ *
+ * @returns {boolean}
+ */
+ isZero(): boolean {
+ return this.amount === 0;
+ }
+
/**
* Checks whether the value represented by this object is less than the other.
*
@@ -236,25 +227,34 @@ export class Money {
}
/**
- * Returns true if the amount is zero.
+ * Multiplies the object by the multiplier returning a new Money instance that holds the result of the operation.
*
- * @returns {boolean}
+ * @param {number} multiplier
+ * @param {(x:number) => number} [fn=Math.round]
+ * @returns {Money}
*/
- isZero(): boolean {
- return this.amount === 0;
+ multiply(multiplier: number, roundingFunction: (x: number) => number): Money {
+ if (!isFunction(roundingFunction))
+ roundingFunction = Math.round;
+
+ assertOperand(multiplier);
+ const amount = roundingFunction(this.amount * multiplier);
+
+ return new Money(amount, this.currency);
}
/**
- * Returns true if the amount is positive.
+ * Subtracts the two objects creating a new Money instance that holds the result of the operation.
*
- * @returns {boolean}
+ * @param {Money} other
+ * @returns {Money}
*/
- isPositive(): boolean {
- return this.amount > 0;
- }
+ subtract(other: Money): Money {
- isNegative(): boolean {
- return this.amount < 0;
+ assertType(other);
+ assertSameCurrency(this, other);
+
+ return new Money(this.amount - other.amount, this.currency);
}
/**
diff --git a/app/javascript/components/formik/MoneyTextField.spec.tsx b/app/javascript/components/formik/MoneyTextField.spec.tsx
index 8ad384f6..93df90c3 100644
--- a/app/javascript/components/formik/MoneyTextField.spec.tsx
+++ b/app/javascript/components/formik/MoneyTextField.spec.tsx
@@ -26,7 +26,7 @@ function FormikInner(props: { onChange:(args:{value:Money})=> void}) {
>;
}
-function FormikHandler(props: { value: Money, onChange:(args:{value:Money})=> void}) {
+function FormikHandler(props: { onChange:(args:{value:Money})=> void, value: Money,}) {
const {value, ...innerFormikProps} = props;
return
diff --git a/app/javascript/components/formik/MoneyTextField.stories.tsx b/app/javascript/components/formik/MoneyTextField.stories.tsx
index c43f2823..44dc1584 100644
--- a/app/javascript/components/formik/MoneyTextField.stories.tsx
+++ b/app/javascript/components/formik/MoneyTextField.stories.tsx
@@ -19,7 +19,7 @@ function FormikInner(props: { onChange:(args:{value:Money})=> void}) {
>;
}
-function FormikHandler(props: { value: Money, onChange:(args:{value:Money})=> void}) {
+function FormikHandler(props: { onChange:(args:{value:Money})=> void, value: Money}) {
const {value, ...innerFormikProps} = props;
return ( { console.log("submitted");}} enableReinitialize={true}>
diff --git a/app/javascript/components/tests/intl/index.tsx b/app/javascript/components/tests/intl/index.tsx
index 66aca9dd..f7098f85 100644
--- a/app/javascript/components/tests/intl/index.tsx
+++ b/app/javascript/components/tests/intl/index.tsx
@@ -28,12 +28,6 @@ class WithIntl extends React.Component {
channel.emit(EVENT_GET_LOCALE_ID);
}
- setLocale (locale:string) {
- this.setState({
- locale: locale,
- });
- }
-
componentWillUnmount () {
this.props.channel.removeListener(EVENT_SET_LOCALE_ID, this.setLocale);
}
@@ -70,6 +64,12 @@ class WithIntl extends React.Component {
);
}
+
+ setLocale (locale:string) {
+ this.setState({
+ locale: locale,
+ });
+ }
}
diff --git a/app/javascript/hooks/useSteps.spec.ts b/app/javascript/hooks/useSteps.spec.ts
index 8081d278..67a9504e 100644
--- a/app/javascript/hooks/useSteps.spec.ts
+++ b/app/javascript/hooks/useSteps.spec.ts
@@ -344,19 +344,19 @@ describe('.enable', () => {
describe('modify steps', () => {
function createTableEntry(props: {
- initial: {
- steps: KeyedStep[],
- activeStep?: number,
- disabled?: KeyedStepMap,
- completed?:
- KeyedStepMap
- },
- stepChange: KeyedStep[],
expectation: {
activeStep?: number,
+ completed?: KeyedStepMap,
disabled?: KeyedStepMap,
- completed?: KeyedStepMap
- }
+ },
+ initial: {
+ activeStep?: number,
+ completed?:
+ KeyedStepMap
+ disabled?: KeyedStepMap,
+ steps: KeyedStep[],
+ },
+ stepChange: KeyedStep[],
}
): [
KeyedStep[], number | undefined, KeyedStepMap | undefined, KeyedStepMap | undefined, // initial
diff --git a/app/javascript/hooks/useSteps.ts b/app/javascript/hooks/useSteps.ts
index 38f4a006..b56cd10f 100644
--- a/app/javascript/hooks/useSteps.ts
+++ b/app/javascript/hooks/useSteps.ts
@@ -18,43 +18,48 @@ export interface KeyedStepMap {
interface ReadonlyStepsState {
readonly activeStep?: number;
+ readonly activeStepKey: string;
readonly completed?: KeyedStepMap;
readonly disabled?: KeyedStepMap;
/**
* An internal copy of steps which only includes the key
*/
readonly stepKeys: readonly string[]
- readonly activeStepKey: string;
+
}
function areKeyedStepsDifferent(first: readonly string[], second: readonly string[]) {
return first.length != second.length || first.find((value, index) => second[index] != value);
}
-function getIndexAndKeyPair(steps: readonly string[], step: string | number | unknown): {key:string, index:number} | false {
+function getIndexAndKeyPair(steps: readonly string[], step: string | number | unknown): { index: number, key: string } | false {
if (typeof step === 'string') {
const index = steps.findIndex((i) => i === step);
- if (index){
- return {key: step, index};
+ if (index) {
+ return { key: step, index };
}
}
else if (typeof step === 'number' && step >= 0 && step < steps.length) {
- return {key: steps[step], index: step};
+ return { key: steps[step], index: step };
}
return false;
}
-function getLastEnabledBeforeGivenStep(steps: readonly string[], currentActiveStep:number, disabled:KeyedStepMap): {key:string, index:number}{
+function getLastEnabledBeforeGivenStep(
+ steps: readonly string[],
+ currentActiveStep: number,
+ disabled: KeyedStepMap
+): { index: number, key: string } {
const possibleNewActiveStep = findLastIndex(take(steps, currentActiveStep + 1), (i) => !disabled[i]);
- const index = possibleNewActiveStep >= 0 ? possibleNewActiveStep : 0;
- return {key: steps[index], index};
+ const index = possibleNewActiveStep >= 0 ? possibleNewActiveStep : 0;
+ return { key: steps[index], index };
}
function reindexState(state: ReadonlyStepsState, incomingSteps: readonly KeyedStep[]): ReadonlyStepsState {
const incomingStepKeys = incomingSteps.map(i => i.key);
//if true, we've had new steps added or removed
- if (areKeyedStepsDifferent(state.stepKeys, incomingStepKeys) ) {
+ if (areKeyedStepsDifferent(state.stepKeys, incomingStepKeys)) {
const newIndexOfActiveStep = incomingStepKeys.findIndex(v => v === state.activeStepKey);
let activeStep = state.activeStep;
let activeStepKey = state.activeStepKey;
@@ -101,10 +106,6 @@ function reindexState(state: ReadonlyStepsState, incomingSteps: readonly KeyedSt
return state;
}
-
-
-
-
interface StepsInitOptions {
readonly activeStep?: number;
readonly completed?: KeyedStepMap;
@@ -123,31 +124,31 @@ interface InputStepsMethods {
interface MutableStepsObject extends InputStepsMethods {
- goto: (step: number) => void
back: () => void
- next: () => void
- first: () => void
- last: () => void
complete: (step: number) => void
- uncomplete: (step: number) => void
disable: (step: number) => void
enable: (step: number) => void
-
+ first: () => void
+ goto: (step: number) => void
+ last: () => void
+ next: () => void
+ uncomplete: (step: number) => void
}
type StepsObject = Readonly & Readonly & StepsInitOptions & { readonly steps: readonly KeyedStep[] }
type StepTypes = 'goto' | 'first' | 'last' | 'back' | 'next' | 'complete' | 'uncomplete' | 'disable' | 'enable' | 'stepsChanged'
interface StepAction {
- type: StepTypes, payload?: number | string | readonly KeyedStep[]
+ payload?: number | string | readonly KeyedStep[];
+ type: StepTypes;
}
function stepsReducer(state: ReadonlyStepsState, args: StepAction): ReadonlyStepsState {
- let indexKeyPair:ReturnType = false;
+ let indexKeyPair: ReturnType = false;
switch (args.type) {
case ('goto'):
indexKeyPair = getIndexAndKeyPair(state.stepKeys, args.payload);
if (indexKeyPair && !state.disabled[indexKeyPair.key]) {
- return {...state, activeStep:indexKeyPair.index, activeStepKey: indexKeyPair.key};
+ return { ...state, activeStep: indexKeyPair.index, activeStepKey: indexKeyPair.key };
}
return state;
case ('first'):
@@ -157,7 +158,7 @@ function stepsReducer(state: ReadonlyStepsState, args: StepAction): ReadonlyStep
}
return state;
case ('last'):
- const lastStep = state.stepKeys.length - 1 >=0 ? state.stepKeys.length - 1 : 0 ;
+ const lastStep = state.stepKeys.length - 1 >= 0 ? state.stepKeys.length - 1 : 0;
if (state.activeStep != lastStep && !state.disabled[state.stepKeys[lastStep]]) {
return { ...state, activeStep: lastStep, activeStepKey: state.stepKeys[lastStep] };
}
@@ -195,7 +196,7 @@ function stepsReducer(state: ReadonlyStepsState, args: StepAction): ReadonlyStep
if (indexKeyPair) {
const disabled = { ...state.disabled };
disabled[indexKeyPair.key] = true;
- let {activeStep, activeStepKey} = state;
+ let { activeStep, activeStepKey } = state;
if (state.activeStep == indexKeyPair.index) {
const result = getLastEnabledBeforeGivenStep(state.stepKeys, activeStep, disabled);
activeStep = result.index;