1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-609 Sets | Protocol | Atomic view changes (#2862)

* DROID-609 event blockDataviewViewUpdate + mapping

* DROID-609 list extensions

* DROID-609 updates mapping

* DROID-609 reduce updateView event

* DROID-609 updateView event model

* DROID-609 update lists extensions + tests

* DROID-609 UpdateView event mapping

* DROID-609 tests

* DROID-609 data view stubs

* DROID-609 pr fix
This commit is contained in:
Konstantin Ivanov 2023-01-25 13:27:20 +01:00 committed by GitHub
parent bdd8548695
commit d94b07a338
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 781 additions and 7 deletions

View file

@ -260,6 +260,41 @@ sealed class Event {
val dv: Id,
val sources: List<Id>
) : DataView()
data class UpdateView(
override val context: Id,
val block: Id,
val viewerId: Id,
val filterUpdates: List<DVFilterUpdate>,
val sortUpdates: List<DVSortUpdate>,
val relationUpdates: List<DVViewerRelationUpdate>
) : DataView() {
sealed class DVFilterUpdate {
data class Add(val afterId: Id, val filters: List<DVFilter>) :
DVFilterUpdate()
data class Move(val afterId: Id, val ids: List<Id>) : DVFilterUpdate()
data class Remove(val ids: List<Id>) : DVFilterUpdate()
data class Update(val id: Id, val filter: DVFilter) : DVFilterUpdate()
}
sealed class DVSortUpdate {
data class Add(val afterId: Id, val sorts: List<DVSort>) : DVSortUpdate()
data class Move(val afterId: Id, val ids: List<Id>) : DVSortUpdate()
data class Remove(val ids: List<Id>) : DVSortUpdate()
data class Update(val id: Id, val sort: DVSort) : DVSortUpdate()
}
sealed class DVViewerRelationUpdate {
data class Add(val afterId: Id, val relations: List<DVViewerRelation>) :
DVViewerRelationUpdate()
data class Move(val afterId: Id, val ids: List<Id>) : DVViewerRelationUpdate()
data class Remove(val ids: List<Id>) : DVViewerRelationUpdate()
data class Update(val id: Id, val relation: DVViewerRelation) :
DVViewerRelationUpdate()
}
}
}
}
}

View file

@ -77,4 +77,37 @@ inline fun <reified T> Fragment.withParent(action: T.() -> Unit) {
(parentFragment as T).action()
}
fun MatchResult?.parseMatchedInt(index: Int): Int? = this?.groups?.get(index)?.value?.toIntOrNull()
fun MatchResult?.parseMatchedInt(index: Int): Int? = this?.groups?.get(index)?.value?.toIntOrNull()
/**
* Adds items after the index meeting a [predicateIndex]
*/
fun <T> MutableList<T>.addAfterIndexInLine(
predicateIndex: (T) -> Boolean,
items: List<T>
) {
val newIndex = indexOfFirst(predicateIndex)
if (newIndex in 0 until size) {
addAll(newIndex + 1, items)
} else {
addAll(size, items)
}
}
/**
* Moves all items meeting a [predicateMove] after the index meeting a [predicateIndex]
*/
fun <T> MutableList<T>.moveAfterIndexInLine(
predicateIndex: (T) -> Boolean,
predicateMove: (T) -> Boolean
) {
val split = partition(predicateMove)
clear()
addAll(split.second)
val newIndex = indexOfFirst(predicateIndex)
if (newIndex in 0 until size) {
addAll(newIndex + 1, split.first)
} else {
addAll(size, split.first)
}
}

View file

