BackUp
This commit is contained in:
parent
8c81b83717
commit
118e8a0ea2
@ -1,7 +1,10 @@
|
||||
import org.apache.tools.ant.util.JavaEnvUtils.VERSION_11
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("com.google.devtools.ksp")
|
||||
id("org.jetbrains.kotlin.plugin.serialization")
|
||||
}
|
||||
|
||||
android {
|
||||
@ -31,11 +34,11 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
jvmTarget = "11"
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
@ -49,9 +52,10 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
//kotlin {
|
||||
//// jvmToolchain(11)
|
||||
//}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Core
|
||||
@ -75,6 +79,14 @@ dependencies {
|
||||
implementation("androidx.room:room-ktx:$room_version")
|
||||
implementation("androidx.room:room-paging:$room_version")
|
||||
|
||||
// retrofit
|
||||
val retrofitVersion = "2.9.0"
|
||||
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
|
||||
implementation("androidx.paging:paging-compose:3.2.1")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
|
||||
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
|
||||
|
||||
// Tests
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
@ -83,4 +95,6 @@ dependencies {
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||
|
||||
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".FoodWarriorsApplication"
|
||||
android:allowBackup="true"
|
||||
@ -12,7 +14,8 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MyApplication"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="31"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.example.myapplication
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.ContentProviderCompat.requireContext
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.createSavedStateHandle
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.example.myapplication.database.PrefRepository
|
||||
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
||||
import com.example.myapplication.ui.dishes.view.CategoryDropDownViewModel
|
||||
import com.example.myapplication.ui.dishes.view.DishEditViewModel
|
||||
@ -16,27 +19,28 @@ import com.example.myapplication.ui.user.UserViewModel
|
||||
object AppViewModelProvider {
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
DishListViewModel(foodWarriorsApplication().container.dishRepository,
|
||||
foodWarriorsApplication().container.userFavoritesRepository)
|
||||
DishListViewModel(foodWarriorsApplication().container.dishRestRepository,
|
||||
foodWarriorsApplication().container.userFavoritesRestRepository,
|
||||
)
|
||||
}
|
||||
initializer {
|
||||
ErrorsViewModel()
|
||||
}
|
||||
initializer {
|
||||
UserViewModel(foodWarriorsApplication().container.userRepository)
|
||||
}
|
||||
initializer {
|
||||
DishViewModel(foodWarriorsApplication().container.dishRepository)
|
||||
}
|
||||
initializer {
|
||||
DishEditViewModel(
|
||||
this.createSavedStateHandle(),
|
||||
foodWarriorsApplication().container.dishRepository
|
||||
)
|
||||
}
|
||||
initializer {
|
||||
CategoryDropDownViewModel(foodWarriorsApplication().container.categoryRepository)
|
||||
UserViewModel(foodWarriorsApplication().container.userRestRepository)
|
||||
}
|
||||
// initializer {
|
||||
// DishViewModel(foodWarriorsApplication().container.dishRestRepository)
|
||||
// }
|
||||
// initializer {
|
||||
// DishEditViewModel(
|
||||
// this.createSavedStateHandle(),
|
||||
// foodWarriorsApplication().container.dishRestRepository
|
||||
// )
|
||||
// }
|
||||
// initializer {
|
||||
// CategoryDropDownViewModel(foodWarriorsApplication().container.categoryRestRepository)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.example.myapplication
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import com.example.myapplication.database.AppContainer
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.example.myapplication.api
|
||||
|
||||
object ApiRoutes {
|
||||
const val BASE = "http://10.0.2.2:8083/"
|
||||
const val PREFIX = "api/"
|
||||
}
|
134
app/src/main/java/com/example/myapplication/api/ServerService.kt
Normal file
134
app/src/main/java/com/example/myapplication/api/ServerService.kt
Normal file
@ -0,0 +1,134 @@
|
||||
package com.example.myapplication.api
|
||||
|
||||
import com.example.myapplication.api.model.CategoryRemote
|
||||
import com.example.myapplication.api.model.DishRemote
|
||||
import com.example.myapplication.api.model.UserFavoritesRemote
|
||||
import com.example.myapplication.api.model.UserRemote
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface ServerService {
|
||||
@POST(ApiRoutes.PREFIX + "users")
|
||||
suspend fun insertUser(
|
||||
@Body user: UserRemote
|
||||
)
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "users")
|
||||
suspend fun getAllUsers() : List<UserRemote>
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "user/{id}")
|
||||
suspend fun getUserById(
|
||||
@Path("id") id: Int
|
||||
): UserRemote?
|
||||
|
||||
@PUT(ApiRoutes.PREFIX + "user/{id}")
|
||||
suspend fun updateUser(
|
||||
@Path("id") id: Int,
|
||||
@Body user: UserRemote
|
||||
)
|
||||
|
||||
@DELETE(ApiRoutes.PREFIX + "user/{id}")
|
||||
suspend fun deleteUser(
|
||||
@Path("id") id: Int,
|
||||
)
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "categories")
|
||||
suspend fun getCategories() : List<CategoryRemote>
|
||||
|
||||
@POST(ApiRoutes.PREFIX + "categories")
|
||||
suspend fun insertCategory(
|
||||
@Body category: CategoryRemote
|
||||
)
|
||||
|
||||
@POST(ApiRoutes.PREFIX + "dishes")
|
||||
suspend fun insertDish(
|
||||
@Body dish: DishRemote
|
||||
)
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "dishes")
|
||||
suspend fun getAllDishes(): List<DishRemote>
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "user_dish/{id}")
|
||||
suspend fun getAllUserDishes(
|
||||
@Path("id") userId: Int
|
||||
): List<DishRemote>
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "dish/{id}")
|
||||
suspend fun getDish(
|
||||
@Path("id") dishId: Int
|
||||
): DishRemote
|
||||
|
||||
@PUT(ApiRoutes.PREFIX + "dish/{id}")
|
||||
suspend fun editDish(
|
||||
@Path("id") dishId: Int,
|
||||
@Body dish: DishRemote
|
||||
)
|
||||
|
||||
@DELETE(ApiRoutes.PREFIX + "dish/{id}")
|
||||
suspend fun deleteDish(
|
||||
@Path("id") dishId: Int,
|
||||
)
|
||||
|
||||
@GET(ApiRoutes.PREFIX + "favorites/{id}")
|
||||
suspend fun getFavoritesOfUser(
|
||||
@Path("id") userId: Int
|
||||
): List<DishRemote>
|
||||
|
||||
@DELETE(ApiRoutes.PREFIX + "favorite/{userId}/{dishId}")
|
||||
suspend fun deleteFavorite(
|
||||
@Path("userId") userId: Int,
|
||||
@Path("dishId") dishId: Int,
|
||||
)
|
||||
|
||||
@POST(ApiRoutes.PREFIX + "favorite/{userId}/{dishId}")
|
||||
suspend fun createFavorite(
|
||||
@Path("userId") userId: Int,
|
||||
@Path("dishId") dishId: Int,
|
||||
)
|
||||
|
||||
@DELETE(ApiRoutes.PREFIX + "favorite/{userId}/{dishId}")
|
||||
suspend fun getUserFavorite(
|
||||
@Path("userId") userId: Int,
|
||||
@Path("dishId") dishId: Int,
|
||||
) : UserFavoritesRemote
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = ApiRoutes.BASE
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: ServerService? = null
|
||||
|
||||
fun getInstance(): ServerService {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val logger = HttpLoggingInterceptor()
|
||||
logger.level = HttpLoggingInterceptor.Level.BASIC
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logger)
|
||||
.build()
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create(ServerService::class.java)
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.example.myapplication.api.model
|
||||
|
||||
import com.example.myapplication.database.model.Category
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CategoryRemote(
|
||||
val uid: Int = 0,
|
||||
val name: String = "",
|
||||
)
|
||||
|
||||
fun CategoryRemote.toCategory(): Category = Category(
|
||||
uid = uid,
|
||||
name = name
|
||||
)
|
||||
|
||||
fun Category.toCategoryRemote(): CategoryRemote = CategoryRemote(
|
||||
uid = uid!!,
|
||||
name = name
|
||||
)
|
@ -0,0 +1,35 @@
|
||||
package com.example.myapplication.api.model
|
||||
|
||||
import com.example.myapplication.database.model.Category
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class DishRemote(
|
||||
val id: Int = 0,
|
||||
val name: String = "",
|
||||
val description: String = "",
|
||||
val image: String?,
|
||||
val userId: Int = 0,
|
||||
val categoryId: Int = 0,
|
||||
)
|
||||
|
||||
fun DishRemote.toDish(): Dish = Dish(
|
||||
uid = id,
|
||||
name = name,
|
||||
description = description,
|
||||
image = ByteArray(1),
|
||||
userId = userId,
|
||||
categoryId = categoryId
|
||||
)
|
||||
|
||||
|
||||
fun Dish.toDishRemote(): DishRemote = DishRemote(
|
||||
id = uid!!,
|
||||
name = name,
|
||||
description = description,
|
||||
image = image.toString(),
|
||||
userId = userId!!,
|
||||
categoryId = categoryId!!
|
||||
)
|
@ -0,0 +1,21 @@
|
||||
package com.example.myapplication.api.model
|
||||
|
||||
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserFavoritesRemote(
|
||||
val userId: Int = 0,
|
||||
val dishId: Int = 0,
|
||||
)
|
||||
|
||||
fun UserFavoritesRemote.toUserFavorites(): UserFavorites = UserFavorites(
|
||||
userId = userId,
|
||||
dishId = dishId
|
||||
)
|
||||
|
||||
fun UserFavorites.toRemote(): UserFavoritesRemote = UserFavoritesRemote(
|
||||
userId = userId,
|
||||
dishId = dishId
|
||||
)
|
@ -0,0 +1,27 @@
|
||||
package com.example.myapplication.api.model
|
||||
|
||||
|
||||
import com.example.myapplication.database.model.User
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserRemote(
|
||||
val id: Int = 0,
|
||||
val nickname: String = "",
|
||||
val email: String = "",
|
||||
val hashed_password: String = ""
|
||||
)
|
||||
|
||||
fun UserRemote.toUser(): User = User(
|
||||
uid = id,
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
password = hashed_password
|
||||
)
|
||||
|
||||
fun User.toRemote(): UserRemote = UserRemote(
|
||||
id = uid!!,
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
hashed_password = password
|
||||
)
|
@ -0,0 +1,26 @@
|
||||
package com.example.myapplication.api.repository
|
||||
|
||||
import com.example.myapplication.api.ServerService
|
||||
import com.example.myapplication.api.model.toCategory
|
||||
import com.example.myapplication.api.model.toCategoryRemote
|
||||
import com.example.myapplication.database.dao.CategoryDao
|
||||
import com.example.myapplication.database.model.Category
|
||||
import com.example.myapplication.database.repository.CategoryRepository
|
||||
import com.example.myapplication.database.repository.OfflineCategoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RestCategoryRepository(
|
||||
private val service: ServerService,
|
||||
private val dbCategoryRepository: OfflineCategoryRepository,
|
||||
) : CategoryRepository {
|
||||
override suspend fun getAll(): List<Category> {
|
||||
dbCategoryRepository.deleteAll()
|
||||
val categories = service.getCategories().map { it.toCategory() }
|
||||
categories.forEach() {dbCategoryRepository.insert(it)}
|
||||
return categories
|
||||
}
|
||||
|
||||
override suspend fun insert(category: Category) {
|
||||
service.insertCategory(category.toCategoryRemote())
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.example.myapplication.api.repository
|
||||
|
||||
import com.example.myapplication.api.ServerService
|
||||
import com.example.myapplication.api.model.toDish
|
||||
import com.example.myapplication.api.model.toDishRemote
|
||||
import com.example.myapplication.database.dao.DishDao
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.OfflineCategoryRepository
|
||||
import com.example.myapplication.database.repository.OfflineDishRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RestDishRepository(private val service: ServerService,
|
||||
private val dbCategoryRepository: OfflineDishRepository
|
||||
) : DishRepository {
|
||||
override suspend fun getAllDishes(): List<Dish> {
|
||||
return service.getAllDishes().map { it.toDish() }
|
||||
}
|
||||
|
||||
override suspend fun getDish(uid: Int): Dish? {
|
||||
return service.getDish(uid).toDish()
|
||||
}
|
||||
|
||||
override suspend fun getUserDishes(userUid: Int): List<Dish> {
|
||||
return service.getAllUserDishes(userUid).map { it.toDish() }
|
||||
}
|
||||
|
||||
override suspend fun insertDish(dish: Dish) {
|
||||
service.insertDish(dish.toDishRemote())
|
||||
}
|
||||
|
||||
override suspend fun updateDish(dish: Dish) {
|
||||
service.editDish(dish.uid!!, dish.toDishRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteDish(dish: Dish) {
|
||||
service.deleteDish(dish.uid!!)
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.example.myapplication.api.repository
|
||||
|
||||
import com.example.myapplication.api.ServerService
|
||||
import com.example.myapplication.api.model.toDish
|
||||
import com.example.myapplication.api.model.toUserFavorites
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import com.example.myapplication.database.repository.OfflineUserFavoritesRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
class RestUserFavoritesRepository(
|
||||
private val service: ServerService,
|
||||
private val dbCategoryRepository: OfflineUserFavoritesRepository,
|
||||
) : UserWithFavoritesRepository {
|
||||
override suspend fun getUserFavorites(userUid: Int): List<Dish> {
|
||||
return service.getFavoritesOfUser(userUid).map { it.toDish() }
|
||||
}
|
||||
|
||||
override suspend fun getUserFavorite(userUid: Int, dishUid: Int): UserFavorites? {
|
||||
return service.getUserFavorite(userUid, dishUid).toUserFavorites()
|
||||
}
|
||||
|
||||
override suspend fun deleteUserFavorites(userUid: Int, dishUid: Int) {
|
||||
service.deleteFavorite(userUid, dishUid)
|
||||
}
|
||||
|
||||
override suspend fun insertUserFavorites(userUid: Int, dishUid: Int) {
|
||||
service.createFavorite(userUid, dishUid)
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.example.myapplication.api.repository
|
||||
|
||||
import com.example.myapplication.api.ServerService
|
||||
import com.example.myapplication.api.model.toRemote
|
||||
import com.example.myapplication.api.model.toUser
|
||||
import com.example.myapplication.api.model.toUserFavorites
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.repository.OfflineUserRepository
|
||||
import com.example.myapplication.database.repository.UserRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import retrofit2.HttpException
|
||||
|
||||
class RestUserRepository(
|
||||
private val service: ServerService,
|
||||
private val dbCategoryRepository: OfflineUserRepository
|
||||
) : UserRepository {
|
||||
override suspend fun getAllUsers(): List<User> {
|
||||
return service.getAllUsers().map { it.toUser() }
|
||||
}
|
||||
|
||||
override suspend fun getUser(uid: Int): User? {
|
||||
try {
|
||||
return service.getUserById(uid)!!.toUser()
|
||||
}
|
||||
catch (e: HttpException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun insertUser(user: User) {
|
||||
service.insertUser(user.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun updateUser(user: User) {
|
||||
service.updateUser(user.uid!!, user.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteUser(user: User) {
|
||||
service.deleteUser(user.uid!!)
|
||||
}
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
package com.example.myapplication.database
|
||||
|
||||
import android.content.Context
|
||||
import com.example.myapplication.api.ServerService
|
||||
import com.example.myapplication.api.repository.RestCategoryRepository
|
||||
import com.example.myapplication.api.repository.RestDishRepository
|
||||
import com.example.myapplication.api.repository.RestUserFavoritesRepository
|
||||
import com.example.myapplication.api.repository.RestUserRepository
|
||||
import com.example.myapplication.database.repository.CategoryRepository
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.OfflineCategoryRepository
|
||||
@ -12,30 +17,60 @@ import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
|
||||
|
||||
interface AppContainer {
|
||||
val userRepository : UserRepository
|
||||
val dishRepository : DishRepository
|
||||
val categoryRepository : CategoryRepository
|
||||
val userFavoritesRepository: UserWithFavoritesRepository
|
||||
val userRestRepository : UserRepository
|
||||
val dishRestRepository : DishRepository
|
||||
val categoryRestRepository : CategoryRepository
|
||||
val userFavoritesRestRepository: UserWithFavoritesRepository
|
||||
}
|
||||
|
||||
class AppDataContainer(private val context: Context) : AppContainer {
|
||||
|
||||
override val userRepository: UserRepository by lazy {
|
||||
val userRepository: OfflineUserRepository by lazy {
|
||||
OfflineUserRepository(AppDatabase.getInstance(context).userDao())
|
||||
}
|
||||
|
||||
override val dishRepository: DishRepository by lazy {
|
||||
val dishRepository: OfflineDishRepository by lazy {
|
||||
OfflineDishRepository(AppDatabase.getInstance(context).dishDao())
|
||||
}
|
||||
|
||||
override val categoryRepository: CategoryRepository by lazy {
|
||||
val categoryRepository: OfflineCategoryRepository by lazy {
|
||||
OfflineCategoryRepository(AppDatabase.getInstance(context).categoryDao())
|
||||
}
|
||||
|
||||
override val userFavoritesRepository: UserWithFavoritesRepository by lazy {
|
||||
val userFavoritesRepository: OfflineUserFavoritesRepository by lazy {
|
||||
OfflineUserFavoritesRepository(AppDatabase.getInstance(context).userFavoritesDao())
|
||||
}
|
||||
|
||||
override val userFavoritesRestRepository: UserWithFavoritesRepository by lazy {
|
||||
RestUserFavoritesRepository(
|
||||
service = ServerService.getInstance(),
|
||||
dbCategoryRepository = userFavoritesRepository
|
||||
)
|
||||
}
|
||||
|
||||
override val userRestRepository: UserRepository by lazy {
|
||||
RestUserRepository(
|
||||
service = ServerService.getInstance(),
|
||||
dbCategoryRepository = userRepository
|
||||
)
|
||||
}
|
||||
|
||||
override val dishRestRepository: DishRepository by lazy {
|
||||
RestDishRepository(
|
||||
service = ServerService.getInstance(),
|
||||
dbCategoryRepository = dishRepository
|
||||
)
|
||||
}
|
||||
|
||||
override val categoryRestRepository: CategoryRepository by lazy {
|
||||
RestCategoryRepository(
|
||||
service = ServerService.getInstance(),
|
||||
dbCategoryRepository = categoryRepository
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
}
|
||||
|
@ -1,24 +1,35 @@
|
||||
package com.example.myapplication.database
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import android.content.SharedPreferences
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.example.myapplication.database.model.Category
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.dao.CategoryDao
|
||||
import com.example.myapplication.database.dao.DishDao
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import com.example.myapplication.database.dao.UserDao
|
||||
import com.example.myapplication.database.dao.UserFavoritesDao
|
||||
import com.example.myapplication.database.model.Category
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Database(entities = [Dish::class, User::class, Category::class, UserFavorites::class],
|
||||
version = 1, exportSchema = false)
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
Dish::class,
|
||||
User::class,
|
||||
Category::class,
|
||||
UserFavorites::class],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun dishDao() : DishDao
|
||||
abstract fun userDao() : UserDao
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.example.myapplication.database
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
||||
class PrefRepository(context: Context) {
|
||||
private val pref: SharedPreferences = context.getSharedPreferences("FoodWarPref", Context.MODE_PRIVATE)
|
||||
|
||||
val editor = pref.edit()
|
||||
fun loadId(id: Int) {
|
||||
editor.putInt("user_id", id)
|
||||
editor.commit()
|
||||
}
|
||||
fun getId() = pref.getInt("user_id", 2)
|
||||
}
|
@ -21,4 +21,7 @@ interface CategoryDao {
|
||||
|
||||
@Delete
|
||||
suspend fun delete(category: Category)
|
||||
|
||||
@Query("DELETE FROM categories")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -12,14 +12,14 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface DishDao {
|
||||
@Query("select * from dishes order by dish_name collate nocase asc")
|
||||
fun getAll(): Flow<List<Dish>>
|
||||
suspend fun getAll(): List<Dish>
|
||||
|
||||
@Query("select * from dishes left join categories on dishes.category_id = categories.category_id " +
|
||||
"left join users on dishes.user_id = users.user_id where dishes.dish_id = :uid")
|
||||
fun getByUid(uid: Int): Flow<DishWithCategoryAndUser?>
|
||||
suspend fun getByUid(uid: Int): Dish?
|
||||
|
||||
@Query("select * from dishes where dishes.user_id = :uid")
|
||||
fun getAllOFUser(uid: Int): Flow<List<Dish>>
|
||||
suspend fun getAllOFUser(uid: Int): List<Dish>
|
||||
@Insert
|
||||
suspend fun insert(category: Dish)
|
||||
|
||||
|
@ -12,10 +12,10 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface UserDao {
|
||||
@Query("select * from users")
|
||||
fun getAll(): Flow<List<User>>
|
||||
suspend fun getAll(): List<User>
|
||||
|
||||
@Query("select * from users where users.user_id = :uid")
|
||||
fun getByUid(uid: Int): Flow<User?>
|
||||
suspend fun getByUid(uid: Int): User?
|
||||
|
||||
|
||||
@Query("select * from user_favorites left join users on user_favorites.user_id = users.user_id " +
|
||||
|
@ -24,13 +24,13 @@ interface UserFavoritesDao {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM dishes")
|
||||
fun getUserWithFavorites(): Flow<List<Dish>>
|
||||
suspend fun getUserWithFavorites(): List<Dish>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM user_favorites us JOIN dishes d ON d.dish_id = us.dish_id WHERE us.user_id = :uid")
|
||||
fun getUserFavorites(uid: Int?): Flow<List<Dish>>
|
||||
suspend fun getUserFavorites(uid: Int?): List<Dish>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM user_favorites us WHERE us.user_id = :userUid AND us.dish_id = :dishUid")
|
||||
fun getUserFavorite(userUid: Int?, dishUid: Int?): Flow<UserFavorites?>
|
||||
suspend fun getUserFavorite(userUid: Int?, dishUid: Int?): UserFavorites?
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.model.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CategoryRepository {
|
||||
suspend fun getAllCategories(): List<Category>
|
||||
suspend fun getAll(): List<Category>
|
||||
suspend fun insert(category: Category)
|
||||
}
|
@ -5,10 +5,9 @@ import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DishRepository {
|
||||
fun getAllDishes(): Flow<List<Dish>>
|
||||
fun getDish(uid: Int): Flow<DishWithCategoryAndUser?>
|
||||
|
||||
fun getUserDishes(userUid: Int) : Flow<List<Dish>>
|
||||
suspend fun getAllDishes(): List<Dish>
|
||||
suspend fun getDish(uid: Int): Dish?
|
||||
suspend fun getUserDishes(userUid: Int) : List<Dish>
|
||||
suspend fun insertDish(dish: Dish)
|
||||
suspend fun updateDish(dish: Dish)
|
||||
suspend fun deleteDish(dish: Dish)
|
||||
|
@ -5,7 +5,12 @@ import com.example.myapplication.database.model.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineCategoryRepository(private val categoryDao: CategoryDao) : CategoryRepository {
|
||||
override suspend fun getAllCategories(): List<Category> {
|
||||
override suspend fun getAll(): List<Category> {
|
||||
return categoryDao.getAll();
|
||||
}
|
||||
|
||||
override suspend fun insert(category: Category) = categoryDao.insert(category)
|
||||
|
||||
suspend fun deleteAll() = categoryDao.deleteAll()
|
||||
|
||||
}
|
@ -6,15 +6,15 @@ import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineDishRepository(private val dishDao: DishDao) : DishRepository {
|
||||
override fun getAllDishes(): Flow<List<Dish>> {
|
||||
override suspend fun getAllDishes(): List<Dish> {
|
||||
return dishDao.getAll()
|
||||
}
|
||||
|
||||
override fun getDish(uid: Int): Flow<DishWithCategoryAndUser?> {
|
||||
override suspend fun getDish(uid: Int): Dish? {
|
||||
return dishDao.getByUid(uid)
|
||||
}
|
||||
|
||||
override fun getUserDishes(userUid: Int): Flow<List<Dish>> {
|
||||
override suspend fun getUserDishes(userUid: Int): List<Dish> {
|
||||
return dishDao.getAllOFUser(userUid);
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,15 @@ import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineUserFavoritesRepository(private val userFavoritesDao: UserFavoritesDao) : UserWithFavoritesRepository {
|
||||
override fun getUserFavorites(userUid: Int): Flow<List<Dish>> {
|
||||
override suspend fun getUserFavorites(userUid: Int): List<Dish> {
|
||||
return userFavoritesDao.getUserFavorites(userUid)
|
||||
}
|
||||
|
||||
override fun getUserFavorite(userUid: Int, dishUid: Int): Flow<UserFavorites?> {
|
||||
override suspend fun getUserFavorite(userUid: Int, dishUid: Int): UserFavorites? {
|
||||
return userFavoritesDao.getUserFavorite(userUid, dishUid)
|
||||
}
|
||||
|
||||
|
||||
override suspend fun deleteUserFavorites(userUid: Int, dishUid: Int) {
|
||||
userFavoritesDao.delete(UserFavorites(userUid, dishUid))
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import com.example.myapplication.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
|
||||
override fun getAllUsers(): Flow<List<User>> {
|
||||
override suspend fun getAllUsers(): List<User> {
|
||||
return userDao.getAll()
|
||||
}
|
||||
|
||||
override fun getUser(uid: Int): Flow<User?> {
|
||||
override suspend fun getUser(uid: Int): User? {
|
||||
return userDao.getByUid(uid)
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ import com.example.myapplication.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserRepository {
|
||||
fun getAllUsers(): Flow<List<User>>
|
||||
fun getUser(uid: Int): Flow<User?>
|
||||
suspend fun getAllUsers(): List<User>
|
||||
suspend fun getUser(uid: Int): User?
|
||||
suspend fun insertUser(user: User)
|
||||
suspend fun updateUser(user: User)
|
||||
suspend fun deleteUser(user: User)
|
||||
|
@ -5,9 +5,9 @@ import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserWithFavoritesRepository {
|
||||
fun getUserFavorites(userUid: Int): Flow<List<Dish>>
|
||||
suspend fun getUserFavorites(userUid: Int): List<Dish>
|
||||
|
||||
fun getUserFavorite(userUid: Int, dishUid: Int): Flow<UserFavorites?>
|
||||
suspend fun getUserFavorite(userUid: Int, dishUid: Int): UserFavorites?
|
||||
|
||||
suspend fun deleteUserFavorites(userUid: Int, dishUid: Int)
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.example.myapplication.ui.dishes.list
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.Image
|
||||
@ -19,20 +20,14 @@ import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@ -44,17 +39,12 @@ import androidx.navigation.NavController
|
||||
import com.example.myapplication.AppViewModelProvider
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.PrefRepository
|
||||
import com.example.myapplication.ui.extra.ErrorElement
|
||||
import com.example.myapplication.ui.extra.ErrorsType
|
||||
import com.example.myapplication.ui.navigation.Screen
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@ -67,8 +57,10 @@ fun DishList(
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val dishListUiState by viewModel.dishListUiState.collectAsState()
|
||||
val userDishes by viewModel.userDishes(userUid ?: 0).collectAsState()
|
||||
val favorites by viewModel.dishFavorites(userUid ?: 0).collectAsState()
|
||||
val dishFavoritesUiState by viewModel.favoritesDishListUiState.collectAsState()
|
||||
val dishUserUiState by viewModel.userDishListUiState.collectAsState()
|
||||
|
||||
|
||||
Scaffold(
|
||||
) { innerPadding ->
|
||||
if (typeDishList != TypeDishList.AllDishes && userUid == null) {
|
||||
@ -81,13 +73,13 @@ fun DishList(
|
||||
.fillMaxSize()
|
||||
.verticalScroll(ScrollState(0)),
|
||||
typeDishList = typeDishList,
|
||||
dishList = when (typeDishList) {
|
||||
dishListTytle = when (typeDishList) {
|
||||
TypeDishList.AllDishes -> dishListUiState.dishList
|
||||
TypeDishList.FavoritesDishes -> favorites.dishList
|
||||
TypeDishList.UserDishes -> userDishes.dishList
|
||||
TypeDishList.FavoritesDishes -> dishFavoritesUiState.dishList
|
||||
TypeDishList.UserDishes -> dishUserUiState.dishList
|
||||
else -> dishListUiState.dishList
|
||||
},
|
||||
favorites = favorites.dishList,
|
||||
favorites = dishFavoritesUiState.dishList,
|
||||
addToFavorites = {uid: Int ->
|
||||
if (userUid != null) {
|
||||
coroutineScope.launch {
|
||||
@ -109,7 +101,7 @@ fun DishList(
|
||||
private fun DishList(
|
||||
modifier: Modifier = Modifier,
|
||||
typeDishList: TypeDishList,
|
||||
dishList: List<Dish>,
|
||||
dishListTytle: List<Dish>,
|
||||
favorites: List<Dish>,
|
||||
addToFavorites: (uid : Int) -> Unit,
|
||||
onClick: (uid : Int) -> Unit
|
||||
@ -130,7 +122,7 @@ private fun DishList(
|
||||
fontSize=26.sp, textAlign = TextAlign.Start)
|
||||
}
|
||||
}
|
||||
dishList.forEachIndexed() {index, dish ->
|
||||
dishListTytle.forEachIndexed() { index, dish ->
|
||||
DishListItem(index=index, dish = dish, favorites = favorites, addToFavorites, onClick = onClick)
|
||||
}
|
||||
}
|
||||
@ -154,7 +146,8 @@ private fun DishListItem(
|
||||
}) {
|
||||
|
||||
Column() {
|
||||
if (dish.image != null) { // TODO Image input check
|
||||
// if (dish.image != null) { // TODO Image input check
|
||||
if (false) {
|
||||
Image(
|
||||
bitmap = dish.getBitmapFromByteArray()!!.asImageBitmap(),
|
||||
contentDescription = "Dish Image",
|
||||
|
@ -1,16 +1,24 @@
|
||||
package com.example.myapplication.ui.dishes.list
|
||||
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
import com.example.myapplication.database.PrefRepository
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
import com.example.myapplication.ui.user.UserUiState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class TypeDishList {
|
||||
AllDishes,
|
||||
@ -19,48 +27,45 @@ enum class TypeDishList {
|
||||
}
|
||||
class DishListViewModel(
|
||||
private val dishRepository: DishRepository,
|
||||
private val userWithFavoritesRepository: UserWithFavoritesRepository
|
||||
private val userWithFavoritesRepository: UserWithFavoritesRepository,
|
||||
) : ViewModel() {
|
||||
val dishListUiState: StateFlow<DishListUiState> = dishRepository.getAllDishes().map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
|
||||
fun dishFavorites(userUid: Int) : StateFlow<DishListUiState> {
|
||||
return userWithFavoritesRepository.getUserFavorites(userUid).map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
}
|
||||
private val _dishListUiState = MutableStateFlow(DishListUiState())
|
||||
val dishListUiState: StateFlow<DishListUiState> = _dishListUiState.asStateFlow()
|
||||
|
||||
fun userDishes(userUid: Int) : StateFlow<DishListUiState> {
|
||||
return dishRepository.getUserDishes(userUid).map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
}
|
||||
private val _userDishListUiState = MutableStateFlow(DishListUiState())
|
||||
val userDishListUiState: StateFlow<DishListUiState> = _dishListUiState.asStateFlow()
|
||||
|
||||
suspend fun addFavoritesToUser(userUid: Int, dishUid: Int) {
|
||||
var flag = true;
|
||||
userWithFavoritesRepository.getUserFavorite(userUid, dishUid).collect {
|
||||
if (flag) {
|
||||
if (it == null) {
|
||||
flag = false
|
||||
userWithFavoritesRepository.insertUserFavorites(userUid, dishUid)
|
||||
} else {
|
||||
flag = false
|
||||
userWithFavoritesRepository.deleteUserFavorites(userUid, dishUid)
|
||||
}
|
||||
private val _favoritesDishListUiState = MutableStateFlow(DishListUiState())
|
||||
val favoritesDishListUiState: StateFlow<DishListUiState> = _dishListUiState.asStateFlow()
|
||||
|
||||
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
_dishListUiState.update { currentScope ->
|
||||
currentScope.copy(dishRepository.getAllDishes())
|
||||
}
|
||||
_favoritesDishListUiState.update { currentScope ->
|
||||
currentScope.copy(userWithFavoritesRepository.getUserFavorites(2))
|
||||
}
|
||||
_userDishListUiState.update { currentScope ->
|
||||
currentScope.copy(dishRepository.getUserDishes(2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun addFavoritesToUser(userId: Int, dishId: Int) {
|
||||
val userFavorite = userWithFavoritesRepository.getUserFavorite(userId, dishId)
|
||||
if (userFavorite == null) {
|
||||
userWithFavoritesRepository.insertUserFavorites(userId, dishId)
|
||||
}
|
||||
else {
|
||||
userWithFavoritesRepository.deleteUserFavorites(userId, dishId)
|
||||
}
|
||||
_favoritesDishListUiState.update { currentScope ->
|
||||
currentScope.copy(userWithFavoritesRepository.getUserFavorites(userId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class CategoryDropDownViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
categoryListUiState = CategoryListUiState(categoryRepository.getAllCategories())
|
||||
categoryListUiState = CategoryListUiState(categoryRepository.getAll())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,16 +23,16 @@ class DishEditViewModel (
|
||||
|
||||
private val dishUid: Int = checkNotNull(savedStateHandle["id"])
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if (dishUid > 0) {
|
||||
dishEditUiState = dishRepository.getDish(dishUid)
|
||||
.filterNotNull()
|
||||
.first().dish!!
|
||||
.toUiState(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
// init {
|
||||
// viewModelScope.launch {
|
||||
// if (dishUid > 0) {
|
||||
// dishEditUiState = dishRepository.getDish(dishUid)
|
||||
// .filterNotNull()
|
||||
// .first().dish!!
|
||||
// .toUiState(true)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
fun updateUiState(dishDetails: DishDetails) {
|
||||
dishEditUiState = DishEditUiState(
|
||||
dishDetails = dishDetails,
|
||||
|
@ -62,33 +62,33 @@ fun DishView(navController: NavController,
|
||||
userUid: Int?,
|
||||
dishUid: Int?) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val dishUiState by viewModel.getDish(dishUid ?: 0).collectAsState()
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
if (dishUiState.dish?.dish?.userId == userUid) {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
val route = Screen.DishEdit.route.replace("{id}", dishUid.toString())
|
||||
navController.navigate(route)
|
||||
},
|
||||
) {
|
||||
Icon(Icons.Filled.Add, "Добавить")
|
||||
}
|
||||
}
|
||||
}
|
||||
){ innerPadding ->
|
||||
if (dishUiState.dish == null) {
|
||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_FOUND)
|
||||
}
|
||||
else {
|
||||
DishView(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
dish = dishUiState.dish!!
|
||||
)
|
||||
}
|
||||
}
|
||||
// val dishUiState by viewModel.getDish(dishUid ?: 0).collectAsState()
|
||||
// Scaffold(
|
||||
// floatingActionButton = {
|
||||
// if (dishUiState.dish?.dish?.userId == userUid) {
|
||||
// FloatingActionButton(
|
||||
// onClick = {
|
||||
// val route = Screen.DishEdit.route.replace("{id}", dishUid.toString())
|
||||
// navController.navigate(route)
|
||||
// },
|
||||
// ) {
|
||||
// Icon(Icons.Filled.Add, "Добавить")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ){ innerPadding ->
|
||||
// if (dishUiState.dish == null) {
|
||||
// ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_FOUND)
|
||||
// }
|
||||
// else {
|
||||
// DishView(
|
||||
// modifier = Modifier
|
||||
// .padding(innerPadding)
|
||||
// .fillMaxSize(),
|
||||
// dish = dishUiState.dish!!
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
|
@ -13,15 +13,15 @@ import kotlinx.coroutines.flow.stateIn
|
||||
class DishViewModel(
|
||||
private val dishRepository: DishRepository
|
||||
) : ViewModel() {
|
||||
fun getDish(uid: Int) : StateFlow<DishViewUiState> {
|
||||
return dishRepository.getDish(uid).map {
|
||||
DishViewUiState(it!!)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishViewUiState()
|
||||
)
|
||||
}
|
||||
// fun getDish(uid: Int) : StateFlow<DishViewUiState> {
|
||||
// return dishRepository.getDish(uid).map {
|
||||
// DishViewUiState(it!!)
|
||||
// }.stateIn(
|
||||
// scope = viewModelScope,
|
||||
// started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
// initialValue = DishViewUiState()
|
||||
// )
|
||||
// }
|
||||
}
|
||||
|
||||
data class DishViewUiState(val dish: DishWithCategoryAndUser? = null)
|
@ -40,7 +40,7 @@ fun Navhost(
|
||||
innerPadding: PaddingValues, modifier:
|
||||
Modifier = Modifier
|
||||
) {
|
||||
val userUid = 1;
|
||||
val userUid = 2;
|
||||
NavHost(
|
||||
navController,
|
||||
startDestination = Screen.AllDishes.route,
|
||||
|
@ -20,6 +20,7 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@ -35,6 +36,8 @@ import com.example.myapplication.ui.extra.ErrorsType
|
||||
import com.example.myapplication.ui.navigation.Screen
|
||||
//import com.example.myapplication.User.Model.getAllUsers
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@ -45,7 +48,11 @@ fun UserView (
|
||||
userUid: Int?
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val userUiState by viewModel.getUser(userUid ?: 0).collectAsState()
|
||||
val userUiState by viewModel.userState.collectAsState()
|
||||
|
||||
coroutineScope.let {
|
||||
it.launch { viewModel.getUser(userUid ?: 0) }
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
@ -66,8 +73,8 @@ fun UserView (
|
||||
UserView(
|
||||
navController = navController,
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
user = userUiState.user!!
|
||||
)
|
||||
}
|
||||
|
@ -9,22 +9,24 @@ import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.UserRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
import com.example.myapplication.ui.dishes.list.DishListUiState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
class UserViewModel(
|
||||
private val userRepository: UserRepository,
|
||||
) : ViewModel() {
|
||||
fun getUser(uid: Int) : StateFlow<UserUiState> {
|
||||
return userRepository.getUser(uid).map {
|
||||
UserUiState(it!!)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = UserUiState()
|
||||
)
|
||||
|
||||
private val _userState = MutableStateFlow(UserUiState())
|
||||
val userState: StateFlow<UserUiState> = _userState.asStateFlow()
|
||||
suspend fun getUser(uid: Int) {
|
||||
_userState.update { currentState ->
|
||||
currentState.copy(userRepository.getUser(uid))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
6
app/src/main/res/xml/network_security_config.xml
Normal file
6
app/src/main/res/xml/network_security_config.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">10.0.2.2</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
@ -3,4 +3,5 @@ plugins {
|
||||
id("com.android.application") version "8.1.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
|
||||
id("com.google.devtools.ksp") version "1.8.20-1.0.11" apply false
|
||||
id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10" apply false
|
||||
}
|
34
server/app.py
Normal file
34
server/app.py
Normal file
@ -0,0 +1,34 @@
|
||||
from flask import Flask, url_for, render_template, jsonify, make_response, abort, redirect, request
|
||||
from flask_login import LoginManager, login_user, login_required, logout_user, current_user
|
||||
from flask_restful import Api
|
||||
|
||||
from recources import db_session, UserFavoritesResource
|
||||
from recources.CategoryResource import CategoryListResource, CategoryResource
|
||||
from recources.DishResource import DishListResource, DishResource, DishUserListResource
|
||||
from recources.UserFavoritesResource import UsersFavoritesListResource, UserFavoriteResource
|
||||
from recources.UserResource import UsersListResource, UserResource
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'my_project_key'
|
||||
db_session.global_init('dishWarriors.db')
|
||||
api = Api(app)
|
||||
api.prefix = "/api"
|
||||
|
||||
api.add_resource(UsersListResource, '/users')
|
||||
api.add_resource(UserResource, "/user/<int:user_id>")
|
||||
api.add_resource(CategoryListResource, '/categories')
|
||||
api.add_resource(CategoryResource, "/category/<int:category_id>")
|
||||
api.add_resource(DishListResource, '/dishes')
|
||||
api.add_resource(DishResource, "/dish/<int:dish_id>")
|
||||
api.add_resource(DishUserListResource, "/user_dish/<int:user_id>")
|
||||
api.add_resource(UserFavoriteResource, "/favorite/<int:user_id>/<int:dish_id>")
|
||||
api.add_resource(UsersFavoritesListResource, "/favorites/<int:user_id>")
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def not_found(error):
|
||||
return make_response(jsonify({'error': 'Not found'})), 404
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=8083, host='127.0.0.1')
|
BIN
server/dishWarriors.db
Normal file
BIN
server/dishWarriors.db
Normal file
Binary file not shown.
64
server/recources/CategoryResource.py
Normal file
64
server/recources/CategoryResource.py
Normal file
@ -0,0 +1,64 @@
|
||||
from flask_restful import reqparse, abort, Resource, marshal_with, fields
|
||||
from . import db_session
|
||||
from recources.Model.Category import Category
|
||||
from flask import jsonify
|
||||
|
||||
|
||||
def abort_if_user_not_found(category_id):
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(Category).get(category_id)
|
||||
if not user:
|
||||
abort(404, message=f'Category {category_id} not found')
|
||||
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', required=True)
|
||||
|
||||
|
||||
class CategoryResource(Resource):
|
||||
def get(self, category_id):
|
||||
abort_if_user_not_found(category_id)
|
||||
db_sess = db_session.create_session()
|
||||
category = db_sess.query(Category).get(category_id)
|
||||
return jsonify(
|
||||
{'category': category.to_dict()}
|
||||
)
|
||||
|
||||
def delete(self, category_id):
|
||||
abort_if_user_not_found(category_id)
|
||||
db_sess = db_session.create_session()
|
||||
category = db_sess.query(Category).get(category_id)
|
||||
db_sess.delete(category)
|
||||
db_sess.commit()
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
def put(self, category_id):
|
||||
abort_if_user_not_found(category_id)
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
category = db_sess.query(Category).get(category_id)
|
||||
category.name = args["name"]
|
||||
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
|
||||
class CategoryListResource(Resource):
|
||||
def get(self):
|
||||
session = db_session.create_session()
|
||||
categories = session.query(Category).all()
|
||||
return jsonify([item.to_dict() for item in categories])
|
||||
|
||||
def post(self):
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
category = Category()
|
||||
category.name = args["name"]
|
||||
|
||||
db_sess.add(category)
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({'success': 'OK'})
|
82
server/recources/DishResource.py
Normal file
82
server/recources/DishResource.py
Normal file
@ -0,0 +1,82 @@
|
||||
from flask_restful import reqparse, abort, Resource
|
||||
from . import db_session
|
||||
from recources.Model.Dish import Dish
|
||||
|
||||
from flask import jsonify
|
||||
|
||||
|
||||
def abort_if_dish_not_found(dish_id):
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(Dish).get(dish_id)
|
||||
if not user:
|
||||
abort(404, message=f'Dish {dish_id} not found')
|
||||
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('name', required=True)
|
||||
parser.add_argument("description", required=True)
|
||||
parser.add_argument("image", required=True)
|
||||
parser.add_argument("userId", required=True)
|
||||
parser.add_argument("categoryId", required=True)
|
||||
|
||||
|
||||
class DishResource(Resource):
|
||||
def get(self, dish_id):
|
||||
abort_if_dish_not_found(dish_id)
|
||||
db_sess = db_session.create_session()
|
||||
dish = db_sess.query(Dish)
|
||||
return jsonify(dish.to_dict())
|
||||
|
||||
def delete(self, dish_id):
|
||||
abort_if_dish_not_found(dish_id)
|
||||
db_sess = db_session.create_session()
|
||||
dish = db_sess.query(Dish).get(dish_id)
|
||||
db_sess.delete(dish)
|
||||
db_sess.commit()
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
def put(self, dish_id):
|
||||
abort_if_dish_not_found(dish_id)
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
dish = db_sess.query(Dish).get(dish_id)
|
||||
dish.name = args["name"]
|
||||
dish.description = args["description"]
|
||||
dish.image = args["image"]
|
||||
dish.userId = args["userId"]
|
||||
dish.categoryId = args["categoryId"]
|
||||
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
|
||||
class DishListResource(Resource):
|
||||
def get(self):
|
||||
session = db_session.create_session()
|
||||
categories = session.query(Dish).all()
|
||||
return jsonify([item.to_dict() for item in categories])
|
||||
|
||||
def post(self):
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
dish = Dish()
|
||||
dish.name = args["name"]
|
||||
dish.description = args["description"]
|
||||
dish.image = args["image"].encode()
|
||||
dish.userId = args["userId"]
|
||||
dish.categoryId = args["categoryId"]
|
||||
|
||||
db_sess.add(dish)
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
|
||||
class DishUserListResource(Resource):
|
||||
def get(self, user_id):
|
||||
session = db_session.create_session()
|
||||
categories = session.query(Dish).where(Dish.userId == user_id)
|
||||
return jsonify([item.to_dict() for item in categories])
|
11
server/recources/Model/Category.py
Normal file
11
server/recources/Model/Category.py
Normal file
@ -0,0 +1,11 @@
|
||||
import sqlalchemy
|
||||
from recources.db_session import SqlAlchemyBase
|
||||
from sqlalchemy_serializer import SerializerMixin
|
||||
|
||||
|
||||
class Category(SqlAlchemyBase, SerializerMixin):
|
||||
__tablename__ = 'categories'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.Integer,
|
||||
primary_key=True, autoincrement=True)
|
||||
name = sqlalchemy.Column(sqlalchemy.String)
|
15
server/recources/Model/Dish.py
Normal file
15
server/recources/Model/Dish.py
Normal file
@ -0,0 +1,15 @@
|
||||
import sqlalchemy
|
||||
from recources.db_session import SqlAlchemyBase
|
||||
from sqlalchemy_serializer import SerializerMixin
|
||||
|
||||
|
||||
class Dish(SqlAlchemyBase, SerializerMixin):
|
||||
__tablename__ = 'dishes'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.Integer,
|
||||
primary_key=True, autoincrement=True)
|
||||
name = sqlalchemy.Column(sqlalchemy.String)
|
||||
description = sqlalchemy.Column(sqlalchemy.String)
|
||||
image = sqlalchemy.Column(sqlalchemy.LargeBinary)
|
||||
userId = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"))
|
||||
categoryId = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("categories.id"))
|
21
server/recources/Model/User.py
Normal file
21
server/recources/Model/User.py
Normal file
@ -0,0 +1,21 @@
|
||||
import sqlalchemy
|
||||
from recources.db_session import SqlAlchemyBase
|
||||
from flask_login import UserMixin
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from sqlalchemy_serializer import SerializerMixin
|
||||
|
||||
|
||||
class User(SqlAlchemyBase, UserMixin, SerializerMixin):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.Integer,
|
||||
primary_key=True, autoincrement=True)
|
||||
nickname = sqlalchemy.Column(sqlalchemy.String)
|
||||
email = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||
hashed_password = sqlalchemy.Column(sqlalchemy.String)
|
||||
|
||||
def set_password(self, password):
|
||||
self.hashed_password = generate_password_hash(password)
|
||||
|
||||
def check_password(self, password):
|
||||
return check_password_hash(self.hashed_password, password)
|
10
server/recources/Model/UserFavorites.py
Normal file
10
server/recources/Model/UserFavorites.py
Normal file
@ -0,0 +1,10 @@
|
||||
import sqlalchemy
|
||||
from recources.db_session import SqlAlchemyBase
|
||||
from sqlalchemy_serializer import SerializerMixin
|
||||
|
||||
|
||||
class UserFavorites(SqlAlchemyBase, SerializerMixin):
|
||||
__tablename__ = 'user_favorites'
|
||||
|
||||
userId = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), primary_key=True)
|
||||
dishId = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("dishes.id"), primary_key=True)
|
1
server/recources/Model/__init__.py
Normal file
1
server/recources/Model/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import Category, Dish, User, UserFavorites
|
60
server/recources/UserFavoritesResource.py
Normal file
60
server/recources/UserFavoritesResource.py
Normal file
@ -0,0 +1,60 @@
|
||||
from flask_restful import reqparse, abort, Resource, marshal_with, fields
|
||||
from . import db_session
|
||||
from recources.Model.UserFavorites import UserFavorites
|
||||
from flask import jsonify
|
||||
|
||||
from .Model.Dish import Dish
|
||||
|
||||
|
||||
def abort_if_user_favorites_not_found(user_id, dish_id):
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(UserFavorites).get({
|
||||
"userId": user_id,
|
||||
"dishId": dish_id
|
||||
})
|
||||
if not user:
|
||||
abort(404, message=f'User favorites {user_id} not found')
|
||||
|
||||
|
||||
class UserFavoriteResource(Resource):
|
||||
def get(self, user_id, dish_id):
|
||||
abort_if_user_favorites_not_found(user_id)
|
||||
db_sess = db_session.create_session()
|
||||
users = db_sess.query(UserFavorites).get({
|
||||
"userId": user_id,
|
||||
"dishId": dish_id
|
||||
})
|
||||
return jsonify(
|
||||
{'users_favorite': users.to_dict()}
|
||||
)
|
||||
|
||||
def delete(self, user_id, dish_id):
|
||||
abort_if_user_favorites_not_found(user_id)
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(UserFavorites).get({
|
||||
"userId": user_id,
|
||||
"dishId": dish_id
|
||||
})
|
||||
db_sess.delete(user)
|
||||
db_sess.commit()
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
def post(self, user_id, dish_id):
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
user = UserFavorites()
|
||||
user.userId = user_id
|
||||
user.dishId = dish_id
|
||||
|
||||
db_sess.add(user)
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({"user": user.to_dict()})
|
||||
|
||||
|
||||
class UsersFavoritesListResource(Resource):
|
||||
def get(self, user_id):
|
||||
session = db_session.create_session()
|
||||
user = session.query(Dish).join(UserFavorites).where(UserFavorites.userId == user_id)
|
||||
return jsonify([item.to_dict() for item in user])
|
||||
|
70
server/recources/UserResource.py
Normal file
70
server/recources/UserResource.py
Normal file
@ -0,0 +1,70 @@
|
||||
from flask_restful import reqparse, abort, Resource, marshal_with, fields
|
||||
from . import db_session
|
||||
from recources.Model.User import User
|
||||
from flask import jsonify
|
||||
|
||||
|
||||
def abort_if_user_not_found(user_id):
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(User).get(user_id)
|
||||
if not user:
|
||||
abort(404, message=f'User {user_id} not found')
|
||||
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('nickname', required=True)
|
||||
parser.add_argument('email', required=True)
|
||||
parser.add_argument('password', required=True)
|
||||
|
||||
|
||||
class UserResource(Resource):
|
||||
def get(self, user_id):
|
||||
abort_if_user_not_found(user_id)
|
||||
db_sess = db_session.create_session()
|
||||
users = db_sess.query(User).get(user_id)
|
||||
return jsonify(
|
||||
users.to_dict()
|
||||
)
|
||||
|
||||
def delete(self, user_id):
|
||||
abort_if_user_not_found(user_id)
|
||||
db_sess = db_session.create_session()
|
||||
user = db_sess.query(User).get(user_id)
|
||||
db_sess.delete(user)
|
||||
db_sess.commit()
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
def put(self, user_id):
|
||||
abort_if_user_not_found(user_id)
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
user = db_sess.query(User).get(user_id)
|
||||
user.nickname = args["nickname"]
|
||||
user.email = args["email"]
|
||||
user.set_password(args["password"])
|
||||
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify({'success': 'OK'})
|
||||
|
||||
|
||||
class UsersListResource(Resource):
|
||||
def get(self):
|
||||
session = db_session.create_session()
|
||||
user = session.query(User).all()
|
||||
return jsonify([item.to_dict() for item in user])
|
||||
|
||||
def post(self):
|
||||
args = parser.parse_args()
|
||||
db_sess = db_session.create_session()
|
||||
|
||||
user = User()
|
||||
user.nickname = args["nickname"]
|
||||
user.email = args["email"]
|
||||
user.set_password(args["password"])
|
||||
|
||||
db_sess.add(user)
|
||||
db_sess.commit()
|
||||
|
||||
return jsonify(user.to_dict())
|
32
server/recources/db_session.py
Normal file
32
server/recources/db_session.py
Normal file
@ -0,0 +1,32 @@
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy.orm as orm
|
||||
from sqlalchemy.orm import Session
|
||||
import sqlalchemy.ext.declarative as dec
|
||||
|
||||
SqlAlchemyBase = dec.declarative_base()
|
||||
|
||||
__factory = None
|
||||
|
||||
def global_init(db_file):
|
||||
global __factory
|
||||
|
||||
if __factory:
|
||||
return
|
||||
|
||||
if not db_file or not db_file.strip():
|
||||
raise Exception("Необходимо указать файл базы данных.")
|
||||
|
||||
conn_str = f'sqlite:///{db_file.strip()}?check_same_thread=False'
|
||||
print(f"Подключение к базе данных по адресу {conn_str}")
|
||||
|
||||
engine = sa.create_engine(conn_str, echo=False)
|
||||
__factory = orm.sessionmaker(bind=engine)
|
||||
|
||||
from . import Model
|
||||
|
||||
SqlAlchemyBase.metadata.create_all(engine)
|
||||
|
||||
|
||||
def create_session() -> Session:
|
||||
global __factory
|
||||
return __factory()
|
@ -3,6 +3,7 @@ pluginManagement {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
|
Loading…
Reference in New Issue
Block a user