feat: [#5] base de données Room (entités, DAOs, AppDatabase, module Hilt)
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
package com.planify.mobile.data.local
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import com.planify.mobile.data.local.dao.ProjectDao
|
||||||
|
import com.planify.mobile.data.local.dao.SectionDao
|
||||||
|
import com.planify.mobile.data.local.dao.TaskDao
|
||||||
|
import com.planify.mobile.data.local.entity.LabelEntity
|
||||||
|
import com.planify.mobile.data.local.entity.ProjectEntity
|
||||||
|
import com.planify.mobile.data.local.entity.ReminderEntity
|
||||||
|
import com.planify.mobile.data.local.entity.SectionEntity
|
||||||
|
import com.planify.mobile.data.local.entity.SourceEntity
|
||||||
|
import com.planify.mobile.data.local.entity.TaskEntity
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [
|
||||||
|
TaskEntity::class,
|
||||||
|
ProjectEntity::class,
|
||||||
|
SectionEntity::class,
|
||||||
|
LabelEntity::class,
|
||||||
|
ReminderEntity::class,
|
||||||
|
SourceEntity::class,
|
||||||
|
],
|
||||||
|
version = 1,
|
||||||
|
exportSchema = true,
|
||||||
|
)
|
||||||
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
abstract fun taskDao(): TaskDao
|
||||||
|
abstract fun projectDao(): ProjectDao
|
||||||
|
abstract fun sectionDao(): SectionDao
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.planify.mobile.data.local.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
import com.planify.mobile.data.local.entity.ProjectEntity
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface ProjectDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getAllProjects(): Flow<List<ProjectEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE is_favorite = 1 AND is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getFavoriteProjects(): Flow<List<ProjectEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE parent_id = :parentId AND is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getSubProjects(parentId: String): Flow<List<ProjectEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE id = :id")
|
||||||
|
suspend fun getById(id: String): ProjectEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE is_inbox = 1 LIMIT 1")
|
||||||
|
suspend fun getInboxProject(): ProjectEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM projects WHERE calendar_url = :calendarUrl LIMIT 1")
|
||||||
|
suspend fun getByCalendarUrl(calendarUrl: String): ProjectEntity?
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(project: ProjectEntity)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(project: ProjectEntity)
|
||||||
|
|
||||||
|
@Query("UPDATE projects SET is_deleted = 1 WHERE id = :id")
|
||||||
|
suspend fun softDelete(id: String)
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.planify.mobile.data.local.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
import com.planify.mobile.data.local.entity.SectionEntity
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface SectionDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM sections WHERE project_id = :projectId AND is_deleted = 0 ORDER BY `order` ASC")
|
||||||
|
fun getSectionsByProject(projectId: String): Flow<List<SectionEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM sections WHERE id = :id")
|
||||||
|
suspend fun getById(id: String): SectionEntity?
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(section: SectionEntity)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(section: SectionEntity)
|
||||||
|
|
||||||
|
@Query("UPDATE sections SET is_deleted = 1 WHERE id = :id")
|
||||||
|
suspend fun softDelete(id: String)
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.planify.mobile.data.local.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
import com.planify.mobile.data.local.entity.TaskEntity
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface TaskDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE project_id = :projectId AND parent_id IS NULL AND is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getTasksByProject(projectId: String): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE section_id = :sectionId AND parent_id IS NULL AND is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getTasksBySection(sectionId: String): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT t.* FROM tasks t
|
||||||
|
INNER JOIN projects p ON t.project_id = p.id
|
||||||
|
WHERE p.is_inbox = 1 AND t.parent_id IS NULL AND t.is_deleted = 0
|
||||||
|
ORDER BY t.child_order ASC
|
||||||
|
""")
|
||||||
|
fun getInboxTasks(): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT * FROM tasks
|
||||||
|
WHERE date(due_date) = date('now') AND checked = 0 AND is_deleted = 0
|
||||||
|
ORDER BY child_order ASC
|
||||||
|
""")
|
||||||
|
fun getTodayTasks(): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT * FROM tasks
|
||||||
|
WHERE date(due_date) < date('now') AND checked = 0 AND is_deleted = 0
|
||||||
|
ORDER BY due_date ASC
|
||||||
|
""")
|
||||||
|
fun getOverdueTasks(): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE parent_id = :parentId AND is_deleted = 0 ORDER BY child_order ASC")
|
||||||
|
fun getSubTasks(parentId: String): Flow<List<TaskEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE id = :id")
|
||||||
|
suspend fun getTaskById(id: String): TaskEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE ical_url = :icalUrl LIMIT 1")
|
||||||
|
suspend fun getTaskByIcalUrl(icalUrl: String): TaskEntity?
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(task: TaskEntity)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(task: TaskEntity)
|
||||||
|
|
||||||
|
@Query("UPDATE tasks SET checked = :checked, completed_at = :completedAt, updated_at = :updatedAt WHERE id = :id")
|
||||||
|
suspend fun setChecked(id: String, checked: Boolean, completedAt: String?, updatedAt: String)
|
||||||
|
|
||||||
|
@Query("UPDATE tasks SET is_deleted = 1, updated_at = :updatedAt WHERE id = :id")
|
||||||
|
suspend fun softDelete(id: String, updatedAt: String)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "labels")
|
||||||
|
data class LabelEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
val name: String,
|
||||||
|
val color: String,
|
||||||
|
val order: Int = 0,
|
||||||
|
@ColumnInfo(name = "source_id") val sourceId: String? = null,
|
||||||
|
@ColumnInfo(name = "backend_type") val backendType: String = "LOCAL",
|
||||||
|
@ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false,
|
||||||
|
@ColumnInfo(name = "is_deleted") val isDeleted: Boolean = false,
|
||||||
|
)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "projects")
|
||||||
|
data class ProjectEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
val name: String,
|
||||||
|
val color: String = "#4CAF50",
|
||||||
|
val emoji: String? = null,
|
||||||
|
@ColumnInfo(name = "parent_id") val parentId: String? = null,
|
||||||
|
@ColumnInfo(name = "source_id") val sourceId: String? = null,
|
||||||
|
@ColumnInfo(name = "backend_type") val backendType: String = "LOCAL",
|
||||||
|
@ColumnInfo(name = "is_inbox") val isInbox: Boolean = false,
|
||||||
|
@ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false,
|
||||||
|
@ColumnInfo(name = "is_archived") val isArchived: Boolean = false,
|
||||||
|
@ColumnInfo(name = "is_deleted") val isDeleted: Boolean = false,
|
||||||
|
@ColumnInfo(name = "view_style") val viewStyle: String = "LIST",
|
||||||
|
@ColumnInfo(name = "sorted_by") val sortedBy: String = "MANUAL",
|
||||||
|
@ColumnInfo(name = "sort_ascending") val sortAscending: Boolean = true,
|
||||||
|
@ColumnInfo(name = "child_order") val childOrder: Int = 0,
|
||||||
|
@ColumnInfo(name = "calendar_url") val calendarUrl: String? = null,
|
||||||
|
@ColumnInfo(name = "sync_id") val syncId: String? = null,
|
||||||
|
)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.Index
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
tableName = "reminders",
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = TaskEntity::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["task_id"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
],
|
||||||
|
indices = [Index("task_id")]
|
||||||
|
)
|
||||||
|
data class ReminderEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
@ColumnInfo(name = "task_id") val taskId: String,
|
||||||
|
val type: String,
|
||||||
|
@ColumnInfo(name = "due_date") val dueDate: String? = null,
|
||||||
|
@ColumnInfo(name = "minutes_offset") val minutesOffset: Int? = null,
|
||||||
|
)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.Index
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
tableName = "sections",
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = ProjectEntity::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["project_id"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
],
|
||||||
|
indices = [Index("project_id")]
|
||||||
|
)
|
||||||
|
data class SectionEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
val name: String,
|
||||||
|
@ColumnInfo(name = "project_id") val projectId: String,
|
||||||
|
val order: Int = 0,
|
||||||
|
@ColumnInfo(name = "is_archived") val isArchived: Boolean = false,
|
||||||
|
@ColumnInfo(name = "is_deleted") val isDeleted: Boolean = false,
|
||||||
|
val collapsed: Boolean = false,
|
||||||
|
@ColumnInfo(name = "ical_url") val icalUrl: String? = null,
|
||||||
|
val etag: String? = null,
|
||||||
|
)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "sources")
|
||||||
|
data class SourceEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
val type: String,
|
||||||
|
@ColumnInfo(name = "display_name") val displayName: String,
|
||||||
|
@ColumnInfo(name = "added_at") val addedAt: String,
|
||||||
|
@ColumnInfo(name = "updated_at") val updatedAt: String,
|
||||||
|
@ColumnInfo(name = "is_visible") val isVisible: Boolean = true,
|
||||||
|
@ColumnInfo(name = "last_sync") val lastSync: String? = null,
|
||||||
|
val data: String = "{}",
|
||||||
|
)
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.planify.mobile.data.local.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.Index
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
tableName = "tasks",
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = ProjectEntity::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["project_id"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
],
|
||||||
|
indices = [
|
||||||
|
Index("project_id"),
|
||||||
|
Index("section_id"),
|
||||||
|
Index("parent_id")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class TaskEntity(
|
||||||
|
@PrimaryKey val id: String,
|
||||||
|
val content: String,
|
||||||
|
val description: String = "",
|
||||||
|
@ColumnInfo(name = "project_id") val projectId: String,
|
||||||
|
@ColumnInfo(name = "section_id") val sectionId: String? = null,
|
||||||
|
@ColumnInfo(name = "parent_id") val parentId: String? = null,
|
||||||
|
val priority: Int = 4,
|
||||||
|
val checked: Boolean = false,
|
||||||
|
@ColumnInfo(name = "due_date") val dueDate: String? = null,
|
||||||
|
@ColumnInfo(name = "deadline_date") val deadlineDate: String? = null,
|
||||||
|
val labels: String = "[]",
|
||||||
|
val pinned: Boolean = false,
|
||||||
|
val collapsed: Boolean = false,
|
||||||
|
@ColumnInfo(name = "child_order") val childOrder: Int = 0,
|
||||||
|
@ColumnInfo(name = "added_at") val addedAt: String = "",
|
||||||
|
@ColumnInfo(name = "updated_at") val updatedAt: String = "",
|
||||||
|
@ColumnInfo(name = "completed_at") val completedAt: String? = null,
|
||||||
|
@ColumnInfo(name = "item_type") val itemType: String = "TASK",
|
||||||
|
@ColumnInfo(name = "calendar_event_uid") val calendarEventUid: String? = null,
|
||||||
|
@ColumnInfo(name = "ical_url") val icalUrl: String? = null,
|
||||||
|
val etag: String? = null,
|
||||||
|
@ColumnInfo(name = "responsible_uid") val responsibleUid: String? = null,
|
||||||
|
)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.planify.mobile.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Room
|
||||||
|
import com.planify.mobile.data.local.AppDatabase
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object DatabaseModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideDatabase(@ApplicationContext context: Context): AppDatabase =
|
||||||
|
Room.databaseBuilder(context, AppDatabase::class.java, "planify.db")
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Provides fun provideTaskDao(db: AppDatabase) = db.taskDao()
|
||||||
|
@Provides fun provideProjectDao(db: AppDatabase) = db.projectDao()
|
||||||
|
@Provides fun provideSectionDao(db: AppDatabase) = db.sectionDao()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user