@ -1,5 +1,7 @@
package com.anytypeio.anytype
import com.anytypeio.anytype.core_utils.ext.addAfterIndexInLine
import com.anytypeio.anytype.core_utils.ext.moveAfterIndexInLine
import com.anytypeio.anytype.core_utils.ext.shift
import com.anytypeio.anytype.core_utils.ext.swap
import org.junit.Assert.assertEquals
@ -41,4 +43,69 @@ class UtilsTest {
.shift(4, 0)
assertEquals(testList2, shiftList3)
}
@Test
fun `when predicate index is true, should move all elements after this index`() {
list.moveAfterIndexInLine(
predicateIndex = { it == 9 },
predicateMove = { i -> listOf(0, 1, 4, 36, 81).contains(i) }
)
val expected = mutableListOf(9, 0, 1, 4, 36, 81, 16, 25, 49, 64)
assertEquals(expected, list)
}
@Test
fun `when predicate index is false, should move all elements at the and`() {
list.moveAfterIndexInLine(
predicateIndex = { it == 91 },
predicateMove = { i -> listOf(0, 1, 4, 36, 81).contains(i) }
)
val expected = mutableListOf(9, 16, 25, 49, 64, 0, 1, 4, 36, 81)
assertEquals(expected, list)
}
@Test
fun `when predicate index is true and predicateMove is false, should not change the list`() {
list.moveAfterIndexInLine(
predicateIndex = { it == 9 },
predicateMove = { i -> listOf(10, 11, 14, 181).contains(i) }
)
val expected = mutableListOf(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
assertEquals(expected, list)
}
@Test
fun `when predicate index is true, should add elements after this index`() {
list.addAfterIndexInLine(
predicateIndex = { it == 9 },
items = listOf(10, 11, 120),
)
val expected = mutableListOf(0, 1, 4, 9, 10, 11, 120, 16, 25, 36, 49, 64, 81)
assertEquals(expected, list)
}
@Test
fun `when predicate index is false, should add all items at the end`() {
list.addAfterIndexInLine(
predicateIndex = { it == 19 },
items = listOf(10, 11, 120),
)
val expected = mutableListOf(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 10, 11, 120)
assertEquals(expected, list)
}
}

View file

@ -29,14 +29,12 @@ class MiddlewareEventChannel(
msg.blockSetAlign,
msg.blockSetDiv,
msg.blockSetRelation,
//msg.blockDataviewRecordsSet,
msg.blockDataviewRelationSet,
//msg.blockDataviewRecordsUpdate,
msg.blockDataviewViewDelete,
msg.blockDataviewViewSet,
msg.objectRelationsAmend,
msg.objectRelationsRemove,
//msg.objectRelationsSet
msg.blockDataviewViewUpdate
)
return events.any { it != null }
}

View file

@ -225,5 +225,23 @@ fun anytype.Event.Message.toCoreModels(
keys = event.relationKeys
)
}
blockDataviewViewUpdate != null -> {
val event = blockDataviewViewUpdate
checkNotNull(event)
Event.Command.DataView.UpdateView(
context = context,
block = event.id,
viewerId = event.viewId,
filterUpdates = event.filter.mapNotNull { filter ->
filter.toCoreModels()
},
sortUpdates = event.sort.mapNotNull { sort ->
sort.toCoreModels()
},
relationUpdates = event.relation.mapNotNull { relation ->
relation.toCoreModels()
}
)
}
else -> null
}

View file

@ -43,7 +43,9 @@ typealias MDVFilterOperator = anytype.model.Block.Content.Dataview.Filter.Operat
typealias MDVRelation = anytype.model.Block.Content.Dataview.Relation
typealias MDVDateFormat = anytype.model.Block.Content.Dataview.Relation.DateFormat
typealias MDVTimeFormat = anytype.model.Block.Content.Dataview.Relation.TimeFormat
typealias MDVFilterUpdate = anytype.Event.Block.Dataview.ViewUpdate.Filter
typealias MDVSortUpdate = anytype.Event.Block.Dataview.ViewUpdate.Sort
typealias MDVRelationUpdate = anytype.Event.Block.Dataview.ViewUpdate.Relation
typealias MObjectType = anytype.model.ObjectType
typealias MSmartBlockType = anytype.model.SmartBlockType

View file

