Compare commits
4 Commits
24242377b9
...
36c578dc8c
Author | SHA1 | Date | |
---|---|---|---|
|
36c578dc8c | ||
|
4ba070d513 | ||
|
30dd0fcea9 | ||
|
3dc988573d |
51
.drone.yml
51
.drone.yml
@ -1,6 +1,6 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
name: analyseAndBuild
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
@ -19,4 +19,51 @@ steps:
|
||||
SONAR_HOST_URL:
|
||||
from_secret: sonarScannerHostUrl
|
||||
SONAR_LOGIN:
|
||||
from_secret: sonarScannerLogin
|
||||
from_secret: sonarScannerLogin
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: Deploy
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: maven:3-jdk-11
|
||||
commands:
|
||||
- mvn install -DskipTests=true -Dmaven.javadoc.skip=true
|
||||
- name: scpFiles
|
||||
image: appleboy/drone-scp
|
||||
settings:
|
||||
host: amine-louveau.fr
|
||||
username: ubuntu
|
||||
key:
|
||||
from_secret: privateKey
|
||||
port: 22
|
||||
target: /home/ubuntu/courses-jar
|
||||
source: target/*
|
||||
- name: deploy
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: amine-louveau.fr
|
||||
user: ubuntu
|
||||
key:
|
||||
from_secret: privateKey
|
||||
command_timeout: 2m
|
||||
script:
|
||||
- sudo service ldc stop
|
||||
- cd /home/ubuntu/courses-jar
|
||||
- mv target/* ./
|
||||
- sudo chown ubuntu:ubuntu ./*
|
||||
- sudo mv ./liste-de-courses-1.4-SNAPSHOT-jar-with-dependencies.jar /usr/local/bin/ #todo change file to variable
|
||||
- cd /usr/local/bin/
|
||||
- sudo rm ldc.jar
|
||||
- sudo ln -s liste-de-courses-1.4-SNAPSHOT-jar-with-dependencies.jar ldc.jar #todo change file to variable
|
||||
- sudo service ldc start
|
||||
trigger:
|
||||
event:
|
||||
- promote
|
||||
target:
|
||||
- production
|
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<artifactId>liste-de-courses</artifactId>
|
||||
<groupId>fr.louveau-amine</groupId>
|
||||
<version>1.3-SNAPSHOT</version>
|
||||
<version>1.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>liste-de-courses</name>
|
||||
|
80
src/main/kotlin/MigrationsController.kt
Normal file
80
src/main/kotlin/MigrationsController.kt
Normal file
@ -0,0 +1,80 @@
|
||||
import dao.*
|
||||
import dao.old.Items
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.deleteAll
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
|
||||
class MigrationsController {
|
||||
private val migrations: Map<String, () -> Boolean> = mapOf(
|
||||
"move-items-to-new-table" to {moveItemsToNewTable()},
|
||||
"unchecked-position-change" to {updatePositionForUnchecked()}
|
||||
)
|
||||
|
||||
fun checkMigrationsToDo() {
|
||||
this.migrations.forEach {
|
||||
transaction {
|
||||
val migrationWithName = Migration.find { Migrations.identifier eq it.key }.firstOrNull()
|
||||
if (migrationWithName == null) {
|
||||
Migration.new {
|
||||
identifier = it.key
|
||||
}
|
||||
println("Migration ${it.key} will start now.")
|
||||
it.value()
|
||||
Migrations.update({Migrations.identifier eq it.key}) {
|
||||
it[done] = true
|
||||
}
|
||||
println("Migration ${it.key} done.")
|
||||
} else if (!migrationWithName.done) {
|
||||
println("Migration ${it.key} not done yet. Redoing.")
|
||||
it.value()
|
||||
Migrations.update({Migrations.identifier eq it.key}) {
|
||||
it[done] = true
|
||||
}
|
||||
println("Migration ${it.key} done.")
|
||||
} else {
|
||||
println("Migration ${it.key} done.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveItemsToNewTable() : Boolean {
|
||||
try {
|
||||
transaction {
|
||||
Items.selectAll().forEach {
|
||||
ItemV2.new {
|
||||
list = it[Items.list]
|
||||
content = it[Items.content]
|
||||
position = if (it[Items.checked]) null else it[Items.position]
|
||||
checked = it[Items.checked]
|
||||
}
|
||||
}
|
||||
Items.deleteAll()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun updatePositionForUnchecked() : Boolean {
|
||||
try {
|
||||
transaction {
|
||||
Lists.selectAll().forEach {
|
||||
var i = 0
|
||||
ItemV2.find { ItemsV2.list eq it[Lists.id].value and (ItemsV2.checked eq false) }
|
||||
.sortedBy { it.position }
|
||||
.forEach {
|
||||
it.position = i
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ class DB {
|
||||
val list = List.findById(resourceId)
|
||||
|
||||
if (list != null) {
|
||||
Item.find { Items.list eq list.id.value}.forEach { i -> i.delete() }
|
||||
ItemV2.find { ItemsV2.list eq list.id.value}.forEach { i -> i.delete() }
|
||||
}
|
||||
|
||||
list?.delete() ?: ctx.status(404)
|
||||
@ -69,7 +69,7 @@ class DB {
|
||||
transaction {
|
||||
val listOpt = List.findById(resourceID)
|
||||
if (listOpt != null) {
|
||||
val items = Item.find { Items.list eq resourceID }
|
||||
val items = ItemV2.find { ItemsV2.list eq resourceID }
|
||||
.sortedBy { it.position }
|
||||
|
||||
ctx.json(listOpt.toViewWithItems(items))
|
||||
@ -81,17 +81,15 @@ class DB {
|
||||
|
||||
fun createItem(listId: Int, c: ItemView, ctx: Context) {
|
||||
transaction {
|
||||
val allITems = Item.find { Items.list eq listId }.sortedBy { it.position }
|
||||
val firstChecked = allITems.firstOrNull { it.checked }
|
||||
val p = firstChecked?.position ?: ((allITems.lastOrNull()?.position ?: - 1) + 1)
|
||||
val listOpt = List.findById(listId)
|
||||
if (listOpt != null) {
|
||||
reorderElements(listId, p)
|
||||
val count = ItemV2.find { ItemsV2.list eq listId and (ItemsV2.checked eq false) }.count()
|
||||
val p = (count + 1)
|
||||
|
||||
var i = Item.new {
|
||||
var i = ItemV2.new {
|
||||
list = listId
|
||||
content = c.content
|
||||
position = p
|
||||
position = p.toInt()
|
||||
checked = false
|
||||
}
|
||||
|
||||
@ -103,17 +101,19 @@ class DB {
|
||||
|
||||
}
|
||||
|
||||
private fun reorderElements(listId: Int, position: Int, itemId: Int? = null) {
|
||||
private fun reorderElements(listId: Int, position: Int?, itemId: Int? = null) {
|
||||
transaction {
|
||||
var i = 0
|
||||
Item.find { Items.list eq listId and (Items.id neq itemId) }
|
||||
ItemV2.find { ItemsV2.list eq listId and (ItemsV2.id neq itemId and (ItemsV2.checked eq false)) }
|
||||
.sortedBy { it.position }
|
||||
.forEach {
|
||||
if (i == position) {
|
||||
if (position != null && i == position) {
|
||||
i++
|
||||
}
|
||||
if (it.position != null) {
|
||||
it.position = i
|
||||
i++
|
||||
}
|
||||
it.position = i
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,11 +122,11 @@ class DB {
|
||||
transaction {
|
||||
val listOpt = List.findById(listId)
|
||||
if (listOpt != null) {
|
||||
val item = Item.find { Items.list eq listId and (Items.id eq itemId) }.limit(1).firstOrNull()
|
||||
val item = ItemV2.find { ItemsV2.list eq listId and (ItemsV2.id eq itemId) }.limit(1).firstOrNull()
|
||||
if (item != null) {
|
||||
item.delete()
|
||||
var i = 0
|
||||
Item.all()
|
||||
ItemV2.all()
|
||||
.sortedBy { it.position }
|
||||
.forEach {
|
||||
it.position = i
|
||||
@ -145,27 +145,21 @@ class DB {
|
||||
transaction {
|
||||
val listOpt = List.findById(listId)
|
||||
if (listOpt != null) {
|
||||
val item = Item.find { Items.list eq listId and (Items.id eq itemId) }.limit(1).firstOrNull()
|
||||
val item = ItemV2.find { ItemsV2.list eq listId and (ItemsV2.id eq itemId) }.limit(1).firstOrNull()
|
||||
if (item != null) {
|
||||
var p = body.position
|
||||
if (body.position != null) {
|
||||
reorderElements(listId, body.position, itemId)
|
||||
item.position = body.position
|
||||
}
|
||||
if (body.checked != null) {
|
||||
val allITems = Item.find { Items.list eq listId }.sortedBy { it.position }
|
||||
val firstChecked = allITems.firstOrNull { it.checked }
|
||||
p = if (body.checked) {
|
||||
if (firstChecked != null) {
|
||||
firstChecked.position - 1
|
||||
} else {
|
||||
allITems.lastOrNull()?.position
|
||||
}
|
||||
var p: Int? = if (body.checked) {
|
||||
null
|
||||
} else {
|
||||
firstChecked?.position ?: allITems.lastOrNull()?.position
|
||||
}
|
||||
|
||||
item.checked = body.checked
|
||||
}
|
||||
if (p != null) {
|
||||
reorderElements(listId, p, itemId)
|
||||
(ItemV2.find { ItemsV2.list eq listId and (ItemsV2.checked eq false) }.count() + 1).toInt()
|
||||
}
|
||||
item.position = p
|
||||
reorderElements(listId, p, itemId)
|
||||
item.checked = body.checked
|
||||
}
|
||||
if (body.content != null) {
|
||||
item.content = body.content
|
||||
|
31
src/main/kotlin/dao/ItemsV2.kt
Normal file
31
src/main/kotlin/dao/ItemsV2.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.IntEntity
|
||||
import org.jetbrains.exposed.dao.IntEntityClass
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object ItemsV2 : IntIdTable() {
|
||||
val list = integer("list")
|
||||
val content = varchar("content", 256)
|
||||
val position = integer("position").nullable()
|
||||
val checked = bool("checked").default(false)
|
||||
}
|
||||
|
||||
class ItemV2(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<ItemV2>(ItemsV2)
|
||||
|
||||
var list by ItemsV2.list
|
||||
var content by ItemsV2.content
|
||||
var position by ItemsV2.position
|
||||
var checked by ItemsV2.checked
|
||||
|
||||
|
||||
}
|
||||
fun ItemV2.toView(): ItemView {
|
||||
return ItemView(this.id.value, this.content, this.checked, this.position)
|
||||
}
|
||||
|
||||
data class ItemView(val id: Int, val content: String, val checked: Boolean = false, val position: Int?)
|
||||
|
||||
data class ItemPatchView(val id: Int, val content: String?, val checked: Boolean?, val position: Int?)
|
@ -20,7 +20,7 @@ fun List.toView(): ListView {
|
||||
return ListView(this.id.value, this.name)
|
||||
}
|
||||
|
||||
fun List.toViewWithItems(items: kotlin.collections.List<Item>): ListViewWithItems {
|
||||
fun List.toViewWithItems(items: kotlin.collections.List<ItemV2>): ListViewWithItems {
|
||||
return ListViewWithItems(this.id.value, this.name, items.map { it.toView() })
|
||||
}
|
||||
|
||||
|
24
src/main/kotlin/dao/Migrations.kt
Normal file
24
src/main/kotlin/dao/Migrations.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package dao
|
||||
|
||||
import org.jetbrains.exposed.dao.IntEntity
|
||||
import org.jetbrains.exposed.dao.IntEntityClass
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object Migrations : IntIdTable() {
|
||||
val identifier = varchar("identifier", 256)
|
||||
val done = bool("done").default(false)
|
||||
}
|
||||
|
||||
class Migration(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<Migration>(Migrations)
|
||||
|
||||
var identifier by Migrations.identifier
|
||||
var done by Migrations.done
|
||||
}
|
||||
|
||||
fun Migration.toView(): MigrationView {
|
||||
return MigrationView(this.id.value, this.identifier, this.done)
|
||||
}
|
||||
|
||||
data class MigrationView(val id: Int, val identifier: String, val done: Boolean = false)
|
@ -1,10 +1,11 @@
|
||||
package dao
|
||||
package dao.old
|
||||
|
||||
import org.jetbrains.exposed.dao.IntEntity
|
||||
import org.jetbrains.exposed.dao.IntEntityClass
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
@Deprecated("Position should be nullable")
|
||||
object Items : IntIdTable() {
|
||||
val list = integer("list")
|
||||
val content = varchar("content", 256)
|
||||
@ -12,6 +13,7 @@ object Items : IntIdTable() {
|
||||
val checked = bool("checked").default(false)
|
||||
}
|
||||
|
||||
@Deprecated("Position should be nullable")
|
||||
class Item(id: EntityID<Int>) : IntEntity(id) {
|
||||
companion object : IntEntityClass<Item>(Items)
|
||||
|
||||
@ -21,11 +23,4 @@ class Item(id: EntityID<Int>) : IntEntity(id) {
|
||||
var checked by Items.checked
|
||||
|
||||
|
||||
}
|
||||
fun Item.toView(): ItemView {
|
||||
return ItemView(this.id.value, this.content, this.checked, this.position)
|
||||
}
|
||||
|
||||
data class ItemView(val id: Int, val content: String, val checked: Boolean = false, val position: Int?)
|
||||
|
||||
data class ItemPatchView(val id: Int, val content: String?, val checked: Boolean?, val position: Int?)
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
import dao.Items
|
||||
import dao.Key
|
||||
import dao.Keys
|
||||
import dao.Lists
|
||||
import dao.*
|
||||
import dao.old.Items
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.apibuilder.ApiBuilder.*
|
||||
import io.javalin.core.security.Role
|
||||
@ -15,6 +13,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
|
||||
enum class ApiRole : Role { PUBLIC, BASIC_AUTHED, API_AUTHED }
|
||||
|
||||
fun main() {
|
||||
var migrationsController = MigrationsController()
|
||||
val app = Javalin.create {
|
||||
it.accessManager { handler, ctx, permittedRoles ->
|
||||
transaction {
|
||||
@ -38,7 +37,11 @@ fun main() {
|
||||
addLogger(StdOutSqlLogger)
|
||||
SchemaUtils.create (Lists)
|
||||
SchemaUtils.create (Items)
|
||||
SchemaUtils.create (ItemsV2)
|
||||
SchemaUtils.create (Keys)
|
||||
SchemaUtils.create (Migrations)
|
||||
migrationsController.checkMigrationsToDo()
|
||||
|
||||
}
|
||||
|
||||
app.routes {
|
||||
|
Loading…
Reference in New Issue
Block a user