aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/component
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/reading/component')
-rw-r--r--src/main/scala/reading/component/Index.scala4
-rw-r--r--src/main/scala/reading/component/index/BookDetail.scala84
-rw-r--r--src/main/scala/reading/component/index/Books.scala10
-rw-r--r--src/main/scala/reading/component/index/FilterUtils.scala15
-rw-r--r--src/main/scala/reading/component/index/Filters.scala6
-rw-r--r--src/main/scala/reading/component/index/Header.scala2
-rw-r--r--src/main/scala/reading/component/index/Menu.scala18
-rw-r--r--src/main/scala/reading/component/index/style/BookDetail.scala9
-rw-r--r--src/main/scala/reading/component/index/style/Books.scala3
-rw-r--r--src/main/scala/reading/component/index/style/Header.scala3
10 files changed, 109 insertions, 45 deletions
diff --git a/src/main/scala/reading/component/Index.scala b/src/main/scala/reading/component/Index.scala
index 0105150..d6d1b6f 100644
--- a/src/main/scala/reading/component/Index.scala
+++ b/src/main/scala/reading/component/Index.scala
@@ -10,8 +10,8 @@ import reading.component.style.{ Index => IndexStyle }
import reading.models.{ Book, Books, Filter }
object Index {
- def apply(initialFilters: Seq[Filter], initialDetail: Option[Book])(implicit ctx: Ctx.Owner): Frag = {
- val filters: Var[Seq[Filter]] = Var(initialFilters)
+ def apply(initialFilters: Set[Filter], initialDetail: Option[Book])(implicit ctx: Ctx.Owner): Frag = {
+ val filters: Var[Set[Filter]] = Var(initialFilters)
val books: Rx[Seq[Book]] = Rx(Filter.add(Books(), filters()))
val search: Var[String] = Var("")
val showFiltersMenu: Var[Boolean] = Var(false)
diff --git a/src/main/scala/reading/component/index/BookDetail.scala b/src/main/scala/reading/component/index/BookDetail.scala
index f532c02..e97a154 100644
--- a/src/main/scala/reading/component/index/BookDetail.scala
+++ b/src/main/scala/reading/component/index/BookDetail.scala
@@ -1,27 +1,32 @@
package reading.component.index
-import scala.util.Random
-
+import rx._
import scalacss.Defaults._
import scalacss.ScalatagsCss._
import scalatags.JsDom.all._
import reading.component.index.style.{ BookDetail => BookStyle }
import reading.component.widget.AnimateMethod
-import reading.models.{ Book, Program, Filter }
+import reading.models.{ Filter, Book, Program, Grade, Theme, GroupedTheme }
import reading.Route
+import reading.utils.RxUtils._
object BookDetail {
- val componentId = s"books${Random.nextInt}"
+ val componentId = s"books-detail"
def apply(
- filters: Seq[Filter],
+ filters: Var[Set[Filter]],
+ detail: Var[Option[Book]],
+ search: Var[String],
book: Book,
parentId: String,
onClose: => Unit
+ )(
+ implicit
+ ctx: Ctx.Owner
): Frag = {
val titleParts = if (book.parts > 1) s", ${book.parts} volumes" else ""
- val grades = book.programs.map(Program.grade(_)).distinct.sorted
+ val grades = book.programs.map(Grade.from(_)).distinct.sorted
AnimateMethod.fadeIn(componentId)
@@ -55,23 +60,33 @@ object BookDetail {
BookStyle.definitions,
grades.map { grade =>
- val programs = book.programs.filter(p => Program.grade(p) == grade).sorted
+ val programs = book.programs.filter(p => Grade.from(p) == grade).sorted
val pp = grade.prettyPrint
- definition(pp, pp, programs.map(p => s"« ${p.prettyPrint} »"))
+ val programFilters = programs.map { program =>
+ (Filter(program), filters.map(addProgram(_, program)))
+ }
+ definition(filters, detail, search, pp, pp, programFilters, p => s"« $p »")
},
if (book.themes.nonEmpty) {
- definition("thème", "thèmes", book.themes.sorted.map(_.prettyPrint))
+ val themeFilters = book.themes.sorted.map { theme =>
+ (Filter(theme), filters.map(addTheme(_, theme)))
+ }
+ definition(filters, detail, search, "thème", "thèmes", themeFilters)
},
if (book.genres.nonEmpty) {
- definition("genre", "genres", book.genres.sorted.map(_.prettyPrint))
+ val bookFilters = book.genres.sorted.map(Filter(_)).map(b => (b, filters.map(_ + b)))
+ definition(filters, detail, search, "genre", "genres", bookFilters)
},
- definition("niveau", "niveaux", Seq(book.level.prettyPrint))
+ {
+ val levelFilters = Seq(Filter(book.level)).map(b => (b, filters.map(_ + b)))
+ definition(filters, detail, search, "niveau", "niveaux", levelFilters)
+ }
),
a(
BookStyle.close,
onclick := (() => onClose),
- href := Route.url(Route.Books(filters)),
+ href := Rx(Route.url(Route.Books(filters()))),
"Fermer"
)
)
@@ -79,11 +94,48 @@ object BookDetail {
)
}
- private def definition(key: String, pluralKey: String, values: Seq[String]): Seq[Frag] = {
- val term = if (values.length > 1) pluralKey else key
+ private def definition(
+ filters: Var[Set[Filter]],
+ detail: Var[Option[Book]],
+ search: Var[String],
+ term: String,
+ pluralTerm: String,
+ definitionFilters: Seq[(Filter, Rx[Set[Filter]])],
+ format: String => String = _.capitalize
+ )(
+ implicit
+ ctx: Ctx.Owner
+ ): Seq[Frag] = {
+ val sTerm = if (definitionFilters.length > 1) pluralTerm else term
+
Seq(
- dt(BookStyle.definitionTerm, s"${term.capitalize} :"),
- dd(BookStyle.definitionDescription, values.mkString(", "))
+ dt(BookStyle.definitionTerm, s"${sTerm.capitalize} :"),
+ dd(
+ BookStyle.definitionDescription,
+ definitionFilters.map {
+ case (filter, newFilters) =>
+ a(
+ BookStyle.definitionFilter,
+ href := Rx(Route.url(Route.Books(newFilters()))),
+ onclick := (() => FilterUtils.set(filters, detail, search, newFilters.now)),
+ format(filter.name)
+ )
+ }
+ )
)
}
+
+ private def addProgram(filters: Set[Filter], program: Program): Set[Filter] = {
+ val grade = Grade.from(program)
+ val otherGrades = Grade.values.filter(_ != grade).map(Filter(_))
+ val otherPrograms = Program.values.filter(Grade.from(_) != grade).map(Filter(_))
+ filters -- otherGrades -- otherPrograms + Filter(grade) + Filter(program)
+ }
+
+ private def addTheme(filters: Set[Filter], theme: Theme): Set[Filter] = {
+ val groupedTheme = GroupedTheme.from(theme)
+ val otherGroupedThemes = GroupedTheme.values.filter(_ != groupedTheme).map(Filter(_))
+ val otherThemes = Theme.values.filter(GroupedTheme.from(_) != groupedTheme).map(Filter(_))
+ filters -- otherGroupedThemes -- otherThemes + Filter(groupedTheme) + Filter(theme)
+ }
}
diff --git a/src/main/scala/reading/component/index/Books.scala b/src/main/scala/reading/component/index/Books.scala
index f15e2dc..14aac51 100644
--- a/src/main/scala/reading/component/index/Books.scala
+++ b/src/main/scala/reading/component/index/Books.scala
@@ -18,7 +18,7 @@ object Books {
def apply(
books: Rx[Seq[Book]],
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
showFiltersMenu: Var[Boolean]
@@ -75,7 +75,10 @@ object Books {
Rx {
detail() match {
case Some(book) =>
- BookDetail(filters.now, book, componentId, onClose = closeDetail(filters, detail))
+ BookDetail(filters, detail, search, book, componentId, onClose = {
+ closeDetail(filters, detail)
+ Route.push(Route.Books(filters.now, None))
+ })
case None =>
span("")
}
@@ -83,10 +86,9 @@ object Books {
)
}
- def closeDetail(filters: Var[Seq[Filter]], detail: Var[Option[Book]]): Unit =
+ def closeDetail(filters: Var[Set[Filter]], detail: Var[Option[Book]]): Unit =
AnimateMethod.fadeOut(BookDetail.componentId, onEnd = {
detail() = None
- Route.push(Route.Books(filters.now, None))
AnimateMethod.fadeIn(componentId)
})
}
diff --git a/src/main/scala/reading/component/index/FilterUtils.scala b/src/main/scala/reading/component/index/FilterUtils.scala
index 89f993a..c019513 100644
--- a/src/main/scala/reading/component/index/FilterUtils.scala
+++ b/src/main/scala/reading/component/index/FilterUtils.scala
@@ -7,7 +7,7 @@ import reading.Route
object FilterUtils {
def remove(
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
filter: Filter
@@ -20,23 +20,22 @@ object FilterUtils {
}
def removeAll(
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String]
): Unit = {
- filters() = Nil
+ filters() = Set()
if (detail.now.nonEmpty) Books.closeDetail(filters, detail)
search() = ""
- Route.push(Route.Books(Nil))
+ Route.push(Route.Books())
}
- def add(
- filters: Var[Seq[Filter]],
+ def set(
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
- filter: Filter
+ newFilters: Set[Filter]
): Unit = {
- val newFilters = filter +: filters.now
filters() = newFilters
if (detail.now.nonEmpty) Books.closeDetail(filters, detail)
search() = ""
diff --git a/src/main/scala/reading/component/index/Filters.scala b/src/main/scala/reading/component/index/Filters.scala
index 935e501..c300190 100644
--- a/src/main/scala/reading/component/index/Filters.scala
+++ b/src/main/scala/reading/component/index/Filters.scala
@@ -15,7 +15,7 @@ import reading.utils.RxUtils._
object Filters {
def apply(
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
showFiltersMenu: Var[Boolean]
@@ -23,7 +23,7 @@ object Filters {
implicit
ctx: Ctx.Owner
): Frag = {
- val filtersCount: Rx[Int] = Rx(filters().length)
+ val filtersCount: Rx[Int] = Rx(filters().size)
div(
FiltersStyle.render,
@@ -51,7 +51,7 @@ object Filters {
"Effacer les filtres"
),
- filters().sortBy(_.name).map { filter =>
+ filters().toSeq.sortBy(_.name).map { filter =>
a(
FiltersStyle.filter,
onclick := (() => FilterUtils.remove(filters, detail, search, filter)),
diff --git a/src/main/scala/reading/component/index/Header.scala b/src/main/scala/reading/component/index/Header.scala
index 0809b0c..2d9504e 100644
--- a/src/main/scala/reading/component/index/Header.scala
+++ b/src/main/scala/reading/component/index/Header.scala
@@ -13,7 +13,7 @@ import reading.utils.RxUtils._
object Header {
def apply(
books: Rx[Seq[Book]],
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
showFiltersMenu: Var[Boolean]
diff --git a/src/main/scala/reading/component/index/Menu.scala b/src/main/scala/reading/component/index/Menu.scala
index 0ea6ca4..ec6c21f 100644
--- a/src/main/scala/reading/component/index/Menu.scala
+++ b/src/main/scala/reading/component/index/Menu.scala
@@ -14,7 +14,7 @@ import reading.utils.RxUtils._
object Menu {
def apply(
books: Rx[Seq[Book]],
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
showFiltersMenu: Var[Boolean]
@@ -27,14 +27,14 @@ object Menu {
Rx(if (showFiltersMenu()) MenuStyle.show else MenuStyle.empty),
MenuStyle.menu,
- Rx(header(showFiltersMenu, filters().length)),
+ Rx(header(showFiltersMenu, filters().size)),
div(
MenuStyle.groups,
Rx {
filters().find(_.kind == FilterKind.Grade) match {
case Some(grade) =>
- val programs = Program.values.filter(p => Program.grade(p).toString() == grade.nonFormattedName).sorted
+ val programs = Program.values.filter(p => Grade.from(p).toString() == grade.nonFormattedName).sorted
group(books, filters, detail, search, grade.name, grade.name, programs.map(Filter.apply(_)), Some(grade))
case None =>
group(books, filters, detail, search, "classe", "classes", Grade.values.sorted.map(Filter.apply(_)))
@@ -43,7 +43,7 @@ object Menu {
Rx {
filters().find(_.kind == FilterKind.GroupedTheme) match {
case Some(groupedTheme) =>
- val themes = Theme.values.filter(t => Theme.grouped(t).toString() == groupedTheme.nonFormattedName).sorted
+ val themes = Theme.values.filter(t => GroupedTheme.from(t).toString() == groupedTheme.nonFormattedName).sorted
group(books, filters, detail, search, groupedTheme.name, groupedTheme.name, themes.map(Filter.apply(_)), Some(groupedTheme))
case None =>
group(books, filters, detail, search, "thème", "thèmes", GroupedTheme.values.sorted.map(Filter.apply(_)))
@@ -66,7 +66,7 @@ object Menu {
def group(
books: Rx[Seq[Book]],
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
name: String,
@@ -100,7 +100,7 @@ object Menu {
if (parentFilter.isDefined) MenuStyle.activeFilter else "",
if (filtersCount() > 1) pluralName else name,
Rx {
- val count = filters().filter(f => groupFilters.exists(f == _)).length
+ val count = filters().filter(f => groupFilters.exists(f == _)).size
if (count > 0) span(MenuStyle.filterTitleCount, count) else span("")
}
),
@@ -109,7 +109,7 @@ object Menu {
case (filter, count) => {
val isActive = Filter.contains(filters(), filter)
val route = Route.Books(
- filters = if (isActive) Filter.remove(filters(), filter) else filter +: filters()
+ filters = if (isActive) Filter.remove(filters(), filter) else filters() + filter
)
a(
@@ -120,7 +120,7 @@ object Menu {
if (isActive)
FilterUtils.remove(filters, detail, search, filter)
else
- FilterUtils.add(filters, detail, search, filter)),
+ FilterUtils.set(filters, detail, search, filters.now + filter)),
span(
span(filter.name.capitalize),
span(MenuStyle.filterCount, count)
@@ -135,7 +135,7 @@ object Menu {
def footer(
books: Rx[Seq[Book]],
- filters: Var[Seq[Filter]],
+ filters: Var[Set[Filter]],
detail: Var[Option[Book]],
search: Var[String],
showFiltersMenu: Var[Boolean]
diff --git a/src/main/scala/reading/component/index/style/BookDetail.scala b/src/main/scala/reading/component/index/style/BookDetail.scala
index 2ce0632..eaad862 100644
--- a/src/main/scala/reading/component/index/style/BookDetail.scala
+++ b/src/main/scala/reading/component/index/style/BookDetail.scala
@@ -71,6 +71,15 @@ object BookDetail extends StyleSheet.Inline {
lineHeight(1.4.em)
)
+ val definitionFilter = style(
+ &.hover(color(C.stiletto.value)),
+ &.not(_.lastChild).after(
+ content := "\",\"",
+ marginRight(5.px),
+ &.hover(color(C.black.value))
+ )
+ )
+
val close = style(
Button.simple,
marginBottom(1.em)
diff --git a/src/main/scala/reading/component/index/style/Books.scala b/src/main/scala/reading/component/index/style/Books.scala
index a1f0374..808b937 100644
--- a/src/main/scala/reading/component/index/style/Books.scala
+++ b/src/main/scala/reading/component/index/style/Books.scala
@@ -21,7 +21,8 @@ object Books extends StyleSheet.Inline {
)
val listParent = style(
- overflowY.scroll
+ overflowY.scroll,
+ paddingTop(15.px)
)
val list = style(
diff --git a/src/main/scala/reading/component/index/style/Header.scala b/src/main/scala/reading/component/index/style/Header.scala
index 10ce059..a871e9c 100644
--- a/src/main/scala/reading/component/index/style/Header.scala
+++ b/src/main/scala/reading/component/index/style/Header.scala
@@ -9,7 +9,8 @@ object Header extends StyleSheet.Inline {
import dsl._
val header = style(
- margin(30.px, 0.px)
+ marginTop(30.px),
+ marginBottom(20.px)
)
val searchAndCount = style(