Skip to content

Commit 12ef6db

Browse files
authored
Merge pull request #631 from NDLANO/language-code-param
Add languagecode codec param
2 parents 62963e0 + 36d22f5 commit 12ef6db

File tree

27 files changed

+355
-216
lines changed

27 files changed

+355
-216
lines changed

article-api/src/main/scala/no/ndla/articleapi/controller/ArticleControllerV2.scala

+12-12
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import no.ndla.articleapi.validation.ContentValidator
1919
import no.ndla.articleapi.Props
2020
import no.ndla.common.ContentURIUtil.parseArticleIdAndRevision
2121
import no.ndla.common.model.api.CommaSeparatedList.*
22-
import no.ndla.language.Language
22+
import no.ndla.common.model.api.LanguageCode
2323
import no.ndla.language.Language.AllLanguages
2424
import no.ndla.network.tapir.NoNullJsonPrinter.jsonBody
2525
import no.ndla.network.tapir.Parameters.feideHeader
@@ -49,9 +49,9 @@ trait ArticleControllerV2 {
4949
private val queryParam =
5050
query[Option[String]]("query").description("Return only articles with content matching the specified query.")
5151
private val language =
52-
query[String]("language")
52+
query[LanguageCode]("language")
5353
.description("The ISO 639-1 language code describing language.")
54-
.default(AllLanguages)
54+
.default(LanguageCode(AllLanguages))
5555
private val license = query[Option[String]]("license").description(
5656
"Return only results with provided license. Specifying 'all' gives all articles regardless of licence."
5757
)
@@ -148,7 +148,7 @@ trait ArticleControllerV2 {
148148
queryOrEmpty,
149149
parsedPageSize,
150150
parsedPageNo,
151-
Language.languageOrParam(language)
151+
language.code
152152
)
153153
.asRight
154154
}
@@ -226,7 +226,7 @@ trait ArticleControllerV2 {
226226
scrollId,
227227
grepCodes
228228
) =>
229-
scrollSearchOr(scrollId, language) {
229+
scrollSearchOr(scrollId, language.code) {
230230
val sort = Sort.valueOf(maybeSort.getOrElse(""))
231231
val pageSize = maybePageSize.getOrElse(DefaultPageSize)
232232
val page = maybePageNo.getOrElse(1)
@@ -235,7 +235,7 @@ trait ArticleControllerV2 {
235235
search(
236236
query,
237237
sort,
238-
Language.languageOrParam(language),
238+
language.code,
239239
license,
240240
page,
241241
pageSize,
@@ -276,7 +276,7 @@ trait ArticleControllerV2 {
276276
readService
277277
.getArticlesByIds(
278278
ids.values,
279-
Language.languageOrParam(language),
279+
language.code,
280280
fallback,
281281
page,
282282
pageSize,
@@ -294,10 +294,10 @@ trait ArticleControllerV2 {
294294
.out(jsonBody[SearchResultV2DTO])
295295
.out(EndpointOutput.derived[DynamicHeaders])
296296
.serverLogicPure { case (feideToken, searchParams) =>
297-
val language = searchParams.language.getOrElse(AllLanguages)
297+
val language = searchParams.language.getOrElse(LanguageCode(AllLanguages))
298298
val fallback = searchParams.fallback.getOrElse(false)
299299

300-
scrollSearchOr(searchParams.scrollId, language) {
300+
scrollSearchOr(searchParams.scrollId, language.code) {
301301
val query = searchParams.query
302302
val sort = searchParams.sort
303303
val license = searchParams.license
@@ -311,7 +311,7 @@ trait ArticleControllerV2 {
311311
search(
312312
query,
313313
sort,
314-
Language.languageOrParam(language),
314+
language.code,
315315
license,
316316
page,
317317
pageSize,
@@ -338,10 +338,10 @@ trait ArticleControllerV2 {
338338
val (articleId, revisionQuery, feideToken, language, fallback) = params
339339
(parseArticleIdAndRevision(articleId) match {
340340
case (Failure(_), _) =>
341-
readService.getArticleBySlug(articleId, Language.languageOrParam(language), fallback)
341+
readService.getArticleBySlug(articleId, language.code, fallback)
342342
case (Success(articleId), inlineRevision) =>
343343
val revision = inlineRevision.orElse(revisionQuery)
344-
readService.withIdV2(articleId, Language.languageOrParam(language), fallback, revision, feideToken)
344+
readService.withIdV2(articleId, language.code, fallback, revision, feideToken)
345345
}).map(_.Ok())
346346
}
347347

article-api/src/main/scala/no/ndla/articleapi/model/api/ArticleSearchParamsDTO.scala

+23-13
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,31 @@
99
package no.ndla.articleapi.model.api
1010

1111
import no.ndla.articleapi.model.domain.Sort
12+
import no.ndla.common.model.api.LanguageCode
1213
import sttp.tapir.Schema.annotations.description
1314

14-
// format: off
1515
@description("The search parameters")
1616
case class ArticleSearchParamsDTO(
17-
@description("The search query") query: Option[String],
18-
@description("The ISO 639-1 language code describing language used in query-params") language: Option[String],
19-
@description("Return only articles with provided license.") license: Option[String],
20-
@description("The page number of the search hits to display.") page: Option[Int],
21-
@description("The number of search hits to display for each page.") pageSize: Option[Int],
22-
@description("Return only articles that have one of the provided ids") ids: Option[List[Long]],
23-
@description("Return only articles of specific type(s)") articleTypes: Option[List[String]],
24-
@description("The sorting used on results. Default is by -relevance.") sort: Option[Sort],
25-
@description("Return all matched articles whether they exist on selected language or not.") fallback: Option[Boolean],
26-
@description("A search context retrieved from the response header of a previous search.") scrollId: Option[String],
27-
@description("A comma separated list of codes from GREP API to filter by.") grepCodes: Option[Seq[String]]
17+
@description("The search query")
18+
query: Option[String],
19+
@description("The ISO 639-1 language code describing language used in query-params")
20+
language: Option[LanguageCode],
21+
@description("Return only articles with provided license.")
22+
license: Option[String],
23+
@description("The page number of the search hits to display.")
24+
page: Option[Int],
25+
@description("The number of search hits to display for each page.")
26+
pageSize: Option[Int],
27+
@description("Return only articles that have one of the provided ids")
28+
ids: Option[List[Long]],
29+
@description("Return only articles of specific type(s)")
30+
articleTypes: Option[List[String]],
31+
@description("The sorting used on results. Default is by -relevance.")
32+
sort: Option[Sort],
33+
@description("Return all matched articles whether they exist on selected language or not.")
34+
fallback: Option[Boolean],
35+
@description("A search context retrieved from the response header of a previous search.")
36+
scrollId: Option[String],
37+
@description("A comma separated list of codes from GREP API to filter by.")
38+
grepCodes: Option[Seq[String]]
2839
)
29-
// format: on

audio-api/src/main/scala/no/ndla/audioapi/controller/AudioController.scala

+13-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import no.ndla.common.errors.FileTooBigException
2222
import no.ndla.language.Language
2323
import no.ndla.common.implicits.*
2424
import no.ndla.common.model.api.CommaSeparatedList.*
25+
import no.ndla.common.model.api.LanguageCode
2526
import no.ndla.common.model.domain.UploadedFile
2627
import no.ndla.network.tapir.NoNullJsonPrinter.*
2728
import no.ndla.network.tapir.{NonEmptyString, TapirController}
@@ -51,9 +52,9 @@ trait AudioController {
5152
.description("Return only results with titles or tags matching the specified query.")
5253
.schema(NonEmptyString.schemaOpt)
5354
private val language =
54-
query[Option[String]]("language")
55+
query[Option[LanguageCode]]("language")
5556
.description("The ISO 639-1 language code describing language.")
56-
.default(Some(Language.AllLanguages))
57+
.default(Some(LanguageCode(Language.AllLanguages)))
5758
private val license = query[Option[String]]("license").description("Return only audio with provided license.")
5859
private val pageNo = query[Option[Int]]("page").description("The page number of the search hits to display.")
5960
private val pageSize = query[Option[Int]]("page-size").description(
@@ -109,11 +110,12 @@ trait AudioController {
109110
.errorOut(errorOutputsFor(400, 404))
110111
.serverLogicPure {
111112
case (query, language, license, sort, pageNo, pageSize, scrollId, audioType, seriesFilter, fallback) =>
112-
scrollSearchOr(scrollId, language.getOrElse(Language.AllLanguages)) {
113+
val lang = language.getOrElse(LanguageCode(Language.AllLanguages))
114+
scrollSearchOr(scrollId, lang.code) {
113115
val shouldScroll = scrollId.exists(InitialScrollContextKeywords.contains)
114116
search(
115117
query.underlying,
116-
language,
118+
language.map(_.code),
117119
license,
118120
sort.flatMap(Sort.valueOf),
119121
pageSize,
@@ -134,11 +136,12 @@ trait AudioController {
134136
.out(EndpointOutput.derived[SummaryWithHeader])
135137
.errorOut(errorOutputsFor(400, 404))
136138
.serverLogicPure { searchParams =>
137-
scrollSearchOr(searchParams.scrollId, searchParams.language.getOrElse(Language.AllLanguages)) {
139+
val lang = searchParams.language.getOrElse(LanguageCode(Language.AllLanguages))
140+
scrollSearchOr(searchParams.scrollId, lang.code) {
138141
val shouldScroll = searchParams.scrollId.exists(InitialScrollContextKeywords.contains)
139142
search(
140143
searchParams.query,
141-
searchParams.language,
144+
searchParams.language.map(_.code),
142145
searchParams.license,
143146
searchParams.sort,
144147
searchParams.pageSize,
@@ -159,7 +162,7 @@ trait AudioController {
159162
.errorOut(errorOutputsFor(400, 404))
160163
.out(jsonBody[AudioMetaInformationDTO])
161164
.serverLogicPure { case (id, language) =>
162-
readService.withId(id, language) match {
165+
readService.withId(id, language.map(_.code)) match {
163166
case Some(audio) => audio.asRight
164167
case None => notFoundWithMsg(s"Audio with id $id not found").asLeft
165168
}
@@ -177,7 +180,7 @@ trait AudioController {
177180
// NOTE: For some weird reason the generated openapi spec fails if this is a List[AudioMetaInformation]
178181
// I assume it is because of the recursive nature of `AudioMetaInformation`.
179182
// For Array[AudioMetaInformation] it works fine so lets just convert it here for now.
180-
readService.getAudiosByIds(audioIds.values, language).map(_.toArray)
183+
readService.getAudiosByIds(audioIds.values, language.map(_.code)).map(_.toArray)
181184
}
182185

183186
def deleteAudio: ServerEndpoint[Any, Eff] = endpoint.delete
@@ -268,9 +271,9 @@ trait AudioController {
268271
case x => x
269272
}
270273

271-
val language = lang.getOrElse(Language.AllLanguages)
274+
val language = lang.getOrElse(LanguageCode(Language.AllLanguages))
272275

273-
readService.getAllTags(query.underlyingOrElse(""), pageSize, pageNo, language)
276+
readService.getAllTags(query.underlyingOrElse(""), pageSize, pageNo, language.code)
274277
}
275278

276279
override val endpoints: List[ServerEndpoint[Any, Eff]] = List(

audio-api/src/main/scala/no/ndla/audioapi/controller/SeriesController.scala

+12-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import no.ndla.network.tapir.NoNullJsonPrinter.*
2121
import no.ndla.network.tapir.TapirUtil.errorOutputsFor
2222
import no.ndla.network.tapir.auth.Permission.AUDIO_API_WRITE
2323
import no.ndla.common.implicits.*
24+
import no.ndla.common.model.api.LanguageCode
2425
import no.ndla.network.tapir.TapirController
2526
import sttp.model.StatusCode
2627
import sttp.tapir.EndpointIO.annotations.{header, jsonbody}
@@ -40,7 +41,7 @@ trait SeriesController {
4041
private val queryString = query[Option[String]]("query")
4142
.description("Return only results with titles or tags matching the specified query.")
4243
private val language =
43-
query[Option[String]]("language").description("The ISO 639-1 language code describing language.")
44+
query[Option[LanguageCode]]("language").description("The ISO 639-1 language code describing language.")
4445
private val pageNo = query[Option[Int]]("page").description("The page number of the search hits to display.")
4546
private val pageSize = query[Option[Int]]("page-size").description(
4647
s"The number of search hits to display for each page. Defaults to $DefaultPageSize and max is $MaxPageSize."
@@ -79,9 +80,10 @@ trait SeriesController {
7980
.in(fallback)
8081
.errorOut(errorOutputsFor(400, 404))
8182
.serverLogicPure { case (query, language, sort, page, pageSize, scrollId, fallback) =>
82-
scrollSearchOr(scrollId, language.getOrElse(Language.AllLanguages)) {
83+
val lang = language.getOrElse(LanguageCode(Language.AllLanguages)).code
84+
scrollSearchOr(scrollId, lang) {
8385
val shouldScroll = scrollId.exists(InitialScrollContextKeywords.contains)
84-
search(query, language, Sort.valueOf(sort), pageSize, page, shouldScroll, fallback.getOrElse(false))
86+
search(query, lang, Sort.valueOf(sort), pageSize, page, shouldScroll, fallback.getOrElse(false))
8587
}
8688
}
8789

@@ -93,16 +95,16 @@ trait SeriesController {
9395
.out(EndpointOutput.derived[SummaryWithHeader])
9496
.errorOut(errorOutputsFor(400, 404))
9597
.serverLogicPure { searchParams =>
96-
scrollSearchOr(searchParams.scrollId, searchParams.language.getOrElse(Language.AllLanguages)) {
98+
val language = searchParams.language.getOrElse(LanguageCode(Language.AllLanguages))
99+
scrollSearchOr(searchParams.scrollId, language.code) {
97100
val query = searchParams.query
98-
val language = searchParams.language
99101
val sort = searchParams.sort
100102
val pageSize = searchParams.pageSize
101103
val page = searchParams.page
102104
val shouldScroll = searchParams.scrollId.exists(InitialScrollContextKeywords.contains)
103105
val fallback = searchParams.fallback.getOrElse(false)
104106

105-
search(query, language, sort, pageSize, page, shouldScroll, fallback)
107+
search(query, language.code, sort, pageSize, page, shouldScroll, fallback)
106108
}
107109
}
108110

@@ -114,7 +116,7 @@ trait SeriesController {
114116
.errorOut(errorOutputsFor(400, 404))
115117
.out(jsonBody[SeriesDTO])
116118
.serverLogicPure { case (id, language) =>
117-
readService.seriesWithId(id, language)
119+
readService.seriesWithId(id, language.map(_.code))
118120
}
119121

120122
def deleteSeries: ServerEndpoint[Any, Eff] = endpoint.delete
@@ -184,7 +186,7 @@ trait SeriesController {
184186

185187
private def search(
186188
query: Option[String],
187-
language: Option[String],
189+
language: String,
188190
sort: Option[Sort],
189191
pageSize: Option[Int],
190192
page: Option[Int],
@@ -195,7 +197,7 @@ trait SeriesController {
195197
case Some(q) =>
196198
SeriesSearchSettings(
197199
query = Some(q),
198-
language = language,
200+
language = Some(language),
199201
page = page,
200202
pageSize = pageSize,
201203
sort = sort.getOrElse(Sort.ByRelevanceDesc),
@@ -206,7 +208,7 @@ trait SeriesController {
206208
case None =>
207209
SeriesSearchSettings(
208210
query = None,
209-
language = language,
211+
language = Some(language),
210212
page = page,
211213
pageSize = pageSize,
212214
sort = sort.getOrElse(Sort.ByTitleAsc),

audio-api/src/main/scala/no/ndla/audioapi/model/api/SearchParamsDTO.scala

+23-12
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,31 @@
99
package no.ndla.audioapi.model.api
1010

1111
import no.ndla.audioapi.model.Sort
12+
import no.ndla.common.model.api.LanguageCode
1213
import sttp.tapir.Schema.annotations.description
1314

14-
// format: off
1515
@description("The search parameters")
1616
case class SearchParamsDTO(
17-
@description("Return only audio with titles, alt-texts or tags matching the specified query.") query: Option[String],
18-
@description("Return only audio with provided license.") license: Option[String],
19-
@description("The ISO 639-1 language code describing language used in query-params") language: Option[String],
20-
@description("The page number of the search hits to display.") page: Option[Int],
21-
@description("The number of search hits to display for each page.") pageSize: Option[Int],
22-
@description("The sorting used on results. Default is by -relevance.") sort: Option[Sort],
23-
@description("A search context retrieved from the response header of a previous search.") scrollId: Option[String],
24-
@description("Type of audio to filter by.") audioType: Option[String],
25-
@description("Filter result by whether they are a part of a series or not.\n'true' will return only audios that are a part of a series.\n'false' will return only audios that are NOT a part of a series.\nNot specifying will return both audios that are a part of a series and not.") filterBySeries: Option[Boolean],
26-
@description("Return all matched audios whether they exist on selected language or not.") fallback: Option[Boolean]
17+
@description("Return only audio with titles, alt-texts or tags matching the specified query.")
18+
query: Option[String],
19+
@description("Return only audio with provided license.")
20+
license: Option[String],
21+
@description("The ISO 639-1 language code describing language used in query-params")
22+
language: Option[LanguageCode],
23+
@description("The page number of the search hits to display.")
24+
page: Option[Int],
25+
@description("The number of search hits to display for each page.")
26+
pageSize: Option[Int],
27+
@description("The sorting used on results. Default is by -relevance.")
28+
sort: Option[Sort],
29+
@description("A search context retrieved from the response header of a previous search.")
30+
scrollId: Option[String],
31+
@description("Type of audio to filter by.")
32+
audioType: Option[String],
33+
@description(
34+
"Filter result by whether they are a part of a series or not.\n'true' will return only audios that are a part of a series.\n'false' will return only audios that are NOT a part of a series.\nNot specifying will return both audios that are a part of a series and not."
35+
)
36+
filterBySeries: Option[Boolean],
37+
@description("Return all matched audios whether they exist on selected language or not.")
38+
fallback: Option[Boolean]
2739
)
28-
// format: on

audio-api/src/main/scala/no/ndla/audioapi/model/api/SeriesSearchParamsDTO.scala

+15-9
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,23 @@
99
package no.ndla.audioapi.model.api
1010

1111
import no.ndla.audioapi.model.Sort
12+
import no.ndla.common.model.api.LanguageCode
1213
import sttp.tapir.Schema.annotations.description
1314

14-
// format: off
1515
@description("The search parameters")
1616
case class SeriesSearchParamsDTO(
17-
@description("Return only series with titles, alt-texts or tags matching the specified query.") query: Option[String],
18-
@description("The ISO 639-1 language code describing language used in query-params") language: Option[String],
19-
@description("The page number of the search hits to display.") page: Option[Int],
20-
@description("The number of search hits to display for each page.") pageSize: Option[Int],
21-
@description("The sorting used on results. Default is by -relevance.") sort: Option[Sort],
22-
@description("A search context retrieved from the response header of a previous search.") scrollId: Option[String],
23-
@description("Return all matched series whether they exist on selected language or not.") fallback: Option[Boolean]
17+
@description("Return only series with titles, alt-texts or tags matching the specified query.")
18+
query: Option[String],
19+
@description("The ISO 639-1 language code describing language used in query-params")
20+
language: Option[LanguageCode],
21+
@description("The page number of the search hits to display.")
22+
page: Option[Int],
23+
@description("The number of search hits to display for each page.")
24+
pageSize: Option[Int],
25+
@description("The sorting used on results. Default is by -relevance.")
26+
sort: Option[Sort],
27+
@description("A search context retrieved from the response header of a previous search.")
28+
scrollId: Option[String],
29+
@description("Return all matched series whether they exist on selected language or not.")
30+
fallback: Option[Boolean]
2431
)
25-
// format: on

0 commit comments

Comments
 (0)