Skip to content

Commit

Permalink
Store task list sorting in DB
Browse files Browse the repository at this point in the history
  • Loading branch information
opatry committed Oct 15, 2024
1 parent 45b231b commit 4a0e583
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 37 deletions.
194 changes: 194 additions & 0 deletions tasks-app-shared/schemas/net.opatry.tasks.data.TasksAppDatabase/3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "17de8549f80d34ddcf3b7baff29a9f31",
"entities": [
{
"tableName": "task_list",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remote_id` TEXT, `etag` TEXT NOT NULL DEFAULT '', `title` TEXT NOT NULL, `update_date` TEXT NOT NULL, `sorting` TEXT NOT NULL DEFAULT 'UserDefined')",
"fields": [
{
"fieldPath": "id",
"columnName": "local_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT"
},
{
"fieldPath": "etag",
"columnName": "etag",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastUpdateDate",
"columnName": "update_date",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sorting",
"columnName": "sorting",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'UserDefined'"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"local_id"
]
}
},
{
"tableName": "task",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`local_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remote_id` TEXT, `parent_list_local_id` INTEGER NOT NULL, `etag` TEXT NOT NULL DEFAULT '', `title` TEXT NOT NULL, `due_date` TEXT, `update_date` TEXT NOT NULL, `completion_date` TEXT, `notes` TEXT NOT NULL DEFAULT '', `is_completed` INTEGER NOT NULL, `position` TEXT NOT NULL, `parent_local_id` INTEGER, `remote_parent_id` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "local_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT"
},
{
"fieldPath": "parentListLocalId",
"columnName": "parent_list_local_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "etag",
"columnName": "etag",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "dueDate",
"columnName": "due_date",
"affinity": "TEXT"
},
{
"fieldPath": "lastUpdateDate",
"columnName": "update_date",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "completionDate",
"columnName": "completion_date",
"affinity": "TEXT"
},
{
"fieldPath": "notes",
"columnName": "notes",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "isCompleted",
"columnName": "is_completed",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "position",
"columnName": "position",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "parentTaskLocalId",
"columnName": "parent_local_id",
"affinity": "INTEGER"
},
{
"fieldPath": "parentTaskRemoteId",
"columnName": "remote_parent_id",
"affinity": "TEXT"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"local_id"
]
}
},
{
"tableName": "user",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remote_id` TEXT, `name` TEXT NOT NULL, `email` TEXT, `avatar_url` TEXT, `is_signed_in` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT"
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT"
},
{
"fieldPath": "avatarUrl",
"columnName": "avatar_url",
"affinity": "TEXT"
},
{
"fieldPath": "isSignedIn",
"columnName": "is_signed_in",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '17de8549f80d34ddcf3b7baff29a9f31')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import kotlinx.datetime.atStartOfDayIn
import kotlinx.datetime.toLocalDateTime
import net.opatry.tasks.app.ui.model.TaskListUIModel
import net.opatry.tasks.app.ui.model.TaskUIModel
import net.opatry.tasks.data.TaskListSorting
import net.opatry.tasks.data.TaskRepository
import net.opatry.tasks.data.model.TaskDataModel
import net.opatry.tasks.data.model.TaskListDataModel
Expand All @@ -52,7 +53,8 @@ private fun TaskListDataModel.asTaskListUIModel(): TaskListUIModel {
id = id,
title = title,
lastUpdate = lastUpdate.toString(),
tasks = tasks.map(TaskDataModel::asTaskUIModel)
tasks = tasks.map(TaskDataModel::asTaskUIModel),
sorting = sorting,
)
}

Expand Down Expand Up @@ -141,6 +143,17 @@ class TaskListsViewModel(
}
}

fun sortBy(taskList: TaskListUIModel, sorting: TaskListSorting) {
viewModelScope.launch {
try {
taskRepository.sortTasksBy(taskList.id, sorting)
} catch (e: Exception) {
println("Error while sorting task list: $e")
// TODO error handling
}
}
}

