feature #6: implement route for search articles
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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')
|
||||
41
resources/sql/functions/article/find_articles.sql
Normal file
41
resources/sql/functions/article/find_articles.sql
Normal 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);
|
||||
@@ -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;
|
||||
|
||||
@@ -15,4 +15,4 @@ class Article(
|
||||
):
|
||||
UuidEntity(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
CreatedBy<User> by EntityCreatedByImp()
|
||||
CreatedBy<Citizen> by EntityCreatedByImp()
|
||||
@@ -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?
|
||||
)
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user