diff --git a/webapp/src/components/calculations/calculations.test.tsx b/webapp/src/components/calculations/calculations.test.tsx index ddc14fc14..3d1c30e99 100644 --- a/webapp/src/components/calculations/calculations.test.tsx +++ b/webapp/src/components/calculations/calculations.test.tsx @@ -222,6 +222,46 @@ describe('components/calculations/calculation logic', () => { expect(result).toBe('2') }) + test('countChecked for cards', () => { + const result = Calculations.countChecked(cards, properties.checkbox) + expect(result).toBe('3') + }) + + test('countChecked for cards, one set, other unset', () => { + const result = Calculations.countChecked([card1, card5], properties.checkbox) + expect(result).toBe('1') + }) + + test('countUnchecked for cards', () => { + const result = Calculations.countUnchecked(cards, properties.checkbox) + expect(result).toBe('1') + }) + + test('countUnchecked for cards, two set, one unset', () => { + const result = Calculations.countUnchecked([card1, card1, card5], properties.checkbox) + expect(result).toBe('1') + }) + + test('countUnchecked for cards, one set, other unset', () => { + const result = Calculations.countUnchecked([card1, card5], properties.checkbox) + expect(result).toBe('1') + }) + + test('countUnchecked for cards, one set, two unset', () => { + const result = Calculations.countUnchecked([card1, card5, card5], properties.checkbox) + expect(result).toBe('2') + }) + + test('percentChecked for cards', () => { + const result = Calculations.percentChecked(cards, properties.checkbox) + expect(result).toBe('75%') + }) + + test('percentUnchecked for cards', () => { + const result = Calculations.percentUnchecked(cards, properties.checkbox) + expect(result).toBe('25%') + }) + test('sum', () => { const result = Calculations.sum(cards, properties.number) expect(result).toBe('170') diff --git a/webapp/src/components/calculations/calculations.ts b/webapp/src/components/calculations/calculations.ts index 5153cb900..8b12a3f68 100644 --- a/webapp/src/components/calculations/calculations.ts +++ b/webapp/src/components/calculations/calculations.ts @@ -48,7 +48,7 @@ function count(cards: readonly Card[], property: IPropertyTemplate): string { return String(cards.length) } -function countValue(cards: readonly Card[], property: IPropertyTemplate): string { +function countValueHelper(cards: readonly Card[], property: IPropertyTemplate): number { let values = 0 if (property.type === 'multiSelect') { @@ -60,7 +60,33 @@ function countValue(cards: readonly Card[], property: IPropertyTemplate): string values = cardsWithValue(cards, property).length } - return String(values) + return values +} + +function countValue(cards: readonly Card[], property: IPropertyTemplate): string { + return String(countValueHelper(cards, property)) +} + +function countChecked(cards: readonly Card[], property: IPropertyTemplate): string { + return countValue(cards, property) +} + +function countUnchecked(cards: readonly Card[], property: IPropertyTemplate): string { + return String(cards.length - countValueHelper(cards, property)) +} + +function percentChecked(cards: readonly Card[], property: IPropertyTemplate): string { + const total = cards.length + const checked = countValueHelper(cards, property) + + return String(Math.round((checked * 100) / total)) + '%' +} + +function percentUnchecked(cards: readonly Card[], property: IPropertyTemplate): string { + const total = cards.length + const checked = countValueHelper(cards, property) + + return String(Math.round(((total - checked) * 100) / total)) + '%' } function countUniqueValue(cards: readonly Card[], property: IPropertyTemplate): string { @@ -175,6 +201,10 @@ const Calculations: Record = { none: {value: 'none', label: 'None', displayName: 'Calculate'}, count: {value: 'count', label: 'Count', displayName: 'Count'}, countValue: {value: 'countValue', label: 'Count Value', displayName: 'Values'}, + countChecked: {value: 'countChecked', label: 'Count Checked', displayName: 'Checked'}, + percentChecked: {value: 'percentChecked', label: 'Percent Checked', displayName: 'Checked'}, + percentUnchecked: {value: 'percentUnchecked', label: 'Percent Unchecked', displayName: 'Unchecked'}, + countUnchecked: {value: 'countUnchecked', label: 'Count Unchecked', displayName: 'Unchecked'}, countUniqueValue: {value: 'countUniqueValue', label: 'Count Unique Values', displayName: 'Unique'}, sum: {value: 'sum', label: 'Sum', displayName: 'Sum'}, average: {value: 'average', label: 'Average', displayName: 'Average'}, @@ -31,6 +35,7 @@ const Options:Record = { const optionsByType: Map = new Map([ ['common', [Options.none, Options.count, Options.countValue, Options.countUniqueValue]], + ['checkbox', [Options.countChecked, Options.countUnchecked, Options.percentChecked, Options.percentUnchecked]], ['number', [Options.sum, Options.average, Options.median, Options.min, Options.max, Options.range]], ])