fun createTask(taskList: TaskListUIModel, title: String, notes: String = "", dueDate: LocalDate? = null) {
viewModelScope.launch {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import net.opatry.tasks.app.ui.model.TaskListUIModel
import net.opatry.tasks.app.ui.screen.TaskListSorting
import net.opatry.tasks.app.ui.tooling.TaskfolioPreview
import net.opatry.tasks.app.ui.tooling.TaskfolioThemedPreview
import net.opatry.tasks.data.TaskListSorting
import net.opatry.tasks.resources.Res
import net.opatry.tasks.resources.task_list_menu_clear_all_completed_tasks
import net.opatry.tasks.resources.task_list_menu_default_list_cannot_be_deleted
Expand All @@ -75,7 +75,6 @@ enum class TaskListMenuAction {
fun TaskListMenu(
taskList: TaskListUIModel,
expanded: Boolean,
sorting: TaskListSorting = TaskListSorting.Manual,
onAction: (TaskListMenuAction) -> Unit
) {
val allowDelete by remember(taskList.canDelete) { mutableStateOf(taskList.canDelete) }
Expand All @@ -96,19 +95,19 @@ fun TaskListMenu(
text = {
RowWithIcon(
stringResource(Res.string.task_list_menu_sort_manual),
LucideIcons.Check.takeIf { sorting == TaskListSorting.Manual })
LucideIcons.Check.takeIf { taskList.sorting == TaskListSorting.Manual })
},
enabled = sorting != TaskListSorting.Manual,
enabled = taskList.sorting != TaskListSorting.Manual,
onClick = { onAction(TaskListMenuAction.SortManual) }
)

DropdownMenuItem(
text = {
RowWithIcon(
stringResource(Res.string.task_list_menu_sort_due_date),
LucideIcons.Check.takeIf { sorting == TaskListSorting.DueDate })
LucideIcons.Check.takeIf { taskList.sorting == TaskListSorting.DueDate })
},
enabled = sorting != TaskListSorting.DueDate,
enabled = taskList.sorting != TaskListSorting.DueDate,
onClick = { onAction(TaskListMenuAction.SortDate) }
)

Expand Down Expand Up @@ -167,7 +166,7 @@ private fun TaskListMenuPreview() {
) {
IconButton(onClick = { showMenu = true }) {
Icon(LucideIcons.EllipsisVertical, null)
TaskListMenu(TaskListUIModel(0L, "My task list", "TODO DATE", tasks = emptyList()), showMenu) {}
TaskListMenu(TaskListUIModel(0L, "My task list", "TODO DATE", tasks = emptyList(), sorting = TaskListSorting.Manual), showMenu) {}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@

package net.opatry.tasks.app.ui.model

import net.opatry.tasks.data.TaskListSorting


data class TaskListUIModel(
val id: Long,
val title: String,
val lastUpdate: String,
val tasks: List<TaskUIModel>,
val sorting: TaskListSorting,
) {
val isEmpty: Boolean = tasks.isEmpty()
val hasCompletedTasks: Boolean = tasks.any { it.isCompleted }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import net.opatry.tasks.app.ui.component.RowWithIcon
import net.opatry.tasks.app.ui.model.TaskListUIModel
import net.opatry.tasks.app.ui.tooling.TaskfolioPreview
import net.opatry.tasks.app.ui.tooling.TaskfolioThemedPreview
import net.opatry.tasks.data.TaskListSorting
import net.opatry.tasks.resources.Res
import net.opatry.tasks.resources.task_lists_screen_add_task_list_cta
import org.jetbrains.compose.resources.stringResource
Expand Down Expand Up @@ -136,6 +137,7 @@ private fun TaskListRowScaffold(
title = title,
"TODO DATE",
tasks = emptyList(),
sorting = TaskListSorting.Manual,
),
isSelected = isSelected,
onClick = {}
Expand Down
Loading

0 comments on commit 4a0e583

Please sign in to comment.