feature #6: implement route for search articles

This commit is contained in:
2019-07-31 23:07:58 +02:00
parent 3bf7ee1d13
commit 4c13d18e8d
11 changed files with 97 additions and 38 deletions

View File

@@ -23,20 +23,21 @@ repositories {
}
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
compile("io.ktor:ktor-server-netty:$ktor_version")
compile("ch.qos.logback:logback-classic:$logback_version")
compile("io.ktor:ktor-server-core:$ktor_version")
compile("io.ktor:ktor-locations:$ktor_version")
compile("io.ktor:ktor-auth:$ktor_version")
compile("io.ktor:ktor-auth-jwt:$ktor_version")
compile("io.ktor:ktor-gson:$ktor_version")
compile("org.koin:koin-ktor:$koinVersion")
compile("io.ktor:ktor-jackson:$ktor_version")
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9")
compile("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.9")
compile("fr.postgresjson:postgresjson:$postgresjson_version")
testCompile("io.ktor:ktor-server-tests:$ktor_version")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
implementation("io.ktor:ktor-server-netty:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")
implementation("io.ktor:ktor-server-core:$ktor_version")
implementation("io.ktor:ktor-locations:$ktor_version")
implementation("io.ktor:ktor-auth:$ktor_version")
implementation("io.ktor:ktor-auth-jwt:$ktor_version")
implementation("io.ktor:ktor-gson:$ktor_version")
implementation("org.koin:koin-ktor:$koinVersion")
implementation("io.ktor:ktor-jackson:$ktor_version")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.9")
implementation("net.pearx.kasechange:kasechange-jvm:1.1.0")
implementation("fr.postgresjson:postgresjson:$postgresjson_version")
testImplementation("io.ktor:ktor-server-tests:$ktor_version")
}
kotlin.sourceSets["main"].kotlin.srcDirs("src")

View File

@@ -4,7 +4,7 @@
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>

View File

@@ -16,5 +16,3 @@ end;
$$;
-- drop function if exists find_article_by_id(uuid, out json);
select find_article_by_id('12fed2f3-2a7d-434b-87e6-5a9895f9d12d')

View File

@@ -0,0 +1,41 @@
create or replace function find_articles(
search text default null,
direction text default 'desc',
sort text default 'created_at',
"limit" int default 50,
"offset" int default 0,
out resource json,
out total int
) language plpgsql as
$$
begin
select json_agg(t), (select count(id) from article)
into resource, total
from (
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by
from article as a
where title ilike '%'||"search"||'%'
order by
case direction when 'asc' then
case sort
when 'title' then a.title
when 'created_at' then a.created_at::text
else null
end
end,
case direction when 'desc' then
case sort
when 'title' then a.title
when 'created_at' then a.created_at::text
end
end
desc,
a.created_at desc
limit "limit" offset "offset"
) as t;
end;
$$;
-- drop function if exists find_articles(json, int, int);

View File

@@ -6,8 +6,7 @@ begin
select to_json(t) into resource
from (
select
z.*,
find_user_by_id(z.user_id) as "user"
z.*
from citizen as z
where z.id = _id
) as t;

View File

@@ -15,4 +15,4 @@ class Article(
):
UuidEntity(id),
EntityCreatedAt by EntityCreatedAtImp(),
CreatedBy<User> by EntityCreatedByImp()
CreatedBy<Citizen> by EntityCreatedByImp()

View File

@@ -7,18 +7,18 @@ import java.util.*
class Citizen(
id: UUID,
var name: Name,
var birthday: String,
var userId: String,
var voteAnnonymous: Boolean,
var followAnnonymous: Boolean,
var user: User
id: UUID?,
var name: Name?,
var birthday: String?,
var userId: String?,
var voteAnnonymous: Boolean?,
var followAnnonymous: Boolean?,
var user: User?
) : UuidEntity(id),
EntityCreatedAt by EntityCreatedAtImp() {
data class Name(
var civility: String,
var lastName: String,
var firstName: String
var civility: String?,
var lastName: String?,
var firstName: String?
)
}

View File

@@ -1,7 +1,6 @@
package fr.dcproject.entity
import fr.postgresjson.entity.*
import fr.postgresjson.entity.User
import org.joda.time.DateTime
import java.util.*
@@ -13,5 +12,4 @@ class User(
override var updatedAt: DateTime?
) : UuidEntity(id),
EntityCreatedAt by EntityCreatedAtImp(),
EntityUpdatedAt by EntityUpdatedAtImp(),
User<UUID?>
EntityUpdatedAt by EntityUpdatedAtImp()

View File

@@ -1,8 +1,10 @@
package fr.dcproject.repository
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
import fr.postgresjson.entity.EntitiesCollections
import fr.postgresjson.repository.RepositoryI
import net.pearx.kasechange.toSnakeCase
import java.util.*
import fr.dcproject.entity.Article as ArticleEntity
@@ -19,6 +21,16 @@ class Article(override var requester: Requester) : RepositoryI<ArticleEntity> {
}
}
fun find(page: Int = 1, limit: Int = 50, sort: String? = null, direction: Direction? = null, search: String? = null): Paginated<ArticleEntity> {
return requester
.getFunction("find_articles")
.select(page, limit,
"sort" to sort?.toSnakeCase(),
"direction" to direction,
"search" to search
)
}
fun upsert(article: ArticleEntity): ArticleEntity? {
return requester
.getFunction("upsert_article")
@@ -26,4 +38,9 @@ class Article(override var requester: Requester) : RepositoryI<ArticleEntity> {
EntitiesCollections().set(it)
}
}
enum class Direction {
asc,
desc
}
}

View File

@@ -1,14 +1,12 @@
package fr.dcproject.routes
import Paths
import fr.postgresjson.serializer.serialize
import io.ktor.application.call
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.get
import io.ktor.locations.post
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.Route
import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.repository.Article as ArticleRepository
@@ -16,11 +14,14 @@ import fr.dcproject.repository.Article as ArticleRepository
@KtorExperimentalLocationsAPI
fun Route.article(repo: ArticleRepository) {
get<Paths.ArticlesRequest> {
call.respondText("todo")
val articles = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
call.respond(articles)
}
get<Paths.ArticleRequest> {
call.respondText(it.article.serialize())
call.respond(it.article)
}
post<Paths.PostArticleRequest>() {
val article = call.receive<ArticleEntity>()
repo.upsert(article)

View File

@@ -1,10 +1,14 @@
import fr.dcproject.entity.Article
import fr.dcproject.repository.Article.Direction
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
@KtorExperimentalLocationsAPI
object Paths {
@Location("/articles") class ArticlesRequest
@Location("/articles") class ArticlesRequest(page: Int = 1, limit: Int = 50, val sort: String? = null, val direction: Direction? = null, val search: String? = null) {
val page: Int = if (page < 1) 1 else page
val limit: Int = if (limit > 50) 50 else if (limit < 1) 1 else limit
}
@Location("/articles/{article}") class ArticleRequest(val article: Article)
@Location("/articles") class PostArticleRequest
}