@ -2,9 +2,129 @@ package com.anytypeio.anytype.middleware.mappers
import anytype.Event
import com.anytypeio.anytype.core_models.SearchResult
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVFilterUpdate
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVSortUpdate
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVViewerRelationUpdate
fun Event.Object.Subscription.Counters.parse() : SearchResult.Counter = SearchResult.Counter(
fun Event.Object.Subscription.Counters.parse(): SearchResult.Counter = SearchResult.Counter(
total = total.toInt(),
prev = prevCount.toInt(),
next = nextCount.toInt()
)
)
fun MDVFilterUpdate.toCoreModels(): DVFilterUpdate? {
val filter = this
if (filter.add != null) {
val add = filter.add
checkNotNull(add)
return DVFilterUpdate.Add(
filters = add.items.map { it.toCoreModels() },
afterId = add.afterId
)
}
if (filter.move != null) {
val move = filter.move
checkNotNull(move)
return DVFilterUpdate.Move(
afterId = move.afterId,
ids = move.ids,
)
}
if (filter.remove != null) {
val remove = filter.remove
checkNotNull(remove)
return DVFilterUpdate.Remove(
ids = remove.ids,
)
}
if (filter.update != null) {
val update = filter.update
checkNotNull(update)
val item = update.item
if (item != null) {
return DVFilterUpdate.Update(
id = update.id,
filter = item.toCoreModels()
)
}
}
return null
}
fun MDVSortUpdate.toCoreModels(): DVSortUpdate? {
val sort = this
if (sort.add != null) {
val add = sort.add
checkNotNull(add)
return DVSortUpdate.Add(
sorts = add.items.map { it.toCoreModels() },
afterId = add.afterId
)
}
if (sort.move != null) {
val move = sort.move
checkNotNull(move)
return DVSortUpdate.Move(
afterId = move.afterId,
ids = move.ids,
)
}
if (sort.remove != null) {
val remove = sort.remove
checkNotNull(remove)
return DVSortUpdate.Remove(
ids = remove.ids,
)
}
if (sort.update != null) {
val update = sort.update
checkNotNull(update)
val item = update.item
if (item != null) {
return DVSortUpdate.Update(
id = update.id,
sort = item.toCoreModels()
)
}
}
return null
}
fun MDVRelationUpdate.toCoreModels(): DVViewerRelationUpdate? {
val relation = this
if (relation.add != null) {
val add = relation.add
checkNotNull(add)
return DVViewerRelationUpdate.Add(
relations = add.items.map { it.toCoreModels() },
afterId = add.afterId
)
}
if (relation.move != null) {
val move = relation.move
checkNotNull(move)
return DVViewerRelationUpdate.Move(
afterId = move.afterId,
ids = move.ids,
)
}
if (relation.remove != null) {
val remove = relation.remove
checkNotNull(remove)
return DVViewerRelationUpdate.Remove(
ids = remove.ids,
)
}
if (relation.update != null) {
val update = relation.update
checkNotNull(update)
val item = update.item
if (item != null) {
return DVViewerRelationUpdate.Update(
id = update.id,
relation = item.toCoreModels()
)
}
}
return null
}

View file

