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:
parent
34f41296ee
commit
63957db7c2
32 changed files with 573 additions and 221 deletions
|
@ -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 {
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 }
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue