[GH-1368] Add empty / not empty table aggregations (#1557)
This adds new aggregations for counting empty / not empty cards as well as computing the respective percentage. Fixes: #1368
This commit is contained in:
parent
40b9e3341f
commit
5204e2d080
5 changed files with 197 additions and 4 deletions
|
@ -151,6 +151,8 @@ describe('components/calculations/calculation logic', () => {
|
|||
updatedBy: {id: 'property_lastUpdatedBy', type: 'updatedBy', name: '', options: []},
|
||||
}
|
||||
|
||||
const autofilledProperties = new Set([properties.createdBy, properties.createdTime, properties.updatedBy, properties.updatedTime])
|
||||
|
||||
const intl = createIntl({locale: 'en-us'})
|
||||
|
||||
// testing count
|
||||
|
@ -160,6 +162,34 @@ describe('components/calculations/calculation logic', () => {
|
|||
})
|
||||
})
|
||||
|
||||
// testing count empty
|
||||
Object.values(properties).filter((p) => !autofilledProperties.has(p)).forEach((property) => {
|
||||
it(`should correctly count empty for property type "${property.type}"`, function() {
|
||||
expect(Calculations.countEmpty(cards, property, intl)).toBe('1')
|
||||
})
|
||||
})
|
||||
|
||||
// testing percent empty
|
||||
Object.values(properties).filter((p) => !autofilledProperties.has(p)).forEach((property) => {
|
||||
it(`should correctly compute empty percent for property type "${property.type}"`, function() {
|
||||
expect(Calculations.percentEmpty(cards, property, intl)).toBe('25%')
|
||||
})
|
||||
})
|
||||
|
||||
// testing count not empty
|
||||
Object.values(properties).filter((p) => !autofilledProperties.has(p)).forEach((property) => {
|
||||
it(`should correctly count not empty for property type "${property.type}"`, function() {
|
||||
expect(Calculations.countNotEmpty(cards, property, intl)).toBe('3')
|
||||
})
|
||||
})
|
||||
|
||||
// testing percent not empty
|
||||
Object.values(properties).filter((p) => !autofilledProperties.has(p)).forEach((property) => {
|
||||
it(`should correctly compute not empty percent for property type "${property.type}"`, function() {
|
||||
expect(Calculations.percentNotEmpty(cards, property, intl)).toBe('75%')
|
||||
})
|
||||
})
|
||||
|
||||
// testing countValues
|
||||
const countValueTests: Record<string, string> = {
|
||||
text: '3',
|
||||
|
|
|
@ -53,6 +53,28 @@ function count(cards: readonly Card[], property: IPropertyTemplate): string {
|
|||
return String(cards.length)
|
||||
}
|
||||
|
||||
function countEmpty(cards: readonly Card[], property: IPropertyTemplate): string {
|
||||
return String(cards.length - cardsWithValue(cards, property).length)
|
||||
}
|
||||
|
||||
function countNotEmpty(cards: readonly Card[], property: IPropertyTemplate): string {
|
||||
return String(cardsWithValue(cards, property).length)
|
||||
}
|
||||
|
||||
function percentEmpty(cards: readonly Card[], property: IPropertyTemplate): string {
|
||||
if (cards.length === 0) {
|
||||
return ''
|
||||
}
|
||||
return String((((cards.length - cardsWithValue(cards, property).length) / cards.length) * 100).toFixed(0)) + '%'
|
||||
}
|
||||
|
||||
function percentNotEmpty(cards: readonly Card[], property: IPropertyTemplate): string {
|
||||
if (cards.length === 0) {
|
||||
return ''
|
||||
}
|
||||
return String(((cardsWithValue(cards, property).length / cards.length) * 100).toFixed(0)) + '%'
|
||||
}
|
||||
|
||||
function countValueHelper(cards: readonly Card[], property: IPropertyTemplate): number {
|
||||
let values = 0
|
||||
|
||||
|
@ -274,6 +296,10 @@ function dateRange(cards: readonly Card[], property: IPropertyTemplate): string
|
|||
|
||||
const Calculations: Record<string, (cards: readonly Card[], property: IPropertyTemplate, intl: IntlShape) => string> = {
|
||||
count,
|
||||
countEmpty,
|
||||
countNotEmpty,
|
||||
percentEmpty,
|
||||
percentNotEmpty,
|
||||
countValue,
|
||||
countUniqueValue,
|
||||
countChecked,
|
||||
|
|
|
@ -19,6 +19,10 @@ type Option = {
|
|||
export const Options:Record<string, Option> = {
|
||||
none: {value: 'none', label: 'None', displayName: 'Calculate'},
|
||||
count: {value: 'count', label: 'Count', displayName: 'Count'},
|
||||
countEmpty: {value: 'countEmpty', label: 'Count Empty', displayName: 'Empty'},
|
||||
countNotEmpty: {value: 'countNotEmpty', label: 'Count Not Empty', displayName: 'Not Empty'},
|
||||
percentEmpty: {value: 'percentEmpty', label: 'Percent Empty', displayName: 'Empty'},
|
||||
percentNotEmpty: {value: 'percentNotEmpty', label: 'Percent Not Empty', displayName: 'Not Empty'},
|
||||
countValue: {value: 'countValue', label: 'Count Value', displayName: 'Values'},
|
||||
countChecked: {value: 'countChecked', label: 'Count Checked', displayName: 'Checked'},
|
||||
percentChecked: {value: 'percentChecked', label: 'Percent Checked', displayName: 'Checked'},
|
||||
|
@ -37,7 +41,8 @@ export const Options:Record<string, Option> = {
|
|||
}
|
||||
|
||||
export const optionsByType: Map<string, Option[]> = new Map([
|
||||
['common', [Options.none, Options.count, Options.countValue, Options.countUniqueValue]],
|
||||
['common', [Options.none, Options.count, Options.countEmpty, Options.countNotEmpty, Options.percentEmpty,
|
||||
Options.percentNotEmpty, 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]],
|
||||
['date', [Options.earliest, Options.latest, Options.dateRange]],
|
||||
|
|
|
@ -45,7 +45,7 @@ exports[`components/kanban/calculation/KanbanCalculation calculations menu open
|
|||
<span
|
||||
id="aria-context"
|
||||
>
|
||||
3 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
7 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
</span>
|
||||
</span>
|
||||
<div
|
||||
|
@ -115,6 +115,50 @@ exports[`components/kanban/calculation/KanbanCalculation calculations menu open
|
|||
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
|
|
|
@ -99,7 +99,7 @@ exports[`components/kanban/calculations/KanbanCalculationOptions with menu open
|
|||
<span
|
||||
id="aria-context"
|
||||
>
|
||||
3 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
7 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
</span>
|
||||
</span>
|
||||
<div
|
||||
|
@ -169,6 +169,50 @@ exports[`components/kanban/calculations/KanbanCalculationOptions with menu open
|
|||
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
|
@ -219,7 +263,7 @@ exports[`components/kanban/calculations/KanbanCalculationOptions with submenu op
|
|||
<span
|
||||
id="aria-context"
|
||||
>
|
||||
3 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
7 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
|
||||
</span>
|
||||
</span>
|
||||
<div
|
||||
|
@ -289,6 +333,50 @@ exports[`components/kanban/calculations/KanbanCalculationOptions with submenu op
|
|||
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Count Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
<span>
|
||||
Percent Not Empty
|
||||
|
||||
<i
|
||||
class="CompassIcon icon-chevron-right ChevronRightIcon"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="KanbanCalculationOptions_CustomOption "
|
||||
>
|
||||
|
|
Loading…
Reference in a new issue