Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from javaBin/feat/load-workshop
Browse files Browse the repository at this point in the history
Feat/load workshop
  • Loading branch information
daudmohamed authored May 7, 2024
2 parents 1b46895 + 8a0907e commit 1c731ba
Show file tree
Hide file tree
Showing 16 changed files with 345 additions and 60 deletions.
2 changes: 1 addition & 1 deletion backend/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies {
val flyway_version = "10.6.0"
val hikari_version = "5.1.0"
val postgres_version = "42.7.1"
val exposed_version = "0.41.1"
val exposed_version = "0.49.0"
val h2_version = "2.1.214"
val kotlinx_datetime_version = "0.2.1"

Expand Down
9 changes: 1 addition & 8 deletions backend/app/src/main/kotlin/backend/App.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package backend

import backend.config.configureAuth
import backend.config.configureRouting
import backend.config.configureSerialization
import backend.config.defaultClient
import backend.config.*
import com.inventy.plugins.DatabaseFactory
import io.ktor.client.*
import io.ktor.server.application.*


Expand All @@ -25,6 +21,3 @@ fun Application.module() {
configureAuth()
configureRouting()
}



20 changes: 14 additions & 6 deletions backend/app/src/main/kotlin/backend/config/DatabaseFactory.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.inventy.plugins

import com.zaxxer.hikari.HikariDataSource
import java.util.concurrent.TimeUnit.MINUTES
import org.jetbrains.exposed.sql.*
import kotlinx.coroutines.*
import org.flywaydb.core.Flyway
import org.postgresql.ds.PGSimpleDataSource
import org.h2.jdbcx.JdbcDataSource
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.experimental.withSuspendTransaction
import org.postgresql.ds.PGSimpleDataSource
import java.util.concurrent.TimeUnit.MINUTES


class DatabaseFactory(
private val dbHost: String,
Expand All @@ -16,11 +19,16 @@ class DatabaseFactory(
private val dbPassword: String,
private val databaseName: String,
private val embedded: Boolean = false
) {
) {

companion object {
suspend fun <T> dbQuery(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() }
withContext(Dispatchers.IO) {
TransactionManager.currentOrNull()
?.let { it.withSuspendTransaction { block() } }
?: newSuspendedTransaction { block() }
}

}

fun init() {
Expand Down Expand Up @@ -63,5 +71,5 @@ class DatabaseFactory(


}

}

6 changes: 5 additions & 1 deletion backend/app/src/main/kotlin/backend/config/Routing.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package backend.config

import backend.repository.AdminRepository
import backend.repository.SpeakerRepository
import backend.repository.UserRepository
import backend.repository.WorkshopRepository
import backend.route.*
import backend.service.WorkshopService
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.response.*
Expand All @@ -13,10 +15,12 @@ fun Application.configureRouting() {
val userRepository = UserRepository()
val adminRepository = AdminRepository()
val workshopRepository = WorkshopRepository()
val speakerRepository = SpeakerRepository()
val workshopService = WorkshopService(environment.config)

configureAuth0Route(userRepository)
configureUserRoutes(userRepository)
configureWorkshopRoutes(workshopRepository)
configureWorkshopRoutes(workshopRepository, speakerRepository, workshopService)
configureAdminRoutes(adminRepository)
configureApiRoutes()

Expand Down
6 changes: 6 additions & 0 deletions backend/app/src/main/kotlin/backend/config/Serialization.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.modules.SerializersModule
import java.time.Instant

fun Application.configureSerialization() {
install(ContentNegotiation) {
Expand Down
10 changes: 10 additions & 0 deletions backend/app/src/main/kotlin/backend/dto/SpeakerDTO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package backend.dto

import kotlinx.serialization.Serializable

@Serializable
data class SpeakerDTO(
val name: String,
val bio: String,
val twitter: String,
)
4 changes: 3 additions & 1 deletion backend/app/src/main/kotlin/backend/dto/WorkshopDTO.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ data class WorkshopDTO(
val description: String,
val startTime: Instant,
val endTime: Instant,
val capacity: Int
val capacity: Int,
val active: Boolean,
val speakers: List<SpeakerDTO>
)

39 changes: 39 additions & 0 deletions backend/app/src/main/kotlin/backend/dto/WorkshopListImportDTO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package backend.dto

import kotlinx.serialization.Serializable

@Serializable
data class WorkshopListImportDTO(
val sessions: List<WorkshopImport>,
)

@Serializable
data class WorkshopImport(
val intendedAudience: String,
val length: String,
val format: String,
val language: String,
val abstract: String,
val title: String,
val room: String,
val startTime: String,
val endTime: String,
val video: String? = "",
val startTimeZulu: String,
val endTimeZulu: String,
val id: String,
val sessionId: String,
val conferenceId: String,
val startSlot: String,
val startSlotZulu: String,
val speakers: List<Speaker>,
val workshopPrerequisites: String? = "",
val registerLoc: String? = "",
)

@Serializable
data class Speaker(
val name: String,
val twitter: String? = "",
val bio: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package backend.repository

import backend.dto.SpeakerDTO
import com.inventy.plugins.DatabaseFactory.Companion.dbQuery
import org.jetbrains.exposed.sql.*

data class Speaker(
val name: String,
val bio: String,
val twitter: String,
val workshopId: String,
val index: Int,
) {
fun toDTO() = SpeakerDTO(name, bio, twitter)
}

class SpeakerRepository {

internal object SpeakerTable : Table() {
val name = varchar("NAME", 256)
val bio = varchar("bio", 2048)
val twitter = varchar("twitter", 256)
val workshopId = reference("workshop_id", WorkshopRepository.WorkshopTable.id)
val index = integer("index");

override val primaryKey = PrimaryKey(arrayOf(workshopId, index), "id")

fun toModel(it: ResultRow) = Speaker(
name = it[name],
bio = it[bio],
twitter = it[twitter],
workshopId = it[workshopId],
index = it[index]
)
}

suspend fun list(): List<Speaker> = dbQuery {
SpeakerTable.selectAll()
.map(SpeakerTable::toModel)
}


private suspend fun create(speakers: List<Speaker>) = dbQuery {
SpeakerTable.batchInsert(speakers) { speaker ->
this[SpeakerTable.name] = speaker.name
this[SpeakerTable.bio] = speaker.bio
this[SpeakerTable.twitter] = speaker.twitter
this[SpeakerTable.workshopId] = speaker.workshopId
this[SpeakerTable.index] = speaker.index
}
}



suspend fun replace(speakers: List<Speaker>) {

dbQuery {
SpeakerTable.deleteAll()
create(speakers)

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package backend.repository
import com.inventy.plugins.DatabaseFactory.Companion.dbQuery
import kotlinx.datetime.Instant
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.insertAndGetId
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.kotlin.datetime.timestamp
import org.jetbrains.exposed.sql.select


enum class WorkshopRegistrationState {
Expand All @@ -16,7 +14,7 @@ enum class WorkshopRegistrationState {
class WorkshopRegistration(
override val id: Int,
val userId: Int,
val workshopId: Int,
val workshopId: String,
val createdAt: Instant,
val updatedAt: Instant,
var state: WorkshopRegistrationState = WorkshopRegistrationState.PENDING,
Expand All @@ -33,7 +31,7 @@ class WorkshopRegistrationRepository(userId: Int) : UserOwnedRepository(userId)
fun toModel(it: ResultRow) = WorkshopRegistration(
it[id].value,
it[userId].value,
it[workshopId].value,
it[workshopId],
it[createdAt],
it[updatedAt],
it[state],
Expand All @@ -51,7 +49,7 @@ class WorkshopRegistrationRepository(userId: Int) : UserOwnedRepository(userId)
}

suspend fun list(): List<WorkshopRegistration> = dbQuery {
WorkshopRegistrationTable.select{ WorkshopRegistrationTable.userId eq userId }
WorkshopRegistrationTable.selectAll().where { WorkshopRegistrationTable.userId eq userId }
.map(WorkshopRegistrationTable::toModel)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,101 @@
package backend.repository

import backend.dto.SpeakerDTO
import backend.dto.WorkshopDTO
import backend.dto.WorkshopImport
import backend.dto.WorkshopListImportDTO
import com.inventy.plugins.DatabaseFactory.Companion.dbQuery
import kotlinx.datetime.Instant
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.kotlin.datetime.timestamp
import org.jetbrains.exposed.sql.selectAll

class Workshop(
override val id: Int,
data class Workshop(
val id: String,
val title: String,
val description: String,
val startTime: Instant,
val endTime: Instant,
val capacity: Int
) : Model {
fun toDTO() = WorkshopDTO(title, description, startTime, endTime, capacity)
val capacity: Int,
val active: Boolean
) {
fun toDTO(speakerDTOS: List<SpeakerDTO>?) = WorkshopDTO(title, description, startTime, endTime, capacity, active, speakerDTOS ?: listOf())
}

class WorkshopRepository {
internal object WorkshopTable : IntIdTable() {
val title = varchar("title", 128)
val description = varchar("description", 256)

companion object {
private const val WORKSHOP_CAPACITY = 30
}

internal object WorkshopTable : Table() {

val id = varchar("id", 64)
val title = varchar("title", 256)
val description = varchar("description", 2048)
val startTime = timestamp("start_time")
val endTime = timestamp("end_time")
val capacity = integer("capacity")
val active = bool("active")

override val primaryKey = PrimaryKey(arrayOf(id), "id")

fun toModel(it: ResultRow) = Workshop(
it[id].value,
it[title],
it[description],
it[startTime],
it[endTime],
it[capacity]
id = it[id],
title = it[title],
description = it[description],
startTime = it[startTime],
endTime = it[endTime],
capacity = it[capacity],
active = it[active],
)
}

suspend fun list(): List<Workshop> = dbQuery {
WorkshopTable.selectAll()
.map(WorkshopTable::toModel)
}


private suspend fun upsertActive(workshops: List<WorkshopImport>) = dbQuery {
WorkshopTable.batchUpsert(workshops) { workshop ->
this[WorkshopTable.id] = workshop.id
this[WorkshopTable.title] = workshop.title
this[WorkshopTable.description] =
workshop.abstract.take(250) + if (workshop.abstract.length > 250) " ..." else ""
this[WorkshopTable.startTime] = Instant.parse(workshop.startTimeZulu)
this[WorkshopTable.endTime] = Instant.parse(workshop.endTimeZulu)
this[WorkshopTable.capacity] = WORKSHOP_CAPACITY
this[WorkshopTable.active] = true
}
}

private suspend fun upsert(workshops: List<Workshop>) = dbQuery {
WorkshopTable.batchUpsert(workshops) { workshop ->
this[WorkshopTable.id] = workshop.id
this[WorkshopTable.title] = workshop.title
this[WorkshopTable.description] = workshop.description
this[WorkshopTable.startTime] = workshop.startTime
this[WorkshopTable.endTime] = workshop.endTime
this[WorkshopTable.capacity] = WORKSHOP_CAPACITY
this[WorkshopTable.active] = workshop.active
}
}

private suspend fun setWorkshopsToDisabled(activeWorkshops: List<WorkshopImport>) {
val activeWorkshopsIds = activeWorkshops.map { it.id }
val allDisabledList = list()
.filterNot { it.id in activeWorkshopsIds }
.map { it.copy(active = false) }
val t = upsert(allDisabledList)
}

suspend fun update(workshops: List<WorkshopImport>) {

dbQuery {
setWorkshopsToDisabled(workshops)
upsertActive(workshops)

}
}
}
Loading

0 comments on commit 1c731ba

Please sign in to comment.