Skip to content

Commit

Permalink
Add created field for learningpaths
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarvelle committed Nov 19, 2024
1 parent 4ad8f3e commit f1808a9
Show file tree
Hide file tree
Showing 29 changed files with 132 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ case class LearningPath(
duration: Option[Int],
status: LearningPathStatus,
verificationStatus: LearningPathVerificationStatus,
created: NDLADate,
lastUpdated: NDLADate,
tags: Seq[Tag],
owner: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UPDATE learningpaths lp
SET document=(
SELECT document || jsonb_build_object('created', document ->> 'lastUpdated')
FROM learningpaths lp2
WHERE lp.id = lp2.id
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ case class LearningPathSummaryV2(
@description("Url to where a cover photo can be found") coverPhotoUrl: Option[String],
@description("The duration of the learningpath in minutes") duration: Option[Int],
@description("The publishing status of the learningpath.") status: String,
@description("The date when this learningpath was created.") created: NDLADate,
@description("The date when this learningpath was last updated.") lastUpdated: NDLADate,
@description("Searchable tags for the learningpath") tags: LearningPathTags,
@description("The contributors of this learningpath") copyright: Copyright,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ case class LearningPathV2(
@description("The duration of the learningpath in minutes") duration: Option[Int],
@description("The publishing status of the learningpath") status: String,
@description("Verification status") verificationStatus: String,
@description("The date when this learningpath was created.") created: NDLADate,
@description("The date when this learningpath was last updated.") lastUpdated: NDLADate,
@description("Searchable tags for the learningpath") tags: LearningPathTags,
@description("Describes the copyright information for the learningpath") copyright: Copyright,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ case class SearchableLearningPath(
duration: Option[Int],
status: String,
verificationStatus: String,
created: NDLADate,
lastUpdated: NDLADate,
defaultTitle: Option[String],
tags: SearchableLanguageList,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import java.util.UUID
import scala.util.Try

trait LearningPathRepositoryComponent extends StrictLogging {
this: DataSource with Props =>
this: DataSource & Props =>
val learningPathRepository: LearningPathRepository

def inTransaction[A](work: DBSession => A)(implicit session: DBSession = null): A = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ trait ConverterService {
val converterService: ConverterService

class ConverterService {
import props._
import props.*

def asEmbedUrlV2(embedUrl: api.EmbedUrlV2, language: String): EmbedUrl = {
learningpath.EmbedUrl(embedUrl.url, language, EmbedType.valueOfOrError(embedUrl.embedType))
Expand Down Expand Up @@ -145,6 +145,7 @@ trait ConverterService {
lp.duration,
lp.status.toString,
lp.verificationStatus.toString,
lp.created,
lp.lastUpdated,
tags,
asApiCopyright(lp.copyright),
Expand Down Expand Up @@ -408,6 +409,7 @@ trait ConverterService {
learningpath.LearningPathStatus.PRIVATE,
getVerificationStatus(user),
clock.now(),
clock.now(),
domainTags,
ownerId,
converterService.asCopyright(newLearningPath.copyright),
Expand Down Expand Up @@ -460,6 +462,7 @@ trait ConverterService {
learningpath.coverPhotoId.flatMap(asCoverPhoto).map(_.url),
learningpath.duration,
learningpath.status.toString,
learningpath.created,
learningpath.lastUpdated,
tags,
asApiCopyright(learningpath.copyright),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,9 @@ import scala.annotation.tailrec
import scala.util.{Failure, Success, Try}

trait UpdateService {
this: LearningPathRepositoryComponent
with ReadService
with ConverterService
with SearchIndexService
with Clock
with LearningStepValidator
with LearningPathValidator
with TaxonomyApiClient
with FeideApiClient
with SearchApiClient
with Props
with RedisClient =>
this: LearningPathRepositoryComponent & ReadService & ConverterService & SearchIndexService & Clock &
LearningStepValidator & LearningPathValidator & TaxonomyApiClient & FeideApiClient & SearchApiClient & Props &
RedisClient =>
val updateService: UpdateService

class UpdateService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import no.ndla.search.SearchLanguage
import no.ndla.search.model.{LanguageValue, SearchableLanguageList, SearchableLanguageValues}

trait SearchConverterServiceComponent {
this: ConverterService with Props =>
this: ConverterService & Props =>
val searchConverterService: SearchConverterService

class SearchConverterService {
Expand Down Expand Up @@ -57,6 +57,7 @@ trait SearchConverterServiceComponent {
searchableLearningPath.coverPhotoUrl,
searchableLearningPath.duration,
searchableLearningPath.status,
searchableLearningPath.created,
searchableLearningPath.lastUpdated,
findByLanguageOrBestEffort(tags, language)
.getOrElse(api.LearningPathTags(Seq(), DefaultLanguage)),
Expand Down Expand Up @@ -86,6 +87,7 @@ trait SearchConverterServiceComponent {
learningPath.duration,
learningPath.status.toString,
learningPath.verificationStatus.toString,
learningPath.created,
learningPath.lastUpdated,
defaultTitle.map(_.title),
SearchableLanguageList(learningPath.tags.map(tags => LanguageValue(tags.language, tags.tags))),
Expand All @@ -95,7 +97,7 @@ trait SearchConverterServiceComponent {
)
}

def asSearchableLearningStep(learningStep: LearningStep): SearchableLearningStep = {
private def asSearchableLearningStep(learningStep: LearningStep): SearchableLearningStep = {
SearchableLearningStep(
learningStep.`type`.toString,
learningStep.embedUrl.map(_.url).toList,
Expand Down Expand Up @@ -125,7 +127,7 @@ trait SearchConverterServiceComponent {
.lastOption
}

val highlightKeys: Option[Map[String, _]] = Option(result.highlight)
val highlightKeys: Option[Map[String, ?]] = Option(result.highlight)
val matchLanguage = keyToLanguage(highlightKeys.getOrElse(Map()).keys)

matchLanguage match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ import no.ndla.common.model.domain.learningpath.LearningPath
import no.ndla.network.tapir.auth.TokenUser

trait SearchIndexService {
this: Elastic4sClient
with SearchConverterServiceComponent
with LearningPathRepositoryComponent
with SearchApiClient
with BaseIndexService
with Props =>
this: Elastic4sClient & SearchConverterServiceComponent & LearningPathRepositoryComponent & SearchApiClient &
BaseIndexService & Props =>
val searchIndexService: SearchIndexService

class SearchIndexService extends BaseIndexService with StrictLogging {
Expand Down Expand Up @@ -165,6 +161,7 @@ trait SearchIndexService {
intField("duration"),
keywordField("status"),
keywordField("verificationStatus"),
dateField("created"),
dateField("lastUpdated"),
keywordField("defaultTitle"),
textField("author"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService, Futu
import scala.util.{Failure, Success, Try}

trait SearchService extends StrictLogging {
this: SearchIndexService with Elastic4sClient with SearchConverterServiceComponent with Props with ErrorHandling =>
this: SearchIndexService & Elastic4sClient & SearchConverterServiceComponent & Props & ErrorHandling =>
val searchService: SearchService

class SearchService {
Expand All @@ -55,7 +55,7 @@ trait SearchService extends StrictLogging {
)
})

def getHitsV2(response: SearchResponse, language: String): Seq[LearningPathSummaryV2] = {
private def getHitsV2(response: SearchResponse, language: String): Seq[LearningPathSummaryV2] = {
response.totalHits match {
case count if count > 0 =>
val resultArray = response.hits.hits.toList
Expand All @@ -75,7 +75,7 @@ trait SearchService extends StrictLogging {
}
}

def hitAsLearningPathSummaryV2(hitString: String, language: String): LearningPathSummaryV2 = {
private def hitAsLearningPathSummaryV2(hitString: String, language: String): LearningPathSummaryV2 = {
val searchable = CirceUtil.unsafeParseAs[SearchableLearningPath](hitString)
searchConverterService.asApiLearningPathSummaryV2(searchable, language)
}
Expand Down Expand Up @@ -220,7 +220,7 @@ trait SearchService extends StrictLogging {
}
}

def pathsFilterQuery(paths: List[String]): Option[NestedQuery] = {
private def pathsFilterQuery(paths: List[String]): Option[NestedQuery] = {
if (paths.isEmpty) None
else {
Some(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ package no.ndla.learningpathapi.validation
import no.ndla.common.errors.ValidationMessage

class DurationValidator {
val DURATION_INVALID = "Required value duration must be greater than 0."
val DURATION_REQUIRED = "Required value is empty."
private val DURATION_INVALID = "Required value duration must be greater than 0."
private val DURATION_REQUIRED = "Required value is empty."

def validateRequired(durationOpt: Option[Int]): Option[ValidationMessage] = {
durationOpt match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ trait LanguageValidator {
}

def validate(fieldPath: String, languageCode: String, allowUnknownLanguage: Boolean): Option[ValidationMessage] = {
languageCode.nonEmpty && languageCodeSupported6391(languageCode, allowUnknownLanguage) match {
case true => None
case false =>
Some(ValidationMessage(fieldPath, s"Language '$languageCode' is not a supported value."))
if (languageCode.nonEmpty && languageCodeSupported6391(languageCode, allowUnknownLanguage)) {
None
} else {
Some(ValidationMessage(fieldPath, s"Language '$languageCode' is not a supported value."))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ trait LearningPathValidator {

class LearningPathValidator(descriptionRequired: Boolean = true) {

val MISSING_DESCRIPTION = "At least one description is required."
private val MISSING_DESCRIPTION = "At least one description is required."

val INVALID_COVER_PHOTO =
private val INVALID_COVER_PHOTO =
"The url to the coverPhoto must point to an image in NDLA Image API."

val noHtmlTextValidator = new TextValidator(allowHtml = false)
val durationValidator = new DurationValidator
val noHtmlTextValidator = new TextValidator(allowHtml = false)
private val durationValidator = new DurationValidator

def validate(newLearningPath: LearningPath, allowUnknownLanguage: Boolean = false): Unit = {
validateLearningPath(newLearningPath, allowUnknownLanguage) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import no.ndla.common.model.domain.learningpath.{Description, EmbedUrl, Learning
import scala.util.{Failure, Success, Try}

trait LearningStepValidator {
this: TitleValidator with LanguageValidator with TextValidator with UrlValidator =>
this: TitleValidator & LanguageValidator & TextValidator & UrlValidator =>
val learningStepValidator: LearningStepValidator

class LearningStepValidator {
val noHtmlTextValidator = new TextValidator(allowHtml = false)
val basicHtmlTextValidator = new TextValidator(allowHtml = true)
val urlValidator = new UrlValidator()
val noHtmlTextValidator = new TextValidator(allowHtml = false)
private val basicHtmlTextValidator = new TextValidator(allowHtml = true)
private val urlValidator = new UrlValidator()

val MISSING_DESCRIPTION_OR_EMBED_URL =
private val MISSING_DESCRIPTION_OR_EMBED_URL =
"A learningstep is required to have either a description, embedUrl or both."

def validate(newLearningStep: LearningStep, allowUnknownLanguage: Boolean = false): Try[LearningStep] = {
Expand All @@ -41,21 +41,21 @@ trait LearningStepValidator {
}

def validateDescription(descriptions: Seq[Description], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = {
descriptions.isEmpty match {
case true => List()
case false =>
descriptions.flatMap(description => {
basicHtmlTextValidator
.validate("description", description.description)
.toList :::
languageValidator
.validate("language", description.language, allowUnknownLanguage)
.toList
})
if (descriptions.isEmpty) {
List()
} else {
descriptions.flatMap(description => {
basicHtmlTextValidator
.validate("description", description.description)
.toList :::
languageValidator
.validate("language", description.language, allowUnknownLanguage)
.toList
})
}
}

def validateEmbedUrl(embedUrls: Seq[EmbedUrl], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = {
private def validateEmbedUrl(embedUrls: Seq[EmbedUrl], allowUnknownLanguage: Boolean): Seq[ValidationMessage] = {
embedUrls.flatMap(embedUrl => {
urlValidator.validate("embedUrl.url", embedUrl.url).toList :::
languageValidator
Expand All @@ -67,17 +67,18 @@ trait LearningStepValidator {
def validateLicense(licenseOpt: Option[String]): Option[ValidationMessage] = {
licenseOpt match {
case None => None
case Some(license) => {
case Some(license) =>
noHtmlTextValidator.validate("license", license)
}
}
}

def validateThatDescriptionOrEmbedUrlOrBothIsDefined(newLearningStep: LearningStep): Option[ValidationMessage] = {
newLearningStep.description.isEmpty && newLearningStep.embedUrl.isEmpty match {
case true =>
Some(ValidationMessage("description|embedUrl", MISSING_DESCRIPTION_OR_EMBED_URL))
case false => None
private def validateThatDescriptionOrEmbedUrlOrBothIsDefined(
newLearningStep: LearningStep
): Option[ValidationMessage] = {
if (newLearningStep.description.isEmpty && newLearningStep.embedUrl.isEmpty) {
Some(ValidationMessage("description|embedUrl", MISSING_DESCRIPTION_OR_EMBED_URL))
} else {
None
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ import no.ndla.common.model.domain.learningpath.{LearningPathStatus, StepStatus}
class StatusValidator {

def validateLearningStepStatus(status: String): Option[ValidationMessage] = {
StepStatus.valueOf(status).isEmpty match {
case true =>
Some(ValidationMessage("status", s"'$status' is not a valid status."))
case false => None
if (StepStatus.valueOf(status).isEmpty) {
Some(ValidationMessage("status", s"'$status' is not a valid status."))
} else {
None
}
}

def validateLearningPathStatus(status: String): Option[ValidationMessage] = {
LearningPathStatus.valueOf(status).isEmpty match {
case true =>
Some(ValidationMessage("status", s"'$status' is not a valid publishingstatus."))
case false => None
if (LearningPathStatus.valueOf(status).isEmpty) {
Some(ValidationMessage("status", s"'$status' is not a valid publishingstatus."))
} else {
None
}
}
}
Loading

0 comments on commit f1808a9

Please sign in to comment.