feat(ui): add changeNamedCollection util
parent
ea1a9fe545
commit
a51ce4d8a1
|
@ -0,0 +1,64 @@
|
|||
interface Named {
|
||||
name: string
|
||||
}
|
||||
type NamedChanges = Record<string, boolean>
|
||||
|
||||
/**
|
||||
* ComputeNamedChanges computes changes between array of named instances
|
||||
* as a Record with instance name as a key and values indicated addition (true)
|
||||
* or removal (false). Undefined is returned if there are no changes detected.
|
||||
*/
|
||||
export function computeNamedChanges<T extends Named>(
|
||||
prev: T[],
|
||||
next: T[]
|
||||
): NamedChanges | undefined {
|
||||
const retVal = {}
|
||||
// indicate all prev values as removed
|
||||
prev.forEach(({name}) => (retVal[name] = false))
|
||||
// indicate all new values as added, existing as undefined
|
||||
next.forEach(
|
||||
({name}) => (retVal[name] = retVal[name] === false ? undefined : true)
|
||||
)
|
||||
// filter all undefined values
|
||||
let changed = false
|
||||
const onlyChanges = Object.entries(retVal).reduce((acc, [key, value]) => {
|
||||
if (value !== undefined) {
|
||||
changed = true
|
||||
acc[key] = value
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
return changed ? onlyChanges : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* ChangeNamedCollection returns a collection that changes the
|
||||
* supplied named collection according to changeType. True changeType
|
||||
* inserts an element in a sorted way, false removes all elements
|
||||
* of the same name, undefined does nothing and returns the
|
||||
* supplied collection.
|
||||
*/
|
||||
export function changeNamedCollection<T extends Named>(
|
||||
values: T[],
|
||||
element: T,
|
||||
changeType: boolean | undefined
|
||||
): T[] {
|
||||
if (changeType === undefined) {
|
||||
// no changes requested, do nothing
|
||||
return values
|
||||
}
|
||||
if (changeType) {
|
||||
// insert to the existing collection
|
||||
let i = 0
|
||||
for (; i < values.length; i++) {
|
||||
if (values[i].name.localeCompare(element.name) >= 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
const retVal = [...values]
|
||||
retVal.splice(i, 0, element)
|
||||
return retVal
|
||||
}
|
||||
// remove from existing collection
|
||||
return values.filter(({name}) => name !== element.name)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import {
|
||||
computeNamedChanges,
|
||||
changeNamedCollection,
|
||||
} from 'src/admin/util/changeNamedCollection'
|
||||
|
||||
describe('admin/util/changeNamedCollection', () => {
|
||||
describe('computeNamedChanges', () => {
|
||||
it('returns undefined upon no change', () => {
|
||||
expect(computeNamedChanges([], [])).toBe(undefined)
|
||||
expect(computeNamedChanges([{name: 'a'}], [{name: 'a'}])).toBe(undefined)
|
||||
})
|
||||
it('returns value indicating changes', () => {
|
||||
expect(
|
||||
computeNamedChanges([{name: 'a'}, {name: 'b'}], [{name: 'a'}])
|
||||
).toEqual({b: false})
|
||||
expect(
|
||||
computeNamedChanges([{name: 'a'}], [{name: 'a'}, {name: 'b'}])
|
||||
).toEqual({b: true})
|
||||
expect(
|
||||
computeNamedChanges(
|
||||
[{name: 'a'}, {name: 'c'}],
|
||||
[{name: 'a'}, {name: 'b'}]
|
||||
)
|
||||
).toEqual({b: true, c: false})
|
||||
})
|
||||
})
|
||||
describe('changeNamedCollection', () => {
|
||||
it('changes nothing upon no change', () => {
|
||||
const collection = [{name: 'a'}, {name: 'b'}]
|
||||
expect(changeNamedCollection(collection, {name: 'c'}, undefined)).toBe(
|
||||
collection
|
||||
)
|
||||
})
|
||||
it('removes from collection', () => {
|
||||
const collection = [{name: 'a'}, {name: 'b'}]
|
||||
expect(changeNamedCollection(collection, {name: 'a'}, false)).toEqual([
|
||||
{name: 'b'},
|
||||
])
|
||||
expect(changeNamedCollection(collection, {name: 'b'}, false)).toEqual([
|
||||
{name: 'a'},
|
||||
])
|
||||
expect(changeNamedCollection(collection, {name: 'c'}, false)).toEqual(
|
||||
collection
|
||||
)
|
||||
})
|
||||
it('adds to collection', () => {
|
||||
const collection = [{name: 'b'}, {name: 'd'}]
|
||||
expect(changeNamedCollection([], {name: 'a'}, true)).toEqual([
|
||||
{name: 'a'},
|
||||
])
|
||||
expect(changeNamedCollection(collection, {name: 'a'}, true)).toEqual([
|
||||
{name: 'a'},
|
||||
{name: 'b'},
|
||||
{name: 'd'},
|
||||
])
|
||||
expect(changeNamedCollection(collection, {name: 'c'}, true)).toEqual([
|
||||
{name: 'b'},
|
||||
{name: 'c'},
|
||||
{name: 'd'},
|
||||
])
|
||||
expect(changeNamedCollection(collection, {name: 'e'}, true)).toEqual([
|
||||
{name: 'b'},
|
||||
{name: 'd'},
|
||||
{name: 'e'},
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue