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

DROID-26 Sets | Enhancement | Implement relative values for date filters (#2452)

This commit is contained in:
Mikhail 2022-08-02 22:43:31 +03:00 committed by GitHub
parent 34f41296ee
commit 63957db7c2
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 573 additions and 221 deletions

View file

@ -14,6 +14,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_ui.features.relations.RelationTextValueAdapter
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argOrNull
import com.anytypeio.anytype.core_utils.ext.hideKeyboard
import com.anytypeio.anytype.core_utils.ext.normalizeUrl
import com.anytypeio.anytype.core_utils.ext.subscribe
@ -42,6 +43,8 @@ open class RelationTextValueFragment :
private val objectId get() = arg<String>(OBJECT_ID)
private val flow get() = arg<Int>(FLOW_KEY)
private val isLocked get() = arg<Boolean>(LOCKED_KEY)
private val value get() = argOrNull<Long?>(KEY_VALUE)
private val name get() = arg<String>(KEY_NAME)
private val relationValueAdapter by lazy {
RelationTextValueAdapter(
@ -78,11 +81,19 @@ open class RelationTextValueFragment :
jobs += lifecycleScope.subscribe(vm.views) { relationValueAdapter.update(it) }
jobs += lifecycleScope.subscribe(vm.title) { binding.tvRelationHeader.text = it }
super.onStart()
vm.onStart(
relationId = relationId,
recordId = objectId,
isLocked = isLocked
)
if (flow == FLOW_CHANGE_DATE) {
vm.onDateStart(
name = name,
value = value
)
} else {
vm.onStart(
relationId = relationId,
recordId = objectId,
isLocked = isLocked,
)
}
}
override fun onStop() {
@ -177,7 +188,7 @@ open class RelationTextValueFragment :
}
override fun injectDependencies() {
if (flow == FLOW_DATAVIEW) {
if (flow == FLOW_DATAVIEW || flow == FLOW_CHANGE_DATE) {
componentManager().relationTextValueDVComponent.get(ctx).inject(this)
} else {
componentManager().relationTextValueComponent.get(ctx).inject(this)
@ -185,7 +196,7 @@ open class RelationTextValueFragment :
}
override fun releaseDependencies() {
if (flow == FLOW_DATAVIEW) {
if (flow == FLOW_DATAVIEW || flow == FLOW_CHANGE_DATE) {
componentManager().relationTextValueDVComponent.release(ctx)
} else {
componentManager().relationTextValueComponent.release(ctx)
@ -206,7 +217,7 @@ open class RelationTextValueFragment :
relationId: Id,
objectId: Id,
flow: Int = FLOW_DEFAULT,
isLocked: Boolean = false
isLocked: Boolean = false,
) = RelationTextValueFragment().apply {
arguments = bundleOf(
CONTEXT_ID to ctx,
@ -217,14 +228,29 @@ open class RelationTextValueFragment :
)
}
fun new(
ctx: Id,
name: String = "",
value: Long? = null
) = new(ctx, "", "", FLOW_CHANGE_DATE)
.apply {
arguments?.apply {
putString(KEY_NAME, name)
value?.let { putLong(KEY_VALUE, it) }
}
}
const val CONTEXT_ID = "arg.edit-relation-value.context"
const val RELATION_ID = "arg.edit-relation-value.relation.id"
const val OBJECT_ID = "arg.edit-relation-value.object.id"
const val FLOW_KEY = "arg.edit-relation-value.flow"
const val LOCKED_KEY = "arg.edit-relation-value.locked"
const val KEY_VALUE = "arg.edit-relation-value.value"
const val KEY_NAME = "arg.edit-relation-value.name"
const val FLOW_DEFAULT = 0
const val FLOW_DATAVIEW = 1
const val FLOW_CHANGE_DATE = 2
}
interface TextValueEditReceiver {

View file

@ -49,12 +49,6 @@ open class ViewerFilterFragment : BaseBottomSheetFragment<FragmentFilterBinding>
subscribe(binding.addButton.clicks()) { vm.onAddNewFilterClicked() }
subscribe(binding.doneBtn.clicks()) { vm.onDoneButtonClicked() }
subscribe(binding.editBtn.clicks()) { vm.onEditButtonClicked() }
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
with(lifecycleScope) {
subscribe(vm.views) { filterAdapter.update(it) }
subscribe(vm.screenState) { render(it) }
}

View file

@ -22,6 +22,7 @@ import com.anytypeio.anytype.databinding.FragmentCreateOrUpdateFilterBinding
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.sets.filter.FilterViewModel
import com.anytypeio.anytype.presentation.sets.model.Viewer
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment.DatePickerReceiver
import com.anytypeio.anytype.ui.sets.modals.PickFilterConditionFragment
@ -34,11 +35,14 @@ import javax.inject.Inject
open class CreateFilterFromSelectedValueFragment :
BaseFragment<FragmentCreateOrUpdateFilterBinding>(R.layout.fragment_create_or_update_filter),
UpdateConditionActionReceiver,
DatePickerReceiver {
DatePickerReceiver,
RelationTextValueFragment.TextValueEditReceiver {
private val ctx: String get() = arg(CTX_KEY)
private val relation: String get() = arg(RELATION_KEY)
private val helper = FilterHelper()
private lateinit var searchRelationInput: EditText
lateinit var clearSearchText: View
@ -114,6 +118,12 @@ open class CreateFilterFromSelectedValueFragment :
}
}
override fun onTextValueChanged(ctx: Id, text: String, objectId: Id, relationId: Id) {}
override fun onNumberValueChanged(ctx: Id, number: Double?, objectId: Id, relationId: Id) {
helper.handleNumberValueChanged(this, number, vm)
}
override fun onStart() {
super.onStart()
vm.onStart(relationId = relation, filterIndex = FILTER_INDEX_EMPTY)
@ -147,6 +157,13 @@ open class CreateFilterFromSelectedValueFragment :
FilterViewModel.Commands.TagDivider -> setDivider(R.drawable.divider_relation_tag)
FilterViewModel.Commands.ShowInput -> {}
FilterViewModel.Commands.HideInput -> {}
is FilterViewModel.Commands.OpenNumberPicker -> {
helper.handleOpenNumberPicker(
fragment = this,
command = commands,
ctx = ctx
)
}
}
}

View file

@ -0,0 +1,41 @@
package com.anytypeio.anytype.ui.sets.modals.filter
import androidx.fragment.app.Fragment
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.presentation.relations.toName
import com.anytypeio.anytype.presentation.sets.filter.FilterViewModel
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
class FilterHelper {
fun handleOpenNumberPicker(
fragment: Fragment,
command: FilterViewModel.Commands.OpenNumberPicker,
ctx: String,
) {
fragment.arguments?.apply {
putSerializable(KEY_OPTION, command.option)
}
RelationTextValueFragment.new(
ctx = ctx,
name = command.option.toName(),
value = command.value
).show(fragment.childFragmentManager, null)
}
fun handleNumberValueChanged(
fragment: Fragment,
number: Double?,
vm: FilterViewModel
) {
number?.let {
fragment.arguments
?.let { it.getSerializable(KEY_OPTION) as? DVFilterQuickOption? }
?.let {
vm.onExactNumberOfDays(it, number.toLong())
}
}
}
}
private const val KEY_OPTION = "arg.filter-helper.option"

View file

@ -23,6 +23,7 @@ import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.sets.filter.FilterViewModel
import com.anytypeio.anytype.presentation.sets.model.ColumnView
import com.anytypeio.anytype.presentation.sets.model.Viewer
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment.DatePickerReceiver
import com.anytypeio.anytype.ui.sets.modals.PickFilterConditionFragment
@ -33,12 +34,15 @@ import javax.inject.Inject
open class ModifyFilterFromSelectedValueFragment :
BaseBottomSheetFragment<FragmentCreateOrUpdateFilterBinding>(),
UpdateConditionActionReceiver, DatePickerReceiver {
UpdateConditionActionReceiver, DatePickerReceiver,
RelationTextValueFragment.TextValueEditReceiver {
private val ctx: String get() = arg(CTX_KEY)
private val relation: String get() = arg(RELATION_KEY)
private val index: Int get() = arg(IDX_KEY)
private val helper = FilterHelper()
private lateinit var searchRelationInput: EditText
lateinit var clearSearchText: View
@ -136,8 +140,13 @@ open class ModifyFilterFromSelectedValueFragment :
FilterViewModel.Commands.DateDivider -> setDivider(R.drawable.divider_relation_date)
FilterViewModel.Commands.ObjectDivider -> setDivider(R.drawable.divider_relation_object)
FilterViewModel.Commands.TagDivider -> setDivider(R.drawable.divider_relation_tag)
FilterViewModel.Commands.ShowInput -> {}
FilterViewModel.Commands.HideInput -> {}
is FilterViewModel.Commands.OpenNumberPicker -> {
helper.handleOpenNumberPicker(
fragment = this,
command = commands,
ctx = ctx,
)
}
}
}
@ -159,6 +168,12 @@ open class ModifyFilterFromSelectedValueFragment :
vm.onExactDayPicked(timeInSeconds)
}
override fun onTextValueChanged(ctx: Id, text: String, objectId: Id, relationId: Id) {}
override fun onNumberValueChanged(ctx: Id, number: Double?, objectId: Id, relationId: Id) {
helper.handleNumberValueChanged(this, number, vm)
}
override fun onStart() {
super.onStart()
expand()

View file

@ -16,6 +16,7 @@ typealias DVViewerType = Block.Content.DataView.Viewer.Type
typealias DVViewerCardSize= Block.Content.DataView.Viewer.Size
typealias DVFilter = Block.Content.DataView.Filter
typealias DVFilterCondition = Block.Content.DataView.Filter.Condition
typealias DVFilterQuickOption = Block.Content.DataView.Filter.QuickOption
typealias DVFilterOperator = Block.Content.DataView.Filter.Operator
typealias DVSort = Block.Content.DataView.Sort
typealias DVSortType = Block.Content.DataView.Sort.Type

View file

@ -329,6 +329,7 @@ data class Block(
val relationKey: String,
val operator: Operator = Operator.AND,
val condition: Condition,
val quickOption: QuickOption = QuickOption.EXACT_DATE,
val value: Any?
) {
enum class Operator { AND, OR }
@ -337,6 +338,11 @@ data class Block(
LIKE, NOT_LIKE, IN, NOT_IN, EMPTY, NOT_EMPTY, ALL_IN, NOT_ALL_IN, NONE,
EXACT_IN, NOT_EXACT_IN
}
enum class QuickOption {
EXACT_DATE, YESTERDAY, TODAY, TOMORROW, LAST_WEEK, CURRENT_WEEK, NEXT_WEEK,
LAST_MONTH, CURRENT_MONTH, NEXT_MONTH, DAYS_AGO, DAYS_AHEAD,
}
}
}

View file

@ -10,8 +10,8 @@ import com.anytypeio.anytype.presentation.sets.model.CellView
class DVGridCellDateHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(cell: CellView.Date) {
itemView.findViewById<TextView>(R.id.tvText).text = cell.timeInMillis?.formatTimestamp(
isMillis = true,
itemView.findViewById<TextView>(R.id.tvText).text = cell.timeInSecs?.formatTimestamp(
isMillis = false,
format = cell.dateFormat
)
}

View file

@ -2,14 +2,17 @@ package com.anytypeio.anytype.core_ui.features.dataview.modals
import android.widget.ImageView
import android.widget.TextView
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_ui.databinding.ItemDvViewerFilterDateBinding
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.presentation.extension.hasValue
import com.anytypeio.anytype.presentation.relations.toName
import com.anytypeio.anytype.presentation.sets.model.FilterView
class FilterDateViewHolder(val binding: ItemDvViewerFilterDateBinding) : FilterViewHolder(binding.root) {
class FilterDateViewHolder(val binding: ItemDvViewerFilterDateBinding) :
FilterViewHolder(binding.root) {
override val textTitle: TextView get() = binding.tvTitle
override val textCondition: TextView get() = binding.tvCondition
@ -28,7 +31,13 @@ class FilterDateViewHolder(val binding: ItemDvViewerFilterDateBinding) : FilterV
)
if (item.condition.hasValue()) {
binding.tvValue.visible()
binding.tvValue.text = item.filterValue.value?.formatTimestamp(isMillis = true)
binding.tvValue.text = when (item.quickOption) {
DVFilterQuickOption.DAYS_AGO -> "${item.filterValue.value?.toString()} days ago"
DVFilterQuickOption.DAYS_AHEAD -> "${item.filterValue.value?.toString()} days from now"
DVFilterQuickOption.EXACT_DATE -> item.filterValue.value?.formatTimestamp(isMillis = false)
else -> item.quickOption.toName()
}
} else {
binding.tvValue.text = null
binding.tvValue.invisible()

View file

@ -4,6 +4,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemCreateFilterCheckboxBinding
import com.anytypeio.anytype.core_ui.databinding.ItemCreateFilterDateBinding
@ -17,7 +18,6 @@ import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.setDrawableColor
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.presentation.editor.editor.ThemeColor
import com.anytypeio.anytype.presentation.relations.DateDescription
import com.anytypeio.anytype.presentation.sets.filter.CreateFilterView
class CreateFilterAdapter(
@ -172,11 +172,18 @@ class CreateFilterAdapter(
class Date(val binding: ItemCreateFilterDateBinding) : ViewHolder(binding.root) {
fun bind(item: CreateFilterView.Date) = with(binding) {
tvDateTitle.text = item.description
if (item.type == DateDescription.EXACT_DAY) {
tvDate.visible()
tvDate.text = item.timeInMillis.formatTimestamp(isMillis = true)
} else {
tvDate.invisible()
when (item.type) {
DVFilterQuickOption.EXACT_DATE -> {
tvDate.visible()
tvDate.text = item.value.formatTimestamp(isMillis = false)
}
DVFilterQuickOption.DAYS_AGO, DVFilterQuickOption.DAYS_AHEAD -> {
tvDate.visible()
tvDate.text = item.value.toString()
}
else -> {
tvDate.invisible()
}
}
if (item.isSelected) {
iconChecked.visible()

View file

@ -45,6 +45,7 @@
android:layout_marginStart="4dp"
android:layout_marginEnd="12dp"
app:layout_goneMarginEnd="@dimen/dp_20"
android:maxLines="2"
style="@style/ViewerFilterTextValueStyle"
app:layout_constraintBottom_toBottomOf="@+id/tvCondition"
app:layout_constraintEnd_toStartOf="@+id/iconArrow"

View file

@ -103,12 +103,12 @@ class CellViewDiffUtilTest {
val oldCell = CellView.Date(
id = MockDataFactory.randomString(),
key = MockDataFactory.randomString(),
timeInMillis = MockDataFactory.randomLong(),
timeInSecs = MockDataFactory.randomLong(),
dateFormat = MockDataFactory.randomString()
)
val newCell = oldCell.copy(
timeInMillis = MockDataFactory.randomLong()
timeInSecs = MockDataFactory.randomLong()
)
val old = listOf(oldCell)

View file

@ -11,7 +11,7 @@ fun Calendar.isSameDay(compare: Calendar): Boolean =
fun Calendar.timeInSeconds() = this.timeInMillis / 1000
fun getTodayTimeUnit() = Calendar.getInstance()
fun getTodayTimeUnit(): Calendar = Calendar.getInstance()
fun getTomorrowTimeUnit(): Calendar = Calendar.getInstance().apply { add(Calendar.DATE, 1) }
fun getYesterdayTimeUnit(): Calendar = Calendar.getInstance().apply { add(Calendar.DATE, -1) }
fun getWeekAheadTimeUnit(): Calendar =
@ -47,9 +47,9 @@ fun Long.formatTimestamp(isMillis: Boolean, format: String? = null): String {
val isYesterday = filterTime.isSameDay(yesterday)
if (isYesterday) return YESTERDAY
val isWeekAgo = filterTime.isSameDay(weekAgo)
if (isWeekAgo) return WEEK_AGO
if (isWeekAgo) return LAST_WEEK
val isWeekAhead = filterTime.isSameDay(weekForward)
if (isWeekAhead) return WEEK_AHEAD
if (isWeekAhead) return NEXT_WEEK
val isMonthAgo = filterTime.isSameDay(monthAgo)
if (isMonthAgo) return MONTH_AGO
val isMonthAhead = filterTime.isSameDay(monthForward)
@ -77,10 +77,13 @@ const val NO_DATE = "No date"
const val TODAY = "Today"
const val TOMORROW = "Tomorrow"
const val YESTERDAY = "Yesterday"
const val WEEK_AGO = "One week ago"
const val WEEK_AHEAD = "One week from now"
const val LAST_WEEK = "One week ago"
const val CURRENT_WEEK = "Current week"
const val NEXT_WEEK = "One week from now"
const val MONTH_AGO = "One month ago"
const val CURRENT_MONTH = "Current month"
const val MONTH_AHEAD = "One month from now"
const val EXACT_DAY = "Exact day"
const val NUMBER_OF_DAYS_AGO = "Number of days ago"
const val NUMBER_OF_DAYS_FROM_NOW = "Number of days from now"
const val EMPTY_TIMESTAMP = 0L

View file

@ -36,6 +36,7 @@ typealias MDVSort = anytype.model.Block.Content.Dataview.Sort
typealias MDVSortType = anytype.model.Block.Content.Dataview.Sort.Type
typealias MDVFilter = anytype.model.Block.Content.Dataview.Filter
typealias MDVFilterCondition = anytype.model.Block.Content.Dataview.Filter.Condition
typealias MDVFilterQuickOption = anytype.model.Block.Content.Dataview.Filter.QuickOption
typealias MDVFilterOperator = anytype.model.Block.Content.Dataview.Filter.Operator
typealias MDVRelation = anytype.model.Block.Content.Dataview.Relation
typealias MDVDateFormat = anytype.model.Block.Content.Dataview.Relation.DateFormat

View file

@ -451,10 +451,12 @@ fun MDVFilter.toCoreModels(): DVFilter = DVFilter(
relationKey = RelationKey,
operator = operator_.toCoreModels(),
condition = condition.toCoreModels(),
quickOption = quickOption.toCoreModels(),
value = value_
)
fun MDVFilterCondition.toCoreModels(): DVFilterCondition = when (this) {
MDVFilterCondition.None -> DVFilterCondition.NONE
MDVFilterCondition.Equal -> DVFilterCondition.EQUAL
MDVFilterCondition.NotEqual -> DVFilterCondition.NOT_EQUAL
MDVFilterCondition.Greater -> DVFilterCondition.GREATER
@ -469,11 +471,25 @@ fun MDVFilterCondition.toCoreModels(): DVFilterCondition = when (this) {
MDVFilterCondition.NotEmpty -> DVFilterCondition.NOT_EMPTY
MDVFilterCondition.AllIn -> DVFilterCondition.ALL_IN
MDVFilterCondition.NotAllIn -> DVFilterCondition.NOT_ALL_IN
MDVFilterCondition.None -> DVFilterCondition.NONE
MDVFilterCondition.ExactIn -> DVFilterCondition.EXACT_IN
MDVFilterCondition.NotExactIn -> DVFilterCondition.NOT_EXACT_IN
}
fun MDVFilterQuickOption.toCoreModels(): DVFilterQuickOption = when (this) {
MDVFilterQuickOption.ExactDate -> DVFilterQuickOption.EXACT_DATE
MDVFilterQuickOption.Yesterday -> DVFilterQuickOption.YESTERDAY
MDVFilterQuickOption.Today -> DVFilterQuickOption.TODAY
MDVFilterQuickOption.Tomorrow -> DVFilterQuickOption.TOMORROW
MDVFilterQuickOption.LastWeek -> DVFilterQuickOption.LAST_WEEK
MDVFilterQuickOption.CurrentWeek -> DVFilterQuickOption.CURRENT_WEEK
MDVFilterQuickOption.NextWeek -> DVFilterQuickOption.NEXT_WEEK
MDVFilterQuickOption.LastMonth -> DVFilterQuickOption.LAST_MONTH
MDVFilterQuickOption.CurrentMonth -> DVFilterQuickOption.CURRENT_MONTH
MDVFilterQuickOption.NextMonth -> DVFilterQuickOption.NEXT_MONTH
MDVFilterQuickOption.NumberOfDaysAgo -> DVFilterQuickOption.DAYS_AGO
MDVFilterQuickOption.NumberOfDaysNow -> DVFilterQuickOption.DAYS_AHEAD
}
fun MDVFilterOperator.toCoreModels(): DVFilterOperator = when (this) {
MDVFilterOperator.And -> DVFilterOperator.AND
MDVFilterOperator.Or -> DVFilterOperator.OR

View file

@ -339,6 +339,7 @@ fun Block.Content.DataView.Filter.toMiddlewareModel(): MDVFilter =
RelationKey = relationKey,
operator_ = operator.toMiddlewareModel(),
condition = condition.toMiddlewareModel(),
quickOption = quickOption.toMiddlewareModel(),
value_ = value
)
@ -347,6 +348,21 @@ fun Block.Content.DataView.Filter.Operator.toMiddlewareModel(): MDVFilterOperato
Block.Content.DataView.Filter.Operator.OR -> MDVFilterOperator.Or
}
fun Block.Content.DataView.Filter.QuickOption.toMiddlewareModel(): MDVFilterQuickOption = when (this) {
Block.Content.DataView.Filter.QuickOption.EXACT_DATE -> MDVFilterQuickOption.ExactDate
Block.Content.DataView.Filter.QuickOption.YESTERDAY -> MDVFilterQuickOption.Yesterday
Block.Content.DataView.Filter.QuickOption.TODAY -> MDVFilterQuickOption.Today
Block.Content.DataView.Filter.QuickOption.TOMORROW -> MDVFilterQuickOption.Tomorrow
Block.Content.DataView.Filter.QuickOption.LAST_WEEK -> MDVFilterQuickOption.LastWeek
Block.Content.DataView.Filter.QuickOption.CURRENT_WEEK -> MDVFilterQuickOption.CurrentWeek
Block.Content.DataView.Filter.QuickOption.NEXT_WEEK -> MDVFilterQuickOption.NextWeek
Block.Content.DataView.Filter.QuickOption.LAST_MONTH -> MDVFilterQuickOption.LastMonth
Block.Content.DataView.Filter.QuickOption.CURRENT_MONTH -> MDVFilterQuickOption.CurrentMonth
Block.Content.DataView.Filter.QuickOption.NEXT_MONTH -> MDVFilterQuickOption.NextMonth
Block.Content.DataView.Filter.QuickOption.DAYS_AGO -> MDVFilterQuickOption.NumberOfDaysAgo
Block.Content.DataView.Filter.QuickOption.DAYS_AHEAD -> MDVFilterQuickOption.NumberOfDaysNow
}
fun Block.Content.DataView.Filter.Condition.toMiddlewareModel(): MDVFilterCondition = when (this) {
Block.Content.DataView.Filter.Condition.EQUAL -> MDVFilterCondition.Equal
Block.Content.DataView.Filter.Condition.NOT_EQUAL -> MDVFilterCondition.NotEqual

View file

@ -11,6 +11,7 @@ fun Viewer.Filter.Condition.index(): Int = this.getConditions().indexOf(this)
fun Viewer.Filter.Condition.getConditions(): List<Viewer.Filter.Condition> = when (this) {
is Viewer.Filter.Condition.Checkbox -> Viewer.Filter.Condition.Checkbox.checkboxConditions()
is Viewer.Filter.Condition.Number -> Viewer.Filter.Condition.Number.numberConditions()
is Viewer.Filter.Condition.Date -> Viewer.Filter.Condition.Date.dateConditions()
is Viewer.Filter.Condition.Selected -> Viewer.Filter.Condition.Selected.selectConditions()
is Viewer.Filter.Condition.Text -> Viewer.Filter.Condition.Text.textConditions()
}
@ -18,6 +19,7 @@ fun Viewer.Filter.Condition.getConditions(): List<Viewer.Filter.Condition> = whe
fun Viewer.Filter.Condition.type(): Viewer.Filter.Type = when (this) {
is Viewer.Filter.Condition.Checkbox -> Viewer.Filter.Type.CHECKBOX
is Viewer.Filter.Condition.Number -> Viewer.Filter.Type.NUMBER
is Viewer.Filter.Condition.Date -> Viewer.Filter.Type.DATE
is Viewer.Filter.Condition.Selected -> Viewer.Filter.Type.SELECTED
is Viewer.Filter.Condition.Text -> Viewer.Filter.Type.TEXT
}
@ -32,11 +34,14 @@ fun Relation.toConditionView(condition: DVFilterCondition?): Viewer.Filter.Condi
condition?.toView(category = DVFilterConditionCategory.TEXT)
?: Viewer.Filter.Condition.Text.textConditions().first()
}
Relation.Format.NUMBER,
Relation.Format.DATE -> {
Relation.Format.NUMBER -> {
condition?.toView(category = DVFilterConditionCategory.NUMBER)
?: Viewer.Filter.Condition.Number.numberConditions().first()
}
Relation.Format.DATE -> {
condition?.toView(category = DVFilterConditionCategory.DATE)
?: Viewer.Filter.Condition.Date.dateConditions().first()
}
Relation.Format.STATUS,
Relation.Format.TAG,
Relation.Format.OBJECT -> {
@ -57,6 +62,7 @@ private fun DVFilterCondition.toView(
when (category) {
DVFilterConditionCategory.TEXT -> Viewer.Filter.Condition.Text.Equal()
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.Equal()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.Equal()
DVFilterConditionCategory.SELECT -> Viewer.Filter.Condition.Selected.Equal()
DVFilterConditionCategory.CHECKBOX -> Viewer.Filter.Condition.Checkbox.Equal()
}
@ -72,24 +78,28 @@ private fun DVFilterCondition.toView(
DVFilterCondition.GREATER -> {
when (category) {
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.Greater()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.Greater()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
DVFilterCondition.LESS -> {
when (category) {
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.Less()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.Less()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
DVFilterCondition.GREATER_OR_EQUAL -> {
when (category) {
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.GreaterOrEqual()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.GreaterOrEqual()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
DVFilterCondition.LESS_OR_EQUAL -> {
when (category) {
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.LessOrEqual()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.LessOrEqual()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
@ -108,6 +118,7 @@ private fun DVFilterCondition.toView(
DVFilterCondition.IN -> {
when (category) {
DVFilterConditionCategory.SELECT -> Viewer.Filter.Condition.Selected.In()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.In()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
@ -121,6 +132,7 @@ private fun DVFilterCondition.toView(
when (category) {
DVFilterConditionCategory.TEXT -> Viewer.Filter.Condition.Text.Empty()
DVFilterConditionCategory.SELECT -> Viewer.Filter.Condition.Selected.Empty()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.Empty()
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.Empty()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
@ -130,6 +142,7 @@ private fun DVFilterCondition.toView(
DVFilterConditionCategory.TEXT -> Viewer.Filter.Condition.Text.NotEmpty()
DVFilterConditionCategory.SELECT -> Viewer.Filter.Condition.Selected.NotEmpty()
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.NotEmpty()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.NotEmpty()
else -> throw IllegalArgumentException("Condition ${this.name} is not present in $category")
}
}
@ -146,6 +159,7 @@ private fun DVFilterCondition.toView(
when (category) {
DVFilterConditionCategory.TEXT -> Viewer.Filter.Condition.Text.None()
DVFilterConditionCategory.NUMBER -> Viewer.Filter.Condition.Number.None()
DVFilterConditionCategory.DATE -> Viewer.Filter.Condition.Date.None()
DVFilterConditionCategory.SELECT -> Viewer.Filter.Condition.Selected.None()
DVFilterConditionCategory.CHECKBOX -> Viewer.Filter.Condition.Checkbox.None()
}

View file

@ -1,6 +1,10 @@
package com.anytypeio.anytype.presentation.extension
import com.anytypeio.anytype.core_models.*
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.mapper.toDomain
import com.anytypeio.anytype.presentation.relations.toView
@ -18,6 +22,9 @@ fun Viewer.Filter.Condition.hasValue(): Boolean = when (this) {
is Viewer.Filter.Condition.Number.None,
is Viewer.Filter.Condition.Number.Empty,
is Viewer.Filter.Condition.Number.NotEmpty,
is Viewer.Filter.Condition.Date.None,
is Viewer.Filter.Condition.Date.Empty,
is Viewer.Filter.Condition.Date.NotEmpty,
is Viewer.Filter.Condition.Selected.None,
is Viewer.Filter.Condition.Text.None -> false
else -> true

View file

@ -533,6 +533,20 @@ fun DVFilterCondition.toTextView(): Viewer.Filter.Condition.Text = when (this) {
else -> throw IllegalStateException("Unexpected filter condition $this for Text relations")
}
fun DVFilterCondition.toDateView(): Viewer.Filter.Condition.Date = when (this) {
DVFilterCondition.EQUAL -> Viewer.Filter.Condition.Date.Equal()
DVFilterCondition.GREATER -> Viewer.Filter.Condition.Date.Greater()
DVFilterCondition.LESS -> Viewer.Filter.Condition.Date.Less()
DVFilterCondition.GREATER_OR_EQUAL -> Viewer.Filter.Condition.Date.GreaterOrEqual()
DVFilterCondition.LESS_OR_EQUAL -> Viewer.Filter.Condition.Date.LessOrEqual()
DVFilterCondition.IN -> Viewer.Filter.Condition.Date.In()
DVFilterCondition.EMPTY -> Viewer.Filter.Condition.Date.Empty()
DVFilterCondition.NOT_EMPTY -> Viewer.Filter.Condition.Date.NotEmpty()
DVFilterCondition.NONE -> Viewer.Filter.Condition.Date.None()
else -> throw IllegalStateException("Unexpected filter condition $this for Number or Date relations")
}
fun DVFilterCondition.toNumberView(): Viewer.Filter.Condition.Number = when (this) {
DVFilterCondition.EQUAL -> Viewer.Filter.Condition.Number.Equal()
DVFilterCondition.NOT_EQUAL -> Viewer.Filter.Condition.Number.NotEqual()
@ -600,6 +614,14 @@ fun Viewer.FilterOperator.toDomain(): DVFilterOperator = when (this) {
fun Viewer.Filter.Condition.toDomain(): DVFilterCondition = when (this) {
is Viewer.Filter.Condition.Checkbox.Equal -> DVFilterCondition.EQUAL
is Viewer.Filter.Condition.Checkbox.NotEqual -> DVFilterCondition.NOT_EQUAL
is Viewer.Filter.Condition.Date.Equal -> DVFilterCondition.EQUAL
is Viewer.Filter.Condition.Date.Greater -> DVFilterCondition.GREATER
is Viewer.Filter.Condition.Date.GreaterOrEqual -> DVFilterCondition.GREATER_OR_EQUAL
is Viewer.Filter.Condition.Date.Less -> DVFilterCondition.LESS
is Viewer.Filter.Condition.Date.LessOrEqual -> DVFilterCondition.LESS_OR_EQUAL
is Viewer.Filter.Condition.Date.In -> DVFilterCondition.IN
is Viewer.Filter.Condition.Date.Empty -> DVFilterCondition.EMPTY
is Viewer.Filter.Condition.Date.NotEmpty -> DVFilterCondition.NOT_EMPTY
is Viewer.Filter.Condition.Number.Equal -> DVFilterCondition.EQUAL
is Viewer.Filter.Condition.Number.Greater -> DVFilterCondition.GREATER
is Viewer.Filter.Condition.Number.GreaterOrEqual -> DVFilterCondition.GREATER_OR_EQUAL
@ -621,6 +643,7 @@ fun Viewer.Filter.Condition.toDomain(): DVFilterCondition = when (this) {
is Viewer.Filter.Condition.Text.NotEqual -> DVFilterCondition.NOT_EQUAL
is Viewer.Filter.Condition.Text.NotLike -> DVFilterCondition.NOT_LIKE
is Viewer.Filter.Condition.Checkbox.None -> DVFilterCondition.NONE
is Viewer.Filter.Condition.Date.None -> DVFilterCondition.NONE
is Viewer.Filter.Condition.Number.None -> DVFilterCondition.NONE
is Viewer.Filter.Condition.Selected.None -> DVFilterCondition.NONE
is Viewer.Filter.Condition.Text.None -> DVFilterCondition.NONE

View file

@ -4,6 +4,8 @@ import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.CoverType
import com.anytypeio.anytype.core_models.DV
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerCardSize
import com.anytypeio.anytype.core_models.DVViewerType
@ -14,28 +16,24 @@ import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.Url
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.ext.title
import com.anytypeio.anytype.core_utils.ext.EMPTY_TIMESTAMP
import com.anytypeio.anytype.core_utils.ext.CURRENT_MONTH
import com.anytypeio.anytype.core_utils.ext.CURRENT_WEEK
import com.anytypeio.anytype.core_utils.ext.EXACT_DAY
import com.anytypeio.anytype.core_utils.ext.LAST_WEEK
import com.anytypeio.anytype.core_utils.ext.MONTH_AGO
import com.anytypeio.anytype.core_utils.ext.MONTH_AHEAD
import com.anytypeio.anytype.core_utils.ext.NEXT_WEEK
import com.anytypeio.anytype.core_utils.ext.NUMBER_OF_DAYS_AGO
import com.anytypeio.anytype.core_utils.ext.NUMBER_OF_DAYS_FROM_NOW
import com.anytypeio.anytype.core_utils.ext.TODAY
import com.anytypeio.anytype.core_utils.ext.TOMORROW
import com.anytypeio.anytype.core_utils.ext.WEEK_AGO
import com.anytypeio.anytype.core_utils.ext.WEEK_AHEAD
import com.anytypeio.anytype.core_utils.ext.YESTERDAY
import com.anytypeio.anytype.core_utils.ext.getMonthAgoTimeUnit
import com.anytypeio.anytype.core_utils.ext.getMonthAheadTimeUnit
import com.anytypeio.anytype.core_utils.ext.getTodayTimeUnit
import com.anytypeio.anytype.core_utils.ext.getTomorrowTimeUnit
import com.anytypeio.anytype.core_utils.ext.getWeekAgoTimeUnit
import com.anytypeio.anytype.core_utils.ext.getWeekAheadTimeUnit
import com.anytypeio.anytype.core_utils.ext.getYesterdayTimeUnit
import com.anytypeio.anytype.core_utils.ext.isSameDay
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.editor.cover.CoverColor
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.extension.isValueRequired
import com.anytypeio.anytype.presentation.mapper.toCheckboxView
import com.anytypeio.anytype.presentation.mapper.toDateView
import com.anytypeio.anytype.presentation.mapper.toGridRecordRows
import com.anytypeio.anytype.presentation.mapper.toNumberView
import com.anytypeio.anytype.presentation.mapper.toSelectedView
@ -62,7 +60,6 @@ import com.anytypeio.anytype.presentation.sets.model.TagView
import com.anytypeio.anytype.presentation.sets.model.Viewer
import com.anytypeio.anytype.presentation.sets.model.ViewerTabView
import timber.log.Timber
import java.util.*
fun ObjectSet.tabs(activeViewerId: String? = null): List<ViewerTabView> {
@ -160,7 +157,8 @@ fun ObjectSet.render(
Viewer.ListView(
id = viewer.id,
items = viewer.buildListViews(
objects = (viewerDb[viewer.id]?.records ?: emptyList()).map { ObjectWrapper.Basic(it) },
objects = (viewerDb[viewer.id]?.records
?: emptyList()).map { ObjectWrapper.Basic(it) },
details = details,
relations = relations,
urlBuilder = builder
@ -301,94 +299,105 @@ fun Relation.toCreateFilterStatusView(ids: List<*>? = null): List<CreateFilterVi
)
}
fun Relation.toCreateFilterDateView(exactDayTimestamp: Long): List<CreateFilterView.Date> {
val filterTime = Calendar.getInstance()
if (exactDayTimestamp != EMPTY_TIMESTAMP) {
filterTime.timeInMillis = exactDayTimestamp * 1000
}
val today = getTodayTimeUnit()
val tomorrow = getTomorrowTimeUnit()
val yesterday = getYesterdayTimeUnit()
val weekAgo = getWeekAgoTimeUnit()
val weekForward = getWeekAheadTimeUnit()
val monthAgo = getMonthAgoTimeUnit()
val monthForward = getMonthAheadTimeUnit()
val isToday = filterTime.isSameDay(today)
val isTomorrow = filterTime.isSameDay(tomorrow)
val isYesterday = filterTime.isSameDay(yesterday)
val isWeekAgo = filterTime.isSameDay(weekAgo)
val isWeekAhead = filterTime.isSameDay(weekForward)
val isMonthAgo = filterTime.isSameDay(monthAgo)
val isMonthAhead = filterTime.isSameDay(monthForward)
val isExactDay = !isToday && !isTomorrow && !isYesterday && !isWeekAgo && !isWeekAhead
&& !isMonthAgo && !isMonthAhead
return listOf(
fun Relation.toCreateFilterDateView(
quickOption: DVFilterQuickOption?,
condition: DVFilterCondition,
value: Long
) = quickOptionOrderMap.getOrDefault(condition, quickOptionDefaultOrder)
.map {
val isSelected = quickOption.isSelected(it, value)
CreateFilterView.Date(
id = key,
description = TODAY,
type = DateDescription.TODAY,
timeInMillis = today.timeInMillis,
isSelected = isToday
),
CreateFilterView.Date(
id = key,
description = TOMORROW,
type = DateDescription.TOMORROW,
timeInMillis = tomorrow.timeInMillis,
isSelected = isTomorrow
),
CreateFilterView.Date(
id = key,
description = YESTERDAY,
type = DateDescription.YESTERDAY,
timeInMillis = yesterday.timeInMillis,
isSelected = isYesterday
),
CreateFilterView.Date(
id = key,
description = WEEK_AGO,
type = DateDescription.ONE_WEEK_AGO,
timeInMillis = weekAgo.timeInMillis,
isSelected = isWeekAgo
),
CreateFilterView.Date(
id = key,
description = WEEK_AHEAD,
type = DateDescription.ONE_WEEK_FORWARD,
timeInMillis = weekForward.timeInMillis,
isSelected = isWeekAhead
),
CreateFilterView.Date(
id = key,
description = MONTH_AGO,
type = DateDescription.ONE_MONTH_AGO,
timeInMillis = monthAgo.timeInMillis,
isSelected = isMonthAgo
),
CreateFilterView.Date(
id = key,
description = MONTH_AHEAD,
type = DateDescription.ONE_MONTH_FORWARD,
timeInMillis = monthForward.timeInMillis,
isSelected = isMonthAhead
),
CreateFilterView.Date(
id = key,
description = EXACT_DAY,
type = DateDescription.EXACT_DAY,
timeInMillis = filterTime.timeInMillis,
isSelected = isExactDay
description = it.toName(),
type = it,
condition = condition,
value = if (isSelected) value else CreateFilterView.Date.NO_VALUE,
isSelected = isSelected
)
}
private fun DVFilterQuickOption?.isSelected(
quickOption: DVFilterQuickOption,
value: Long
) = if (this == quickOption) {
if (quickOption == DVFilterQuickOption.EXACT_DATE) {
value > 0
} else {
true
}
} else {
false
}
private val quickOptionDefaultOrder by lazy {
listOf(
DVFilterQuickOption.TODAY,
DVFilterQuickOption.TOMORROW,
DVFilterQuickOption.YESTERDAY,
DVFilterQuickOption.CURRENT_WEEK,
DVFilterQuickOption.LAST_WEEK,
DVFilterQuickOption.NEXT_WEEK,
DVFilterQuickOption.CURRENT_MONTH,
DVFilterQuickOption.LAST_MONTH,
DVFilterQuickOption.NEXT_MONTH,
DVFilterQuickOption.DAYS_AGO,
DVFilterQuickOption.DAYS_AHEAD,
DVFilterQuickOption.EXACT_DATE,
)
}
enum class DateDescription {
TODAY, TOMORROW, YESTERDAY, ONE_WEEK_AGO,
ONE_WEEK_FORWARD, ONE_MONTH_AGO, ONE_MONTH_FORWARD, EXACT_DAY
private val quickOptionOrderMap: Map<DVFilterCondition, List<DVFilterQuickOption>> by lazy {
buildMap {
put(
DVFilterCondition.EQUAL, listOf(
DVFilterQuickOption.TODAY,
DVFilterQuickOption.TOMORROW,
DVFilterQuickOption.YESTERDAY,
DVFilterQuickOption.DAYS_AGO,
DVFilterQuickOption.DAYS_AHEAD,
DVFilterQuickOption.EXACT_DATE,
)
)
put(
DVFilterCondition.IN, listOf(
DVFilterQuickOption.TODAY,
DVFilterQuickOption.TOMORROW,
DVFilterQuickOption.YESTERDAY,
DVFilterQuickOption.LAST_WEEK,
DVFilterQuickOption.CURRENT_WEEK,
DVFilterQuickOption.NEXT_WEEK,
DVFilterQuickOption.LAST_MONTH,
DVFilterQuickOption.CURRENT_MONTH,
DVFilterQuickOption.NEXT_MONTH,
)
)
put(DVFilterCondition.EMPTY, emptyList())
put(DVFilterCondition.NOT_EMPTY, emptyList())
}
}
private val quickOptionToNameMapping: Map<DVFilterQuickOption, String> by lazy {
buildMap {
put(DVFilterQuickOption.EXACT_DATE, EXACT_DAY)
put(DVFilterQuickOption.YESTERDAY, YESTERDAY)
put(DVFilterQuickOption.TODAY, TODAY)
put(DVFilterQuickOption.TOMORROW, TOMORROW)
put(DVFilterQuickOption.LAST_WEEK, LAST_WEEK)
put(DVFilterQuickOption.CURRENT_WEEK, CURRENT_WEEK)
put(DVFilterQuickOption.NEXT_WEEK, NEXT_WEEK)
put(DVFilterQuickOption.LAST_MONTH, MONTH_AGO)
put(DVFilterQuickOption.CURRENT_MONTH, CURRENT_MONTH)
put(DVFilterQuickOption.NEXT_MONTH, MONTH_AHEAD)
put(DVFilterQuickOption.DAYS_AGO, NUMBER_OF_DAYS_AGO)
put(DVFilterQuickOption.DAYS_AHEAD, NUMBER_OF_DAYS_FROM_NOW)
}
}
fun DVFilterQuickOption.toName() = quickOptionToNameMapping.getOrDefault(this, "Error")
fun ObjectSet.columns(viewerId: Id): ArrayList<ColumnView> {
val block = blocks.first { it.content is DV }
@ -617,7 +626,8 @@ fun DVFilter.toView(
key = relationKey,
title = relation.name,
operator = operator.toView(),
condition = condition.toNumberView(),
condition = condition.toDateView(),
quickOption = quickOption,
filterValue = FilterValue.Date(DateParser.parse(value)),
format = relation.format.toView(),
isValueRequired = condition.isValueRequired(),

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.presentation.sets.model.Viewer
import java.sql.Date
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
fun List<Relation>.views(
details: Block.Details,
@ -67,9 +68,10 @@ fun Relation.view(
// see {SetsExtension:buildGridRow()}
val format = SimpleDateFormat(DateConst.DEFAULT_DATE_FORMAT, Locale.getDefault())
val value = values[relation.key]
val timeInMillis = DateParser.parse(value)
val formattedDate = if (timeInMillis != null) {
format.format(Date(timeInMillis))
val timeInSec = DateParser.parse(value)
val formattedDate = if (timeInSec != null) {
format.format(Date(TimeUnit.SECONDS.toMillis(timeInSec)))
} else {
null
}
@ -187,13 +189,13 @@ object FilterInputValueParser {
*/
object DateParser {
fun parse(value: Any?): Long? {
val timeInMillis: Long? = when (value) {
val result: Long? = when (value) {
is String -> value.toLongOrNull()
is Double -> value.toLong()
is Long -> value
else -> null
}
return timeInMillis?.times(1000)
return result
}
}

View file

@ -26,6 +26,18 @@ class RelationTextValueViewModel(
private val jobs = mutableListOf<Job>()
fun onDateStart(
name: String,
value: Long?,
) {
title.value = name
views.value = listOf(
RelationTextValueView.Number(
value = NumberParser.parse(value)
)
)
}
fun onStart(
relationId: Id,
recordId: String,
@ -36,48 +48,43 @@ class RelationTextValueViewModel(
relations.observe(relationId),
values.subscribe(recordId)
) { relation, values ->
title.value = relation.name
val value = values[relationId]?.toString()
val isValueReadOnly = values[Relations.IS_READ_ONLY] as? Boolean ?: false
val isValueEditable = !(isValueReadOnly || isLocked)
title.value = relation.name
views.value = listOf(
when (relation.format) {
Relation.Format.SHORT_TEXT -> {
val value = values[relationId] as? String
RelationTextValueView.TextShort(
value = value,
isEditable = isValueEditable
)
}
Relation.Format.LONG_TEXT -> {
val value = values[relationId] as? String
RelationTextValueView.Text(
value = value,
isEditable = isValueEditable
)
}
Relation.Format.NUMBER -> {
val value = NumberParser.parse(values[relationId])
RelationTextValueView.Number(
value = value,
value = NumberParser.parse(value),
isEditable = isValueEditable
)
}
Relation.Format.URL -> {
val value = values[relationId] as? String
RelationTextValueView.Url(
value = value,
isEditable = isValueEditable
)
}
Relation.Format.EMAIL -> {
val value = values[relationId] as? String
RelationTextValueView.Email(
value = value,
isEditable = isValueEditable
)
}
Relation.Format.PHONE -> {
val value = values[relationId] as? String
RelationTextValueView.Phone(
value = value,
isEditable = isValueEditable

View file

@ -75,7 +75,7 @@ fun List<ColumnView>.buildGridRow(
CellView.Date(
id = record[ObjectSetConfig.ID_KEY] as String,
key = column.key,
timeInMillis = DateParser.parse(value),
timeInSecs = DateParser.parse(value),
dateFormat = column.getDateRelationFormat()
)
}

View file

@ -1,8 +1,9 @@
package com.anytypeio.anytype.presentation.sets.filter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.relations.DateDescription
sealed class CreateFilterView {
@ -32,12 +33,17 @@ sealed class CreateFilterView {
data class Date(
val id: Id,
val description: String,
val type: DateDescription,
val timeInMillis: Long,
val type: DVFilterQuickOption,
val condition: DVFilterCondition,
val value: Long,
override val isSelected: Boolean
) : CreateFilterView() {
override val text: String
get() = description
companion object {
const val NO_VALUE = 0L
}
}
data class Object(

View file

@ -1,3 +1,3 @@
package com.anytypeio.anytype.presentation.sets.filter
enum class DVFilterConditionCategory { TEXT, NUMBER, SELECT, CHECKBOX }
enum class DVFilterConditionCategory { TEXT, NUMBER, DATE, SELECT, CHECKBOX }

View file

@ -4,18 +4,35 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_models.*
import com.anytypeio.anytype.core_utils.ext.EMPTY_TIMESTAMP
import com.anytypeio.anytype.core_models.DV
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_utils.ext.cancel
import com.anytypeio.anytype.core_utils.ext.toTimeSeconds
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.extension.*
import com.anytypeio.anytype.presentation.extension.checkboxFilter
import com.anytypeio.anytype.presentation.extension.hasValue
import com.anytypeio.anytype.presentation.extension.index
import com.anytypeio.anytype.presentation.extension.sendAnalyticsAddFilterEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsChangeFilterValueEvent
import com.anytypeio.anytype.presentation.extension.toConditionView
import com.anytypeio.anytype.presentation.extension.type
import com.anytypeio.anytype.presentation.mapper.toDomain
import com.anytypeio.anytype.presentation.objects.toCreateFilterObjectView
import com.anytypeio.anytype.presentation.relations.*
import com.anytypeio.anytype.presentation.relations.FilterInputValueParser
import com.anytypeio.anytype.presentation.relations.toCreateFilterCheckboxView
import com.anytypeio.anytype.presentation.relations.toCreateFilterDateView
import com.anytypeio.anytype.presentation.relations.toCreateFilterStatusView
import com.anytypeio.anytype.presentation.relations.toCreateFilterTagView
import com.anytypeio.anytype.presentation.relations.toFilterValue
import com.anytypeio.anytype.presentation.relations.toViewRelation
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
import com.anytypeio.anytype.presentation.sets.ObjectSet
import com.anytypeio.anytype.presentation.sets.ObjectSetSession
@ -25,7 +42,10 @@ import com.anytypeio.anytype.presentation.sets.model.SimpleRelationView
import com.anytypeio.anytype.presentation.sets.model.Viewer
import com.anytypeio.anytype.presentation.util.Dispatcher
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import timber.log.Timber
@ -112,7 +132,7 @@ open class FilterViewModel(
}
private fun updateUi(format: Relation.Format, condition: Viewer.Filter.Condition) {
when(format) {
when (format) {
Relation.Format.SHORT_TEXT,
Relation.Format.LONG_TEXT,
Relation.Format.URL,
@ -200,7 +220,8 @@ open class FilterViewModel(
proceedWithFilterValueList(
relation = relation,
filter = null,
objectTypes = objectTypesProvider.get()
objectTypes = objectTypesProvider.get(),
condition = condition
)
} else {
val filter = viewer.filters[index]
@ -213,7 +234,8 @@ open class FilterViewModel(
proceedWithFilterValueList(
relation = relation,
filter = filter,
objectTypes = objectTypesProvider.get()
objectTypes = objectTypesProvider.get(),
condition = condition
)
}
}
@ -221,11 +243,16 @@ open class FilterViewModel(
private fun proceedWithFilterValueList(
relation: Relation,
filter: DVFilter?,
objectTypes: List<ObjectType>
objectTypes: List<ObjectType>,
condition: Viewer.Filter.Condition
) = when (relation.format) {
Relation.Format.DATE -> {
val timestamp = (filter?.value as? Double)?.toLong() ?: EMPTY_TIMESTAMP
filterValueListState.value = relation.toCreateFilterDateView(timestamp)
val value = (filter?.value as? Double)?.toLong() ?: 0L
filterValueListState.value = relation.toCreateFilterDateView(
quickOption = filter?.quickOption,
condition = condition.toDomain(),
value = value
)
}
Relation.Format.TAG -> {
val ids = filter?.value as? List<*>
@ -382,11 +409,15 @@ open class FilterViewModel(
}
fun onExactDayPicked(timeInSeconds: Long) {
setFilterState(DVFilterQuickOption.EXACT_DATE, timeInSeconds)
}
private fun setFilterState(quickOption: DVFilterQuickOption, value: Long) {
filterValueListState.value = filterValueListState.value.map { view ->
if (view is CreateFilterView.Date) {
if (view.type == DateDescription.EXACT_DAY) {
if (view.type == quickOption) {
view.copy(
timeInMillis = timeInSeconds * 1000,
value = value,
isSelected = true
)
} else {
@ -398,6 +429,10 @@ open class FilterViewModel(
}
}
fun onExactNumberOfDays(quickOption: DVFilterQuickOption, numberOfDays: Long) {
setFilterState(quickOption, numberOfDays)
}
fun onCreateFilterFromSelectedValueClicked(ctx: Id, relation: Id) {
val condition = conditionState.value?.condition
checkNotNull(condition)
@ -439,7 +474,7 @@ open class FilterViewModel(
ctx = ctx,
filter = DVFilter(
relationKey = relation,
value = selected?.timeInMillis?.toTimeSeconds(),
value = selected?.value?.toDouble(),
condition = condition.toDomain()
)
)
@ -574,11 +609,9 @@ open class FilterViewModel(
)
}
ColumnView.Format.DATE -> {
val value = filterValueListState.value
val date = filterValueListState.value
.filterIsInstance<CreateFilterView.Date>()
.filter { it.isSelected }
.map { date -> date.timeInMillis.toTimeSeconds() }
.firstOrNull()
.firstOrNull { it.isSelected }
proceedWithUpdatingFilter(
ctx = ctx,
target = block.id,
@ -587,7 +620,8 @@ open class FilterViewModel(
updatedFilter = DVFilter(
relationKey = relation,
condition = condition.toDomain(),
value = value
quickOption = date?.type ?: DVFilterQuickOption.EXACT_DATE,
value = date?.value?.toDouble()
)
)
sendAnalyticsChangeFilterValueEvent(
@ -694,15 +728,30 @@ open class FilterViewModel(
}
private fun onFilterDateItemClicked(dateItem: CreateFilterView.Date) {
if (dateItem.type == DateDescription.EXACT_DAY) {
viewModelScope.launch { proceedWithDatePickerScreen(dateItem.timeInMillis) }
} else {
filterValueListState.value = updateSelectedState(dateItem)
when (dateItem.type) {
DVFilterQuickOption.EXACT_DATE -> {
viewModelScope.launch { proceedWithDatePickerScreen(dateItem.value) }
}
DVFilterQuickOption.DAYS_AGO, DVFilterQuickOption.DAYS_AHEAD -> {
viewModelScope.launch {
proceedWithNumberPickerScreen(
dateItem.type,
if (dateItem.isSelected) dateItem.value else null
)
}
}
else -> {
filterValueListState.value = updateSelectedState(dateItem)
}
}
}
private suspend fun proceedWithDatePickerScreen(timeInMillis: Long) {
commands.emit(Commands.OpenDatePicker(timeInSeconds = timeInMillis / 1000))
private suspend fun proceedWithDatePickerScreen(timeInSeconds: Long) {
commands.emit(Commands.OpenDatePicker(timeInSeconds))
}
private suspend fun proceedWithNumberPickerScreen(option: DVFilterQuickOption, value: Long?) {
commands.emit(Commands.OpenNumberPicker(option, value))
}
private suspend fun proceedWithConditionPickerScreen(type: Viewer.Filter.Type, index: Int) {
@ -713,16 +762,13 @@ open class FilterViewModel(
selectedItem: CreateFilterView.Date
): List<CreateFilterView> = filterValueListState.value.map { view ->
if (view is CreateFilterView.Date) {
if (view.type == DateDescription.EXACT_DAY) {
view.copy(
isSelected = false,
timeInMillis = EMPTY_TIMESTAMP
)
if (view.type == DVFilterQuickOption.EXACT_DATE) {
view.copy(isSelected = false, value = CreateFilterView.Date.NO_VALUE)
} else {
if (view.type == selectedItem.type) {
view.copy(isSelected = true)
} else {
view.copy(isSelected = false)
view.copy(isSelected = false, value = CreateFilterView.Date.NO_VALUE)
}
}
} else {
@ -756,16 +802,17 @@ open class FilterViewModel(
}
sealed class Commands {
object ShowInput: Commands()
object HideInput: Commands()
object ShowSearchbar: Commands()
object HideSearchbar: Commands()
object ShowCount: Commands()
object HideCount: Commands()
object ShowInput : Commands()
object HideInput : Commands()
object ShowSearchbar : Commands()
object HideSearchbar : Commands()
object ShowCount : Commands()
object HideCount : Commands()
data class OpenDatePicker(val timeInSeconds: Long) : Commands()
data class OpenNumberPicker(val option: DVFilterQuickOption, val value: Long?) : Commands()
data class OpenConditionPicker(val type: Viewer.Filter.Type, val index: Int) : Commands()
object TagDivider: Commands()
object ObjectDivider: Commands()
object DateDivider: Commands()
object TagDivider : Commands()
object ObjectDivider : Commands()
object DateDivider : Commands()
}
}

View file

@ -23,6 +23,10 @@ class PickFilterConditionViewModel : BaseViewModel() {
conditions.addAll(Viewer.Filter.Condition.Number.numberConditions())
conditions[index]
}
Viewer.Filter.Type.DATE -> {
conditions.addAll(Viewer.Filter.Condition.Date.dateConditions())
conditions[index]
}
Viewer.Filter.Type.SELECTED -> {
conditions.addAll(Viewer.Filter.Condition.Selected.selectConditions())
conditions[index]

View file

@ -26,7 +26,7 @@ sealed class CellView {
data class Date(
override val id: String,
override val key: String,
val timeInMillis: Long? = null,
val timeInSecs: Long? = null,
override val dateFormat: String,
) : CellView(), DateFormat

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.presentation.sets.model
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_utils.ui.ViewType
sealed class FilterView : ViewType {
@ -9,6 +10,7 @@ sealed class FilterView : ViewType {
abstract val title: String
abstract val operator: Viewer.FilterOperator
abstract val condition: Viewer.Filter.Condition
open val quickOption: DVFilterQuickOption = DVFilterQuickOption.EXACT_DATE
abstract val filterValue: FilterValue
abstract val format: ColumnView.Format
abstract val isValueRequired: Boolean
@ -122,7 +124,8 @@ sealed class FilterView : ViewType {
override val key: String,
override val title: String,
override val operator: Viewer.FilterOperator,
override val condition: Viewer.Filter.Condition.Number,
override val condition: Viewer.Filter.Condition.Date,
override val quickOption: DVFilterQuickOption,
override val filterValue: FilterValue.Date,
override val format: ColumnView.Format,
override val isValueRequired: Boolean,

View file

@ -133,7 +133,7 @@ sealed class Viewer {
sealed class Filter {
@Parcelize
enum class Type : Parcelable { TEXT, NUMBER, SELECTED, CHECKBOX }
enum class Type : Parcelable { TEXT, NUMBER, DATE, SELECTED, CHECKBOX }
sealed class Condition : Filter() {
abstract val title: String
@ -252,6 +252,70 @@ sealed class Viewer {
}
sealed class Date : Condition() {
data class None(val name: String = "All") : Date() {
override val title: String
get() = name
}
data class Equal(val name: String = "Is") : Date() {
override val title: String
get() = name
}
data class Greater(val name: String = "Is after") : Date() {
override val title: String
get() = name
}
data class Less(val name: String = "Is before") : Date() {
override val title: String
get() = name
}
data class GreaterOrEqual(val name: String = "Is on or after") : Date() {
override val title: String
get() = name
}
data class LessOrEqual(val name: String = "Is on or before") : Date() {
override val title: String
get() = name
}
data class In(val name: String = "Is within") : Date() {
override val title: String
get() = name
}
data class Empty(val name: String = "Is empty") : Date() {
override val title: String
get() = name
}
data class NotEmpty(val name: String = "Is not empty") : Date() {
override val title: String
get() = name
}
companion object {
fun dateConditions() =
listOf(
None(),
Equal(),
Greater(),
Less(),
GreaterOrEqual(),
LessOrEqual(),
In(),
Empty(),
NotEmpty(),
)
}
}
sealed class Selected : Condition() {
data class In(val name: String = "Has any of") : Selected() {
override val title: String

View file

@ -113,6 +113,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.Equal()
val expectedNumber = Viewer.Filter.Condition.Number.Equal()
val expectedDate = Viewer.Filter.Condition.Date.None()
val expectedSelected = Viewer.Filter.Condition.Selected.In()
val expectedCheckbox = Viewer.Filter.Condition.Checkbox.Equal()
@ -148,7 +149,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Equal",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = null)
)
asserter.assertEquals(
@ -219,6 +220,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.Equal()
val expectedNumber = Viewer.Filter.Condition.Number.Equal()
val expectedDate = Viewer.Filter.Condition.Date.Equal()
val expectedSelected = Viewer.Filter.Condition.Selected.Equal()
val expectedCheckbox = Viewer.Filter.Condition.Checkbox.Equal()
@ -254,7 +256,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Equal",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.EQUAL)
)
asserter.assertEquals(
@ -357,11 +359,9 @@ class FilterConditionExtensionTest {
expected = expectedNumber,
actual = relationNumber.toConditionView(condition = DVFilterCondition.NOT_EQUAL)
)
asserter.assertEquals(
message = "Condition should be Number Not Equal",
expected = expectedNumber,
actual = relationDate.toConditionView(condition = DVFilterCondition.NOT_EQUAL)
)
assertFails {
relationDate.toConditionView(condition = DVFilterCondition.NOT_EQUAL)
}
assertFails {
relationTag.toConditionView(condition = DVFilterCondition.NOT_EQUAL)
}
@ -423,6 +423,7 @@ class FilterConditionExtensionTest {
)
val expectedNumber = Viewer.Filter.Condition.Number.Greater()
val expectedDate = Viewer.Filter.Condition.Date.Greater()
assertFails {
relationTextLong.toConditionView(condition = DVFilterCondition.GREATER)
@ -446,7 +447,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Greater",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.GREATER)
)
assertFails {
@ -508,6 +509,7 @@ class FilterConditionExtensionTest {
)
val expectedNumber = Viewer.Filter.Condition.Number.Less()
val expectedDate = Viewer.Filter.Condition.Date.Less()
assertFails {
relationTextLong.toConditionView(condition = DVFilterCondition.LESS)
@ -531,7 +533,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Less",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.LESS)
)
assertFails {
@ -593,6 +595,7 @@ class FilterConditionExtensionTest {
)
val expectedNumber = Viewer.Filter.Condition.Number.GreaterOrEqual()
val expectedDate = Viewer.Filter.Condition.Date.GreaterOrEqual()
assertFails {
relationTextLong.toConditionView(condition = DVFilterCondition.GREATER_OR_EQUAL)
@ -616,7 +619,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Greater or Equal",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.GREATER_OR_EQUAL)
)
assertFails {
@ -678,6 +681,7 @@ class FilterConditionExtensionTest {
)
val expectedNumber = Viewer.Filter.Condition.Number.LessOrEqual()
val expectedDate = Viewer.Filter.Condition.Date.LessOrEqual()
assertFails {
relationTextLong.toConditionView(condition = DVFilterCondition.LESS_OR_EQUAL)
@ -701,7 +705,7 @@ class FilterConditionExtensionTest {
)
asserter.assertEquals(
message = "Condition should be Number Less or Equal",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.LESS_OR_EQUAL)
)
assertFails {
@ -903,7 +907,7 @@ class FilterConditionExtensionTest {
}
@Test
fun `test in condition`() {
fun `relation - should have or should not have in condition`() {
val relationTextLong = Relation(
key = MockDataFactory.randomUuid(),
name = MockDataFactory.randomString(),
@ -966,9 +970,13 @@ class FilterConditionExtensionTest {
assertFails {
relationNumber.toConditionView(condition = DVFilterCondition.IN)
}
assertFails {
relationDate.toConditionView(condition = DVFilterCondition.IN)
}
asserter.assertEquals(
message = "Condition should be Selected In",
expected = Viewer.Filter.Condition.Date.In(),
actual = relationDate.toConditionView(condition = DVFilterCondition.IN)
)
asserter.assertEquals(
message = "Condition should be Selected In",
expected = expectedSelected,
@ -1289,6 +1297,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.Empty()
val expectedSelected = Viewer.Filter.Condition.Selected.Empty()
val expectedNumber = Viewer.Filter.Condition.Number.Empty()
val expectedDate = Viewer.Filter.Condition.Date.Empty()
asserter.assertEquals(
message = "Condition should be Text Empty",
@ -1324,7 +1333,7 @@ class FilterConditionExtensionTest {
asserter.assertEquals(
message = "Condition should be Date Empty",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.EMPTY)
)
@ -1395,6 +1404,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.NotEmpty()
val expectedSelected = Viewer.Filter.Condition.Selected.NotEmpty()
val expectedNumber = Viewer.Filter.Condition.Number.NotEmpty()
val expectedDate = Viewer.Filter.Condition.Date.NotEmpty()
asserter.assertEquals(
message = "Condition should be Text Not Empty",
@ -1430,7 +1440,7 @@ class FilterConditionExtensionTest {
asserter.assertEquals(
message = "Condition should be Date Not Empty",
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.NOT_EMPTY)
)
@ -1501,6 +1511,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.Equal()
val expectedSelected = Viewer.Filter.Condition.Selected.In()
val expectedNumber = Viewer.Filter.Condition.Number.Equal()
val expectedDate = Viewer.Filter.Condition.Date.None()
val expectedCheckbox = Viewer.Filter.Condition.Checkbox.Equal()
asserter.assertEquals(
@ -1537,7 +1548,7 @@ class FilterConditionExtensionTest {
asserter.assertEquals(
message = null,
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.EXACT_IN)
)
@ -1610,6 +1621,7 @@ class FilterConditionExtensionTest {
val expectedText = Viewer.Filter.Condition.Text.Equal()
val expectedSelected = Viewer.Filter.Condition.Selected.In()
val expectedNumber = Viewer.Filter.Condition.Number.Equal()
val expectedDate = Viewer.Filter.Condition.Date.None()
val expectedCheckbox = Viewer.Filter.Condition.Checkbox.Equal()
asserter.assertEquals(
@ -1646,7 +1658,7 @@ class FilterConditionExtensionTest {
asserter.assertEquals(
message = null,
expected = expectedNumber,
expected = expectedDate,
actual = relationDate.toConditionView(condition = DVFilterCondition.NOT_EXACT_IN)
)

View file

@ -35,13 +35,13 @@ class RelationValueExtensionTest {
}
@Test
fun `should return time in millis when Any is numbered string`() {
fun `should return time in secs when Any is numbered string`() {
val value: Any = "1621596602"
val result: Long? = DateParser.parse(value)
val expected: Long = 1621596602000L
val expected: Long = 1621596602L
assertNotNull(result)
@ -52,13 +52,13 @@ class RelationValueExtensionTest {
}
@Test
fun `should return time in millis when Any is Double`() {
fun `should return time in secs when Any is Double`() {
val value: Any = 1621596602.0
val result: Long? = DateParser.parse(value)
val expected: Long = 1621596602000L
val expected: Long = 1621596602L
assertNotNull(result)
@ -69,13 +69,13 @@ class RelationValueExtensionTest {
}
@Test
fun `should return time in millis when Any is Long`() {
fun `should return time in secs when Any is Long`() {
val value: Any = 1621596602L
val result: Long? = DateParser.parse(value)
val expected: Long = 1621596602000L
val expected: Long = 1621596602L
assertNotNull(result)