@ -2,12 +2,17 @@ package com.anytypeio.anytype.presentation.sets
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.DV
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVRecord
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewerRelation
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_utils.ext.addAfterIndexInLine
import com.anytypeio.anytype.core_utils.ext.replace
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.objects.ObjectIcon
@ -19,6 +24,11 @@ import com.anytypeio.anytype.presentation.relations.objectTypeRelation
import com.anytypeio.anytype.presentation.relations.view
import com.anytypeio.anytype.presentation.sets.model.ObjectView
import com.anytypeio.anytype.presentation.sets.model.SimpleRelationView
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVSortUpdate
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVFilterUpdate
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVViewerRelationUpdate
import com.anytypeio.anytype.core_utils.ext.mapInPlace
import com.anytypeio.anytype.core_utils.ext.moveAfterIndexInLine
fun ObjectSet.featuredRelations(
ctx: Id,
@ -179,4 +189,97 @@ fun ObjectWrapper.Basic.toObjectView(urlBuilder: UrlBuilder): ObjectView = when
types = type,
isRelation = type.contains(ObjectTypeIds.RELATION)
)
}
fun List<DVFilter>.updateFilters(updates: List<DVFilterUpdate>): List<DVFilter> {
val filters = this.toMutableList()
updates.forEach { update ->
when (update) {
is DVFilterUpdate.Add -> {
filters.addAfterIndexInLine(
predicateIndex = { it.relationKey == update.afterId },
items = update.filters
)
}
is DVFilterUpdate.Move -> {
filters.moveAfterIndexInLine(
predicateIndex = { filter -> filter.relationKey == update.afterId },
predicateMove = { filter -> update.ids.contains(filter.relationKey) }
)
}
is DVFilterUpdate.Remove -> {
filters.retainAll {
!update.ids.contains(it.relationKey)
}
}
is DVFilterUpdate.Update -> {
filters.mapInPlace { filter ->
if (filter.relationKey == update.id) update.filter else filter
}
}
}
}
return filters
}
fun List<DVSort>.updateSorts(updates: List<DVSortUpdate>): List<DVSort> {
val sorts = this.toMutableList()
updates.forEach { update ->
when (update) {
is DVSortUpdate.Add -> {
sorts.addAfterIndexInLine(
predicateIndex = { it.relationKey == update.afterId },
items = update.sorts
)
}
is DVSortUpdate.Move -> {
sorts.moveAfterIndexInLine(
predicateIndex = { sort -> sort.relationKey == update.afterId },
predicateMove = { sort -> update.ids.contains(sort.relationKey) }
)
}
is DVSortUpdate.Remove -> {
sorts.retainAll {
!update.ids.contains(it.relationKey)
}
}
is DVSortUpdate.Update -> {
sorts.mapInPlace { sort ->
if (sort.relationKey == update.id) update.sort else sort
}
}
}
}
return sorts
}
fun List<DVViewerRelation>.updateViewerRelations(updates: List<DVViewerRelationUpdate>): List<DVViewerRelation> {
val relations = this.toMutableList()
updates.forEach { update ->
when (update) {
is DVViewerRelationUpdate.Add -> {
relations.addAfterIndexInLine(
predicateIndex = { it.key == update.afterId },
items = update.relations
)
}
is DVViewerRelationUpdate.Move -> {
relations.moveAfterIndexInLine(
predicateIndex = { relation -> relation.key == update.afterId },
predicateMove = { relation -> update.ids.contains(relation.key) }
)
}
is DVViewerRelationUpdate.Remove -> {
relations.retainAll {
!update.ids.contains(it.key)
}
}
is DVViewerRelationUpdate.Update -> {
relations.mapInPlace { relation ->
if (relation.key == update.id) update.relation else relation
}
}
}
}
return relations
}

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.presentation.sets
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.DV
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Event.Command
@ -146,6 +147,53 @@ class ObjectSetReducer {
}
)
}
is Command.DataView.UpdateView -> {
val updatedBlocks = state.blocks.map { block: Block ->
val content = block.content
if (block.id == event.block && content is DV) {
block.copy(
content = content.copy(
viewers = content.viewers.map { viewer ->
if (viewer.id == event.viewerId) {
val filters = if (event.filterUpdates.isNotEmpty()) {
viewer.filters.updateFilters(
updates = event.filterUpdates
)
} else {
viewer.filters
}
val sorts = if (event.sortUpdates.isNotEmpty()) {
viewer.sorts.updateSorts(
updates = event.sortUpdates
)
} else {
viewer.sorts
}
val viewerRelations =
if (event.relationUpdates.isNotEmpty()) {
viewer.viewerRelations.updateViewerRelations(
updates = event.relationUpdates
)
} else {
viewer.viewerRelations
}
viewer.copy(
filters = filters,
sorts = sorts,
viewerRelations = viewerRelations
)
} else {
viewer
}
}
)
)
} else {
block
}
}
state.copy(blocks = updatedBlocks)
}
is Command.Details.Set -> {
state.copy(
details = state.details.toMutableMap().apply {

View file

@ -1,8 +1,15 @@
package com.anytypeio.anytype.presentation.sets
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.StubDataView
import com.anytypeio.anytype.core_models.StubDataViewView
import com.anytypeio.anytype.core_models.StubDataViewViewRelation
import com.anytypeio.anytype.core_models.StubFilter
import com.anytypeio.anytype.core_models.StubSort
import com.anytypeio.anytype.core_models.StubTitle
import com.anytypeio.anytype.test_utils.MockDataFactory
import org.junit.Before
import org.junit.Test
@ -361,4 +368,322 @@ class ObjectSetReducerTest {
assertEquals(expected, result)
}
@Test
fun `when getting add, move, update, remove sorts events, should proper update viewer`() {
val context = MockDataFactory.randomUuid()
val title = StubTitle()
val relationKey1 = MockDataFactory.randomUuid()
val relationKey2 = MockDataFactory.randomUuid()
val relationKey3 = MockDataFactory.randomUuid()
val relationKey4 = MockDataFactory.randomUuid()
val relationKey5 = MockDataFactory.randomUuid()
val sort1 = StubSort(relationKey = relationKey1)
val sort2 = StubSort(relationKey = relationKey2)
val sort3 = StubSort(relationKey = relationKey3)
val sort4 = StubSort(relationKey = relationKey4)
val sort5 = StubSort(relationKey = relationKey5)
val viewer1 = StubDataViewView(
type = Block.Content.DataView.Viewer.Type.BOARD,
sorts = listOf(sort1, sort2, sort3, sort4)
)
val viewer2 = StubDataViewView(
type = Block.Content.DataView.Viewer.Type.GRID,
sorts = listOf(sort1)
)
val dataView = StubDataView(
id = MockDataFactory.randomUuid(),
views = listOf(viewer1, viewer2),
sources = listOf(MockDataFactory.randomString())
)
val blocks = listOf(title, dataView)
val objectSet = ObjectSet(blocks = blocks)
// TESTING
val event = Event.Command.DataView.UpdateView(
context = context,
block = dataView.id,
viewerId = viewer1.id,
sortUpdates = listOf(
Event.Command.DataView.UpdateView.DVSortUpdate.Move(
afterId = relationKey3,
ids = listOf(relationKey1, relationKey2)
),
Event.Command.DataView.UpdateView.DVSortUpdate.Add(
afterId = relationKey3,
sorts = listOf(sort5)
),
Event.Command.DataView.UpdateView.DVSortUpdate.Update(
id = relationKey2,
sort = DVSort(relationKey2, Block.Content.DataView.Sort.Type.DESC)
),
Event.Command.DataView.UpdateView.DVSortUpdate.Remove(
ids = listOf(relationKey1)
)
),
filterUpdates = listOf(),
relationUpdates = listOf()
)
val result = reducer.reduce(state = objectSet, events = listOf(event))
val expectedSorts = listOf(
DVSort(
relationKey = relationKey3,
type = Block.Content.DataView.Sort.Type.ASC
),
DVSort(
relationKey = relationKey5,
type = Block.Content.DataView.Sort.Type.ASC
),
DVSort(
relationKey = relationKey2,
type = Block.Content.DataView.Sort.Type.DESC
),
DVSort(
relationKey = relationKey4,
type = Block.Content.DataView.Sort.Type.ASC
)
)
val expectedDataView = Block(
id = dataView.id,
content = Block.Content.DataView(
sources = (dataView.content as Block.Content.DataView).sources,
viewers = listOf(
Block.Content.DataView.Viewer(
id = viewer1.id,
name = viewer1.name,
type = viewer1.type,
viewerRelations = viewer1.viewerRelations,
sorts = expectedSorts,
filters = viewer1.filters
),
Block.Content.DataView.Viewer(
id = viewer2.id,
name = viewer2.name,
type = Block.Content.DataView.Viewer.Type.GRID,
viewerRelations = viewer2.viewerRelations,
sorts = listOf(sort1),
filters = listOf()
)
),
relations = listOf()
),
fields = Block.Fields.empty(),
children = listOf()
)
val expected = ObjectSetReducer.Transformation(
state = ObjectSet(blocks = listOf(title, expectedDataView)),
effects = emptyList()
)
assertEquals(expected, result)
}
@Test
fun `when getting add, move, update, remove filters events, should proper update viewer`() {
val context = MockDataFactory.randomUuid()
val title = StubTitle()
val relationKey1 = MockDataFactory.randomUuid()
val relationKey2 = MockDataFactory.randomUuid()
val relationKey3 = MockDataFactory.randomUuid()
val relationKey4 = MockDataFactory.randomUuid()
val relationKey5 = MockDataFactory.randomUuid()
val filter1 = StubFilter(relationKey = relationKey1)
val filter2 = StubFilter(relationKey = relationKey2)
val filter3 = StubFilter(relationKey = relationKey3)
val filter4 = StubFilter(relationKey = relationKey4)
val filter5 = StubFilter(relationKey = relationKey5)
val viewer1 = StubDataViewView(
type = Block.Content.DataView.Viewer.Type.BOARD,
filters = listOf(filter1, filter2, filter3, filter4)
)
val dataView = StubDataView(
id = MockDataFactory.randomUuid(),
views = listOf(viewer1),
sources = listOf(MockDataFactory.randomString())
)
val blocks = listOf(title, dataView)
val objectSet = ObjectSet(blocks = blocks)
// TESTING
val filter2Value = MockDataFactory.randomString()
val event = Event.Command.DataView.UpdateView(
context = context,
block = dataView.id,
viewerId = viewer1.id,
sortUpdates = listOf(),
filterUpdates = listOf(
Event.Command.DataView.UpdateView.DVFilterUpdate.Move(
afterId = relationKey3,
ids = listOf(relationKey1, relationKey2)
),
Event.Command.DataView.UpdateView.DVFilterUpdate.Add(
afterId = relationKey3,
filters = listOf(filter5)
),
Event.Command.DataView.UpdateView.DVFilterUpdate.Update(
id = relationKey2,
filter = filter2.copy(
value = filter2Value
)
),
Event.Command.DataView.UpdateView.DVFilterUpdate.Remove(
ids = listOf(relationKey1)
)
),
relationUpdates = listOf()
)
val result = reducer.reduce(state = objectSet, events = listOf(event))
val expectedFilters = listOf(
filter3,
filter5,
filter2.copy(
value = filter2Value
),
filter4
)
val expectedDataView = Block(
id = dataView.id,
content = Block.Content.DataView(
sources = (dataView.content as Block.Content.DataView).sources,
viewers = listOf(
Block.Content.DataView.Viewer(
id = viewer1.id,
name = viewer1.name,
type = viewer1.type,
viewerRelations = viewer1.viewerRelations,
sorts = viewer1.sorts,
filters = expectedFilters
)
),
relations = listOf()
),
fields = Block.Fields.empty(),
children = listOf()
)
val expected = ObjectSetReducer.Transformation(
state = ObjectSet(blocks = listOf(title, expectedDataView)),
effects = emptyList()
)
assertEquals(expected, result)
}
@Test
fun `when getting add, move, update, remove relations events, should proper update viewer`() {
val context = MockDataFactory.randomUuid()
val title = StubTitle()
val relationKey1 = MockDataFactory.randomUuid()
val relationKey2 = MockDataFactory.randomUuid()
val relationKey3 = MockDataFactory.randomUuid()
val relationKey4 = MockDataFactory.randomUuid()
val relationKey5 = MockDataFactory.randomUuid()
val relation1 = StubDataViewViewRelation(key = relationKey1)
val relation2 = StubDataViewViewRelation(key = relationKey2)
val relation3 = StubDataViewViewRelation(key = relationKey3)
val relation4 = StubDataViewViewRelation(key = relationKey4)
val relation5 = StubDataViewViewRelation(key = relationKey5)
val viewer1 = StubDataViewView(
type = Block.Content.DataView.Viewer.Type.BOARD,
viewerRelations = listOf(relation1, relation2, relation3, relation4)
)
val dataView = StubDataView(
id = MockDataFactory.randomUuid(),
views = listOf(viewer1),
sources = listOf(MockDataFactory.randomString())
)
val blocks = listOf(title, dataView)
val objectSet = ObjectSet(blocks = blocks)
// TESTING
val relation2IsVisible = !relation2.isVisible
val event = Event.Command.DataView.UpdateView(
context = context,
block = dataView.id,
viewerId = viewer1.id,
sortUpdates = listOf(),
filterUpdates = listOf(),
relationUpdates = listOf(
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Move(
afterId = relationKey3,
ids = listOf(relationKey1, relationKey2)
),
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Add(
afterId = relationKey3,
relations = listOf(relation5)
),
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Update(
id = relationKey2,
relation = relation2.copy(
isVisible = relation2IsVisible
)
),
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Remove(
ids = listOf(relationKey1)
)
)
)
val result = reducer.reduce(state = objectSet, events = listOf(event))
val expectedRelations = listOf(
relation3,
relation5,
relation2.copy(
isVisible = relation2IsVisible
),
relation4
)
val expectedDataView = Block(
id = dataView.id,
content = Block.Content.DataView(
sources = (dataView.content as Block.Content.DataView).sources,
viewers = listOf(
Block.Content.DataView.Viewer(
id = viewer1.id,
name = viewer1.name,
type = viewer1.type,
viewerRelations = expectedRelations,
sorts = viewer1.sorts,
filters = viewer1.filters
)
),
relations = listOf()
),
fields = Block.Fields.empty(),
children = listOf()
)
val expected = ObjectSetReducer.Transformation(
state = ObjectSet(blocks = listOf(title, expectedDataView)),
effects = emptyList()
)
assertEquals(expected, result)
}
}

View file

@ -41,4 +41,29 @@ fun StubDataViewViewRelation(
) : DVViewerRelation = DVViewerRelation(
key = key,
isVisible = isVisible
)
fun StubSort(
relationKey: Key = MockDataFactory.randomUuid(),
type: DVSortType = DVSortType.ASC
): DVSort = DVSort(
relationKey = relationKey,
type = type
)
fun StubFilter(
relationKey: Key = MockDataFactory.randomUuid(),
relationFormat: RelationFormat = RelationFormat.LONG_TEXT,
operator: DVFilterOperator = DVFilterOperator.AND,
condition: DVFilterCondition = DVFilterCondition.EQUAL,
quickOption: DVFilterQuickOption = DVFilterQuickOption.EXACT_DATE,
value: Any? = null
): DVFilter = DVFilter(
relationKey = relationKey,
relationFormat = relationFormat,
operator = operator,
condition = condition,
quickOption = quickOption,
value = value
)