From 2693b401fda60e7650ab7c9790436875aa3190f1 Mon Sep 17 00:00:00 2001 From: d1snin Date: Thu, 9 Nov 2023 21:35:55 +0300 Subject: [PATCH] feat: implement in-row block positioning --- .../d1s/beam/client/app/state/BlockContext.kt | 7 ++++++- .../d1s/beam/client/BlockModificationBuilder.kt | 4 ++++ .../kotlin/dev/d1s/beam/commons/Block.kt | 6 ++++++ .../beam/commons/validation/BlockValidation.kt | 13 ++++++++++++- .../beam/commons/validation/RowValidation.kt | 2 +- .../beam/daemon/converter/BlockDtoConverter.kt | 1 + .../converter/BlockModificationDtoConverter.kt | 1 + .../d1s/beam/daemon/database/BlockRepository.kt | 14 +------------- .../dev/d1s/beam/daemon/database/Blocks.kt | 4 ++++ .../d1s/beam/daemon/database/RowRepository.kt | 5 +---- .../dev/d1s/beam/daemon/entity/BlockEntity.kt | 5 ++++- .../dev/d1s/beam/daemon/service/BlockService.kt | 17 +++++++++++++++-- config/db/changelog.json | 6 ++++++ http/daemon.http | 1 + 14 files changed, 63 insertions(+), 23 deletions(-) diff --git a/beam-client-app/src/jvmMain/kotlin/dev/d1s/beam/client/app/state/BlockContext.kt b/beam-client-app/src/jvmMain/kotlin/dev/d1s/beam/client/app/state/BlockContext.kt index 88a1f8f3..f8139ced 100644 --- a/beam-client-app/src/jvmMain/kotlin/dev/d1s/beam/client/app/state/BlockContext.kt +++ b/beam-client-app/src/jvmMain/kotlin/dev/d1s/beam/client/app/state/BlockContext.kt @@ -42,6 +42,10 @@ public class BlockContext internal constructor( modifyBlock(row = row()) } + public suspend fun setIndex(index: suspend () -> BlockIndex?) { + modifyBlock(index = index()) + } + public suspend fun setSize(size: suspend () -> BlockSize) { modifyBlock(size = size()) } @@ -58,12 +62,13 @@ public class BlockContext internal constructor( private suspend fun modifyBlock( row: RowIndex = block.row, + index: BlockIndex? = block.index, size: BlockSize = block.size, entities: ContentEntities = block.entities, metadata: Metadata = block.metadata, ) { operationLock.withLock { - val modification = BlockModification(row, size, entities, metadata, block.spaceId) + val modification = BlockModification(row, index, size, entities, metadata, block.spaceId) log.d { "Modifying block with the following data: $modification" diff --git a/beam-client/src/commonMain/kotlin/dev/d1s/beam/client/BlockModificationBuilder.kt b/beam-client/src/commonMain/kotlin/dev/d1s/beam/client/BlockModificationBuilder.kt index 60b90517..4d722f64 100644 --- a/beam-client/src/commonMain/kotlin/dev/d1s/beam/client/BlockModificationBuilder.kt +++ b/beam-client/src/commonMain/kotlin/dev/d1s/beam/client/BlockModificationBuilder.kt @@ -25,6 +25,8 @@ public class BlockModificationBuilder() : ContentEntitiesBuilder() { public var row: RowIndex? = null + public var index: BlockIndex? = null + public var size: BlockSize? = null public var spaceId: SpaceIdentifier? = null @@ -33,6 +35,7 @@ public class BlockModificationBuilder() : ContentEntitiesBuilder() { public constructor(modification: BlockModification) : this() { row = modification.row + index = modification.index size = modification.size entities = modification.entities.toMutableList() metadataBuilder.metadata = modification.metadata.toMutableMap() @@ -50,6 +53,7 @@ public class BlockModificationBuilder() : ContentEntitiesBuilder() { public fun buildBlockModification(): BlockModification = BlockModification( row ?: error("Block row is undefined"), + index, size ?: error("Block size is undefined"), buildContentEntities(), metadataBuilder.buildMetadata(), diff --git a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/Block.kt b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/Block.kt index 4e54eded..7a2cc2d6 100644 --- a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/Block.kt +++ b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/Block.kt @@ -23,10 +23,14 @@ public typealias BlockId = String public typealias Blocks = List +public typealias BlockIndex = Int + public sealed interface AbstractBlock { public val row: RowIndex + public val index: BlockIndex? + public val size: BlockSize public val entities: ContentEntities @@ -40,6 +44,7 @@ public sealed interface AbstractBlock { public data class Block( val id: BlockId, override val row: RowIndex, + override val index: BlockIndex?, override val size: BlockSize, override val entities: ContentEntities, override val metadata: Metadata, @@ -49,6 +54,7 @@ public data class Block( @Serializable public data class BlockModification( override val row: RowIndex, + override val index: BlockIndex?, override val size: BlockSize, override val entities: ContentEntities, override val metadata: Metadata, diff --git a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/BlockValidation.kt b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/BlockValidation.kt index 98e44ab7..12e236ac 100644 --- a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/BlockValidation.kt +++ b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/BlockValidation.kt @@ -17,13 +17,20 @@ package dev.d1s.beam.commons.validation import dev.d1s.beam.commons.AbstractBlock +import dev.d1s.beam.commons.BlockIndex import io.konform.validation.Validation +import io.konform.validation.ValidationBuilder import io.konform.validation.jsonschema.maxItems import io.konform.validation.jsonschema.minItems +import io.konform.validation.jsonschema.minimum public val validateBlock: Validation = Validation { AbstractBlock::row { - requireValidaRowIndex() + requireValidRowIndex() + } + + AbstractBlock::index ifPresent { + requireValidBlockIndex() } AbstractBlock::entities { @@ -38,4 +45,8 @@ public val validateBlock: Validation = Validation { AbstractBlock::metadata { run(validateMetadata) } +} + +private fun ValidationBuilder.requireValidBlockIndex() { + minimum(0) hint "block index must be greater or equal to 0" } \ No newline at end of file diff --git a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/RowValidation.kt b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/RowValidation.kt index 2a97011b..841a84c1 100644 --- a/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/RowValidation.kt +++ b/beam-common/src/commonMain/kotlin/dev/d1s/beam/commons/validation/RowValidation.kt @@ -20,6 +20,6 @@ import dev.d1s.beam.commons.RowIndex import io.konform.validation.ValidationBuilder import io.konform.validation.jsonschema.minimum -internal fun ValidationBuilder.requireValidaRowIndex() { +internal fun ValidationBuilder.requireValidRowIndex() { minimum(0) hint "row index must be greater or equal to 0" } \ No newline at end of file diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockDtoConverter.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockDtoConverter.kt index ec71cf5b..4d715fa5 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockDtoConverter.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockDtoConverter.kt @@ -28,6 +28,7 @@ class BlockDtoConverter : DtoConverter, KoinComponent { Block( id.toString(), row, + index, size, entities, metadata, diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockModificationDtoConverter.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockModificationDtoConverter.kt index 44cbdb9c..c2f98c35 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockModificationDtoConverter.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/converter/BlockModificationDtoConverter.kt @@ -31,6 +31,7 @@ class BlockModificationDtoConverter : DtoConverter - suspend fun findLatestBlockRowInSpace(space: SpaceEntity): Result - suspend fun findBlocksInSpace(space: SpaceEntity): Result suspend fun updateBlock(block: BlockEntity): Result @@ -71,18 +68,9 @@ class DefaultBlockRepository : BlockRepository, KoinComponent { findBlocksInSpaceAsSequence(space).count() } - override suspend fun findLatestBlockRowInSpace(space: SpaceEntity): Result = - withIoCatching { - findBlocksInSpaceAsSequence(space).sortedByDescending { - it.row - }.first().row - } - override suspend fun findBlocksInSpace(space: SpaceEntity): Result = withIoCatching { - findBlocksInSpaceAsSequence(space).sortedBy { - it.row - }.toList() + findBlocksInSpaceAsSequence(space).toList() } override suspend fun updateBlock(block: BlockEntity): Result = diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/Blocks.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/Blocks.kt index cb9fd272..a28db979 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/Blocks.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/Blocks.kt @@ -33,6 +33,10 @@ object Blocks : UuidIdentifiedEntities(tableName = "block") { it.row } + val index = int("index").bindTo { + it.index + } + val size = enum("size").bindTo { it.size } diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/RowRepository.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/RowRepository.kt index b4b214a3..7d473539 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/RowRepository.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/database/RowRepository.kt @@ -26,10 +26,7 @@ import org.koin.core.component.inject import org.ktorm.database.Database import org.ktorm.dsl.and import org.ktorm.dsl.eq -import org.ktorm.entity.add -import org.ktorm.entity.filter -import org.ktorm.entity.find -import org.ktorm.entity.toList +import org.ktorm.entity.* interface RowRepository { diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/entity/BlockEntity.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/entity/BlockEntity.kt index b80c85df..2ecd7d5c 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/entity/BlockEntity.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/entity/BlockEntity.kt @@ -16,6 +16,7 @@ package dev.d1s.beam.daemon.entity +import dev.d1s.beam.commons.BlockIndex import dev.d1s.beam.commons.BlockSize import dev.d1s.beam.commons.Metadata import dev.d1s.beam.commons.RowIndex @@ -29,6 +30,8 @@ interface BlockEntity : UuidIdentified { var row: RowIndex + var index: BlockIndex? + var size: BlockSize var entities: ContentEntities @@ -41,4 +44,4 @@ interface BlockEntity : UuidIdentified { } val BlockEntity.asString - get() = "BlockEntity{row = $row, size = $size, entities = $entities, metadata = $metadata}" \ No newline at end of file + get() = "BlockEntity{row = $row, index = $index, size = $size, entities = $entities, metadata = $metadata}" \ No newline at end of file diff --git a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/service/BlockService.kt b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/service/BlockService.kt index 88839849..9b0ad975 100644 --- a/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/service/BlockService.kt +++ b/beam-daemon/src/main/kotlin/dev/d1s/beam/daemon/service/BlockService.kt @@ -144,9 +144,17 @@ class DefaultBlockService : BlockService, KoinComponent { val blocks = blockRepository.findBlocksInSpace(space).getOrThrow() - val translatedBlocks = translateOptionally(blocks, languageCode) + val sortedBlocks = blocks + .sortedBy { + it.index ?: MAX_INDEX + } + .sortedBy { + it.row + } - translatedBlocks to blockDtoConverter.convertToDtoListIf(blocks) { + val translatedBlocks = translateOptionally(sortedBlocks, languageCode) + + translatedBlocks to blockDtoConverter.convertToDtoListIf(translatedBlocks) { requireDto } } @@ -253,4 +261,9 @@ class DefaultBlockService : BlockService, KoinComponent { } eventChannel.send(event) } + + private companion object { + + private const val MAX_INDEX = Int.MAX_VALUE + } } \ No newline at end of file diff --git a/config/db/changelog.json b/config/db/changelog.json index 4161e1ff..4b5eec31 100644 --- a/config/db/changelog.json +++ b/config/db/changelog.json @@ -26,6 +26,12 @@ } } }, + { + "column": { + "name": "index", + "type": "integer" + } + }, { "column": { "name": "row", diff --git a/http/daemon.http b/http/daemon.http index 90ca2e6e..64fc77f0 100644 --- a/http/daemon.http +++ b/http/daemon.http @@ -91,6 +91,7 @@ Content-Type: application/json { "row": 0, + "index": null, "size": "MEDIUM", "entities": [ {