diff options
| -rw-r--r-- | src/main/scala/reading/Books.scala | 71 | ||||
| -rw-r--r-- | src/main/scala/reading/component/index/Books.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/reading/component/index/FiltersMenu.scala | 111 | ||||
| -rw-r--r-- | src/main/scala/reading/component/index/style/Books.scala | 5 | ||||
| -rw-r--r-- | src/main/scala/reading/models/Book.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/reading/models/Difficulty.scala | 6 | ||||
| -rw-r--r-- | src/main/scala/reading/models/Filter.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/reading/models/Level.scala | 33 | ||||
| -rw-r--r-- | src/main/scala/reading/models/Program.scala | 70 | 
9 files changed, 250 insertions, 61 deletions
| diff --git a/src/main/scala/reading/Books.scala b/src/main/scala/reading/Books.scala index 29c26d2..af23146 100644 --- a/src/main/scala/reading/Books.scala +++ b/src/main/scala/reading/Books.scala @@ -1,52 +1,61 @@  package reading -import reading.models.{Book, Period, Theme, Genre}, Period._, Theme._, Genre._ +import reading.models.{Book, Period, Theme, Genre, Program} +import Period._ +import Theme._ +import Genre._ +import Program._  object Books {    def apply(): Seq[Book] = Seq(      Book( -      title  = "Les Dix petits nègres", -      author = "Agatha Christie", -      period = Siecle20, -      genres = Seq(Policier), -      themes = Seq(Peur), -      pages  = 250 +      title   = "Les Dix petits nègres", +      author  = "Agatha Christie", +      period  = Siecle20, +      genres  = Seq(Policier), +      themes  = Seq(Peur), +      program = Monstre, +      pages   = 250      ),      Book( -      title  = "Le Joueur", -      author = "Fiódor Dostoyevski", -      period = Siecle19, -      genres = Seq(), -      themes = Seq(Peur), -      pages  = 170 +      title   = "Le Joueur", +      author  = "Fiódor Dostoyevski", +      period  = Siecle19, +      genres  = Seq(), +      themes  = Seq(Peur), +      program = Heros, +      pages   = 170      ),      Book( -      title  = "Voyage au bout de la nuit", -      author = "Céline", -      period = Siecle20, -      genres = Seq(), -      themes = Seq(Peur), -      pages  = 380 +      title   = "Voyage au bout de la nuit", +      author  = "Céline", +      period  = Siecle20, +      genres  = Seq(), +      themes  = Seq(Peur), +      program = IndividuEtSociete, +      pages   = 380      ),      Book( -      title  = "Le Petit Prince", -      author = "Antoine de Saint Exupéry", -      period = Siecle19, -      genres = Seq(Policier), -      themes = Seq(Amitie), -      pages  = 130 +      title   = "Le Petit Prince", +      author  = "Antoine de Saint Exupéry", +      period  = Siecle19, +      genres  = Seq(Policier), +      themes  = Seq(Amitie), +      program = RecitAventure, +      pages   = 130      ),      Book( -      title  = "Les Frères Karamazov", -      author = "Fiódor Dostoyevski", -      period = Siecle19, -      genres = Seq(), -      themes = Seq(Famille), -      pages  = 850 +      title   = "Les Frères Karamazov", +      author  = "Fiódor Dostoyevski", +      period  = Siecle19, +      genres  = Seq(), +      themes  = Seq(Famille), +      program = Autrui, +      pages   = 850      )    )  } diff --git a/src/main/scala/reading/component/index/Books.scala b/src/main/scala/reading/component/index/Books.scala index 39c0e67..dacfe4e 100644 --- a/src/main/scala/reading/component/index/Books.scala +++ b/src/main/scala/reading/component/index/Books.scala @@ -36,6 +36,10 @@ object Books {                  s"thème: ${book.themes.mkString(", ")}"                ),                div( +                BooksStyle.program, +                s"programme: ${book.program}" +              ), +              div(                  BooksStyle.pages,                  s"${book.pages} pages"                ) diff --git a/src/main/scala/reading/component/index/FiltersMenu.scala b/src/main/scala/reading/component/index/FiltersMenu.scala index 81220e3..02f591b 100644 --- a/src/main/scala/reading/component/index/FiltersMenu.scala +++ b/src/main/scala/reading/component/index/FiltersMenu.scala @@ -8,21 +8,31 @@ import scalacss.Defaults._  import scalacss.ScalatagsCss._  import reading.component.index.style.{FiltersMenu => FiltersMenuStyle} -import reading.models.{Book, Filter, Period, Genre, Theme, Difficulty} +import reading.models.{Book, Filter, Period, Genre, Theme, Program, Difficulty, FilterFactory}  import reading.utils.{RxTag, RxAttr}  object FiltersMenu {    def apply(books: Rx[Seq[Book]], filters: Var[Seq[Filter]]): Frag = -    div( -      FiltersMenuStyle.render, -      FiltersMenuStyle.groups, -      group(books, filters, "Période", Period.values.map(Filter.apply(_))), -      group(books, filters, "Genre", Genre.values.map(Filter.apply(_))), -      group(books, filters, "Theme", Theme.values.map(Filter.apply(_))), -      group(books, filters, "Difficulté", Difficulty.filters) -    ) +    RxTag { implicit context => +      div( +        FiltersMenuStyle.render, +        FiltersMenuStyle.groups, +        group(books, filters, "Période", Period.values.map(Filter.apply(_))), +        group(books, filters, "Genre", Genre.values.map(Filter.apply(_))), +        group(books, filters, "Theme", Theme.values.map(Filter.apply(_))), +        multiGroup(books, filters, "Programme", Program.values, Program.level _), +        group(books, filters, "Difficulté", Difficulty.filters) +      ) +    } -  def group(books: Rx[Seq[Book]], filters: Var[Seq[Filter]], name: String, groupFilters: Seq[Filter]): Frag = { +  def group( +    books: Rx[Seq[Book]], +    filters: Var[Seq[Filter]], +    name: String, +    groupFilters: Seq[Filter] +  )( +    implicit context: Ctx.Data +  ): Frag = {      val filtersWithCount = Rx {        groupFilters          .filter(filter => !Filter.contains(filters(), filter)) @@ -30,25 +40,72 @@ object FiltersMenu {          .filter(_._2 > 0)      } -    RxTag { implicit context => -      if(filtersWithCount().isEmpty) -        span("") -      else +    if(filtersWithCount().isEmpty) +      span("") +    else +      div( +        FiltersMenuStyle.group, +        div(FiltersMenuStyle.groupTitle, name),          div( -          FiltersMenuStyle.group, - -          div(FiltersMenuStyle.groupTitle, name), - -          div( -            filtersWithCount().map { case (filter, count) => -              button( -                FiltersMenuStyle.filter, -                RxAttr(onclick, Rx(() => filters() = filter +: filters())), -                span(s"${filter.name} ($count)") -              ) -            } -          ) +          filtersWithCount().map { case (filter, count) => +            button( +              FiltersMenuStyle.filter, +              RxAttr(onclick, Rx(() => filters() = filter +: filters())), +              span(s"${filter.name} ($count)") +            ) +          } +        ) +      ) +  } + + + +  def multiGroup[A: FilterFactory, B: Ordering]( +    books: Rx[Seq[Book]], +    filters: Var[Seq[Filter]], +    name: String, +    groupFilters: Seq[A], +    superGroup: A => B +  )( +    implicit context: Ctx.Data +  ): Frag = +    div( +      FiltersMenuStyle.group, +      div(FiltersMenuStyle.groupTitle, name), +      groupFilters.groupBy(superGroup).toList.sortBy(_._1).map { case (superGroup, subGroupFilters) => +        div( +          superGroup.toString, +          subGroup(books, filters, name, subGroupFilters.map(Filter(_)))          ) +      } +    ) + +  def subGroup( +    books: Rx[Seq[Book]], +    filters: Var[Seq[Filter]], +    name: String, +    groupFilters: Seq[Filter] +  )( +    implicit context: Ctx.Data +  ): Frag = { +    val filtersWithCount = Rx { +      groupFilters +        .filter(filter => !Filter.contains(filters(), filter)) +        .map(filter => (filter, Book.filter(books(), filter +: filters()).length)) +        .filter(_._2 > 0)      } + +    if(filtersWithCount().isEmpty) +      span("") +    else +      div( +        filtersWithCount().map { case (filter, count) => +          button( +            FiltersMenuStyle.filter, +            RxAttr(onclick, Rx(() => filters() = filter +: filters())), +            span(s"${filter.name} ($count)") +          ) +        } +      )    }  } diff --git a/src/main/scala/reading/component/index/style/Books.scala b/src/main/scala/reading/component/index/style/Books.scala index c023e66..69e1c55 100644 --- a/src/main/scala/reading/component/index/style/Books.scala +++ b/src/main/scala/reading/component/index/style/Books.scala @@ -41,6 +41,11 @@ object Books extends StyleSheet.Inline {      marginBottom(10.px)    ) +  val program = style( +    marginLeft(20.px), +    marginBottom(10.px) +  ) +    val pages = style(      marginLeft(20.px)    ) diff --git a/src/main/scala/reading/models/Book.scala b/src/main/scala/reading/models/Book.scala index 7c4bf8a..ef9eb9b 100644 --- a/src/main/scala/reading/models/Book.scala +++ b/src/main/scala/reading/models/Book.scala @@ -6,6 +6,7 @@ case class Book (    period: Period,    genres: Seq[Genre],    themes: Seq[Theme], +  program: Program,    pages: Int  ) extends Ordered[Book] {    def compare(that: Book) = { diff --git a/src/main/scala/reading/models/Difficulty.scala b/src/main/scala/reading/models/Difficulty.scala index aade5f5..e20d7b2 100644 --- a/src/main/scala/reading/models/Difficulty.scala +++ b/src/main/scala/reading/models/Difficulty.scala @@ -6,17 +6,17 @@ object Difficulty {        new Filter {          def filter(book: Book): Boolean = book.pages < 200          val kind: FilterKind = DifficultyKind -        def name: String = "facile" +        val name: String = "facile"        },        new Filter {          def filter(book: Book): Boolean = book.pages >= 200 && book.pages < 400          val kind: FilterKind = DifficultyKind -        def name: String = "moyen" +        val name: String = "moyen"        },        new Filter {          def filter(book: Book): Boolean = book.pages > 400          val kind: FilterKind = DifficultyKind -        def name: String = "difficile" +        val name: String = "difficile"        }      )  } diff --git a/src/main/scala/reading/models/Filter.scala b/src/main/scala/reading/models/Filter.scala index 5e96cf9..a74a6f1 100644 --- a/src/main/scala/reading/models/Filter.scala +++ b/src/main/scala/reading/models/Filter.scala @@ -11,6 +11,7 @@ case object PeriodKind extends FilterKind  case object ThemeKind extends FilterKind  case object GenreKind extends FilterKind  case object DifficultyKind extends FilterKind +case object ProgramKind extends FilterKind  object Filter {    def apply[T](in: T)(implicit filterFactory: FilterFactory[T]): Filter = @@ -54,4 +55,13 @@ object FilterFactory {          val name: String = genre.toString()        }    } + +  implicit object ProgramFilter extends FilterFactory[Program] { +    def create(program: Program): Filter = +      new Filter { +        def filter(book: Book): Boolean = book.program == program +        val kind: FilterKind = ProgramKind +        val name: String = program.toString() +      } +  }  } diff --git a/src/main/scala/reading/models/Level.scala b/src/main/scala/reading/models/Level.scala new file mode 100644 index 0000000..1f7e153 --- /dev/null +++ b/src/main/scala/reading/models/Level.scala @@ -0,0 +1,33 @@ +package reading.models + +import enumeratum._ + +sealed trait Level extends EnumEntry with Ordered[Level] { +  import Level._ + +  def compare(that: Level) = { +    def toInt(level: Level): Int = level match { +      case Sixieme => 6 +      case Cinquieme => 5 +      case Quatrieme => 4 +      case Troisieme => 3 +    } +    toInt(that) - toInt(this) +  } + +  override def toString(): String = this match { +    case Sixieme  => "6ème" +    case Cinquieme  => "5ème" +    case Quatrieme  => "4ème" +    case Troisieme  => "3ème" +  } +} + +object Level extends Enum[Level] { +  val values = findValues + +  case object Sixieme extends Level +  case object Cinquieme extends Level +  case object Quatrieme extends Level +  case object Troisieme extends Level +} diff --git a/src/main/scala/reading/models/Program.scala b/src/main/scala/reading/models/Program.scala new file mode 100644 index 0000000..4603b03 --- /dev/null +++ b/src/main/scala/reading/models/Program.scala @@ -0,0 +1,70 @@ +package reading.models + +import enumeratum._ + +sealed trait Program extends EnumEntry { +  import Program._ + +  override def toString(): String = this match { +    case Monstre  => "Le monstre, aux limites de l'humain" +    case RecitAventure  => "Récits d'aventures" +    case CreationPoetique  => "Récit de création, création poétique" +    case Resister  => "Résister au plus fort : ruses, mensonges et masques" + +    case VoyageEtAventure  => "le voyage et l'aventure. Pourquoi aller vers l'inconnu ?" +    case Autrui  => "avec autrui : familles, amis, réseaux." +    case UniversNouveaux  => "imaginer des univers nouveaux." +    case Heros  => "héros, héroïnes et héroïsmes." +    case HommeEtNature  => "l'être humain est-il maître de la nature ?" + +    case DireAmour  => "Dire l'amour" +    case IndividuEtSociete  => "Individu et société : confrontations de valeur ?" +    case FictionEtReel  => "la fiction pour interroger le réel" +    case Informer  => "Informer, s'informer, déformer ?" +    case Ville  => "La ville, lieu de tous les possibles ?" + +    case RaconterRepresenter  => "Se raconter, se représenter" +    case TraversSociete  => "Dénoncer les travers de la société" +    case VisionsPoetiques  => "Visions poétiques du monde" +    case AgirCite  => "Agir dans la cité : individu et pouvoir" +    case ProgresReveScientifique  => "Progrès et rêves scientifiques" +  } +} + +object Program extends Enum[Program] { +  val values = findValues + +  case object Monstre extends Program +  case object RecitAventure extends Program +  case object CreationPoetique extends Program +  case object Resister extends Program + +  case object VoyageEtAventure extends Program +  case object Autrui extends Program +  case object UniversNouveaux extends Program +  case object Heros extends Program +  case object HommeEtNature extends Program + +  case object DireAmour extends Program +  case object IndividuEtSociete extends Program +  case object FictionEtReel extends Program +  case object Informer extends Program +  case object Ville extends Program + +  case object RaconterRepresenter extends Program +  case object TraversSociete extends Program +  case object VisionsPoetiques extends Program +  case object AgirCite extends Program +  case object ProgresReveScientifique extends Program + +  def level(program: Program): Level = { +    import Level._ + +    program match { +      case Monstre | RecitAventure | CreationPoetique | Resister => Sixieme +      case VoyageEtAventure | Autrui | UniversNouveaux | Heros | HommeEtNature => Cinquieme +      case DireAmour | IndividuEtSociete | FictionEtReel | Informer | Ville => Quatrieme +      case RaconterRepresenter | TraversSociete | VisionsPoetiques | AgirCite | ProgresReveScientifique => Troisieme +    } +  } +} | 
