Skip to content

Commit

Permalink
Books page design changes according to Figma (ocaml#1536)
Browse files Browse the repository at this point in the history
  • Loading branch information
SaySayo committed Oct 11, 2023
1 parent d36f5c1 commit 9c2abab
Show file tree
Hide file tree
Showing 20 changed files with 118 additions and 46 deletions.
1 change: 1 addition & 0 deletions data/books/apprendre-a-programmer-avec-ocaml.md
Expand Up @@ -21,6 +21,7 @@ links:
uri: https://www.amazon.fr/Apprendre-programmer-avec-Ocaml-Algorithmes/dp/2212136781/
featured: false
difficulty: beginner
pricing: paid
---

Computer programming is hard to learn. Being a skillful programmer
Expand Down
1 change: 1 addition & 0 deletions data/books/apprentissage-de-la-programmation-avec-ocaml.md
Expand Up @@ -19,6 +19,7 @@ links:
uri: https://www.amazon.com/apprentissage-programmation-avec-ocaml/dp/2746208199
featured: false
difficulty: beginner
pricing: paid
---

Programming is a discipline by which the strengths of computers can be
Expand Down
Expand Up @@ -18,6 +18,7 @@ links:
uri: https://www.amazon.fr/exec/obidos/ASIN/2841771210
featured: false
difficulty: intermediate
pricing: free
---

A comprehensive (742 pages) book on OCaml, covering not only the core
Expand Down
Expand Up @@ -15,6 +15,7 @@ links:
uri: https://www.edilivre.com/initiation-a-la-programmation-fonctionnelle-en-ocaml-mohammed-said-habet.html
featured: false
difficulty: beginner
pricing: paid
---

La programmation fonctionnelle est un style de programmation qui
Expand Down
1 change: 1 addition & 0 deletions data/books/introduzione-alla-programmazione-funzionale.md
Expand Up @@ -15,4 +15,5 @@ links:
uri: https://www.amazon.it/Introduzione-programmazione-funzionale-Marta-Cialdea/dp/8874880316
featured: false
difficulty: beginner
pricing: paid
---
1 change: 1 addition & 0 deletions data/books/more-ocaml-algorithms-methods-diversions.md
Expand Up @@ -18,6 +18,7 @@ links:
rating: 5
featured: false
difficulty: intermediate
pricing: paid
---

In "More OCaml," John Whitington takes a meandering tour of functional
Expand Down
1 change: 1 addition & 0 deletions data/books/nyumon-ocaml.md
Expand Up @@ -12,4 +12,5 @@ links:
uri: https://www.amazon.co.jp/%E5%85%A5%E9%96%80OCaml-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%9F%BA%E7%A4%8E%E3%81%A8%E5%AE%9F%E8%B7%B5%E7%90%86%E8%A7%A3-OCaml-Nagoya/dp/4839923116
featured: false
difficulty: beginner
pricing: paid
---
1 change: 1 addition & 0 deletions data/books/ocaml-from-the-very-beginning.md
Expand Up @@ -19,6 +19,7 @@ links:
rating: 4
featured: true
difficulty : beginner
pricing: free
---

In *OCaml from the Very Beginning*, John Whitington takes a
Expand Down
Expand Up @@ -17,6 +17,7 @@ links:
rating: 5
featured: true
difficulty: beginner
pricing: free
---

A textbook on functional programming and data structures in OCaml, with an
Expand Down
1 change: 1 addition & 0 deletions data/books/ocaml-scientific-computing.md
Expand Up @@ -18,6 +18,7 @@ links:
uri: https://www.amazon.com/gp/product/3030976440
featured: true
difficulty: advanced
pricing: paid
---

This book is about the harmonious synthesis of functional programming and
Expand Down
1 change: 1 addition & 0 deletions data/books/ocaml-yuyan-biancheng-jichu-jiaocheng.md
Expand Up @@ -12,4 +12,5 @@ links:
uri: https://www.epubit.com/bookDetails?id=N18159
featured: false
difficulty: beginner
pricing: paid
---
3 changes: 2 additions & 1 deletion data/books/programmation-de-droite-a-gauche-et-vice-versa.md
Expand Up @@ -10,7 +10,8 @@ cover: books/programmation-de-droite-a-gauche-et-vice-versa.jpg
language: french
isbn: "978-2-916466-05-7"
links:
- description: Order Online from Paracamplus
- description: Order on Paracamplus
uri: https://www.decitre.fr/livres/programmation-de-droite-a-gauche-et-vice-versa-9782916466064.html
featured: false
pricing: paid
---
1 change: 1 addition & 0 deletions data/books/puroguramingu-in-ocaml.md
Expand Up @@ -11,4 +11,5 @@ links:
- description: Order at Amazon.co.jp
uri: https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-OCaml-%E3%80%9C%E9%96%A2%E6%95%B0%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89GUI%E6%A7%8B%E7%AF%89%E3%81%BE%E3%81%A7%E3%80%9C-%E4%BA%94%E5%8D%81%E5%B5%90%E6%B7%B3-ebook/dp/B00QRPI1AS
featured: false
pricing: paid
---
1 change: 1 addition & 0 deletions data/books/real-world-ocaml.md
Expand Up @@ -19,6 +19,7 @@ links:
rating: 4
featured: true
difficulty: intermediate
pricing: free
---

Learn how to solve day-to-day problems in data processing, numerical
Expand Down
Expand Up @@ -14,6 +14,7 @@ links:
uri: https://greenteapress.com/thinkocaml/thinkocaml.pdf
featured: false
difficulty : beginner
pricing: free
---

This book is a work in progress. It is an introductory programming
Expand Down
1 change: 1 addition & 0 deletions src/ocamlorg_data/data.mli
Expand Up @@ -41,6 +41,7 @@ module Book : sig
rating : int option;
featured : bool;
difficulty : string option;
pricing : string;
body_md : string;
body_html : string;
}
Expand Down
18 changes: 14 additions & 4 deletions src/ocamlorg_frontend/components/learn_components.eml
Expand Up @@ -5,7 +5,7 @@ let skill_tag difficulty class_ =
| Some "intermediate" ->
<div class="<%s class_ %> px-2 py-1 inline-block bg-[#040113] rounded-3xl border-2 border-[#040113] font-normal text-center text-white"> Intermediate </div>
| Some "advanced" ->
<div class="<%s class_ %> px-2 py-1 inline-block bg-primary-700 rounded-3xl border-2 border-primary-700 font-normal text-center text-white"> Advanced </div>
<div class="<%s class_ %> px-2 py-1 inline-block bg-learn-area-orange rounded-3xl border-2 border-learn-area-orange font-normal text-center text-white"> Advanced </div>
| None ->
<></>
| Some _ ->
Expand Down Expand Up @@ -98,7 +98,18 @@ let right_tutorial_block ~title ~heading ~description ~(tutorial_links: link lis
</div>
</div>

let book_tile books =
let pricing_tag =
<div class="absolute -mt-3 ml-3 w-16 h-16">
<div class="bg-learn-area-orange rotate-[-10deg] rounded-full w-16 h-16 flex items-center justify-center" style="filter: drop-shadow(-4px -2px 4px rgb(0 0 0 / 0.25));">
<div class="text-center text-white text-base font-bold leading-7 tracking-wide">
FREE
</div>
</div>
</div>

let book_tile
books
=
<div class="mt-2 flex flex-col flex-grow gap-12 lg:gap-6 md:flex-row xl:gap-12">
<% books |> List.rev |> List.iteri (fun index (item : Data.Book.t) -> if (index < 2) then ( %>
<div class="flex flex-col w-full gap-4 lg:w-60">
Expand Down Expand Up @@ -181,5 +192,4 @@ let lang_manual_banner =
<a href="<%s Url.manual %>" class="w-full md:w-auto mt-5 py-2 px-24 bg-default text-sm rounded-sm items-center text-center text-primary-700 sm:px-20 sm:text-md font-medium leading-7 md:text-lg">Take Me There</a>
</div>
<div class="min-w-[200px] min-h-[200px] overflow-hidden rounded-full bg-cover bg-center bg-no-repeat md:min-w-[240px] md:min-h-[240px]" style="background-image: url('../img/home/ocaml_camel.png')">
</div>
</div>

89 changes: 49 additions & 40 deletions src/ocamlorg_frontend/pages/books.eml
Expand Up @@ -2,63 +2,72 @@ let render_books books =
<div class="overflow-x-scroll lg:overflow-hidden mt-5">
<% books |> List.iter (fun (item : Data.Book.t) -> %>
<div
class="flex space-y-10 lg:space-y-0 lg:space-x-16 pb-10 lg:pb-20 border-b border-gray-200 mt-10 flex-col lg:flex-row">
class="flex space-y-10 pt-6 lg:space-y-0 lg:space-x-16 pb-10 mt-4 flex-col lg:flex-row">
<div class="flex flex-col gap-y-4">
<img src="<%s Ocamlorg_static.Media.url item.cover %>"
class="m-4 h-48 w-32 lg:w-64 lg:h-96 md:w-64 md:h-96 rounded-2xl border border-gray-200"
alt="">
<%s! Learn_components.skill_tag item.difficulty "mx-4 w-32 lg:w-64 md:w-64" %>
<div class="relative w-64 sm:w-72 lg:w-64 max-w-full space-y-5">
<%s! if item.pricing = "free" then Learn_components.pricing_tag else "" %>
<img src="<%s Ocamlorg_static.Media.url item.cover %>"
class="w-full border z-10"
alt="">
<%s! Learn_components.skill_tag item.difficulty "w-full" %>
</div>

</div>
<div class="flex-col flex-1">
<h4 class="font-bold mb-6"><%s item.title %></h4>
<div class="font-semibold text-base mb-6 uppercase"><%s item.authors |> String.concat ", " %></div>
<div class="prose prose-orange mb-6"><%s! item.body_html %></div>
<% item.links |> List.iter (fun (link : Data.Book.link) -> %>
<a class="btn btn-secondary" href="<%s link.uri %>">
<span><%s link.description %></span>
<%s! Icons.chevron_right "h-4 w-4" %>
</a>
<% ); %>
<h4 class="font-bold text-2xl mb-6"><%s item.title %></h4>
<div class="font-normal text-base mb-6 uppercase"><%s item.authors |> String.concat ", " %></div>
<div class="prose prose-md prose-orange mb-6 md:prose-lg"><%s! item.body_html %></div>
<div class="flex gap-x-5 gap-y-4 flex-col sm:flex-row">
<% item.links |> List.iter (fun (link : Data.Book.link) -> %>
<div>
<a class="btn bg-learn-area-orange" href="<%s link.uri %>">
<span><%s link.description %></span>
<%s! Icons.chevron_right "h-4 w-4" %>
</a>
</div>
<% ); %>
</div>
</div>
</div>
<% ); %>
</div>

let render books =

let render
?(difficulty = "All")
?(pricing = "All")
?(language = "All")
books =
Learn_layout.single_column_layout
~title:"OCaml Books"
~description:"A selection of books to learn the OCaml programming language."
~canonical:Url.books
~active_top_nav_item:Header.Learn
~current:Books @@
<div class="bg-default dark:bg-dark-default">
<div class="container-fluid" x-data="{ language: 'english' }">
<div class="flex justify-between mb-0 lg:flex-row flex-col items-center">
<h2 class="font-bold mt-10 lg:mt-0 mb-10 lg:mb-0">15+ OCaml Books</h2>
<div class="flex justify-between flex-col lg:flex-row lg:space-x-6 space-y-5 lg:space-y-0 md:space-y-5 w-full lg:w-auto">
<div class="container-fluid">
<h2 class="font-bold mt-10 mb-6 lg:mt-0">Books On OCaml (<%s string_of_int (List.length books) %>)</h2>
<form action="<%s Url.books %>" method="GET">
<div class="flex mb-0 flex-col gap-4 sm:flex-row">
<%s! Forms.select
~attrs:{|id="language" name="language" onchange="this.form.submit()"|}
~options:[("All", "All Languages"); ("english", "English"); ("french", "French"); ("italian", "Italian"); ("japanese", "Japanese"); ("chinese", "Chinese")]
~selected:language
"w-48 rounded-sm" %>
<%s! Forms.select
~attrs:{|id="difficulty" name="difficulty" onchange="this.form.submit()"|}
~options:[("All", "Any Difficulty"); ("beginner", "Beginner"); ("intermediate", "Intermediate"); ("advanced", "Advanced")]
~selected:difficulty
"w-48 rounded-sm" %>
<%s! Forms.select
~attrs:{|name="Languages" x-model="language"|}
~options:[("english", "English"); ("french", "French"); ("italian", "Italian"); ("portugese", "Portugese"); ("japanese", "Japanese"); ("chinese", "Chinese")]
"h-14" %>
~attrs:{|id="pricing" name="pricing" onchange="this.form.submit()"|}
~options:[("All", "Free or Paid"); ("free", "Free"); ("paid", "Paid")]
~selected:pricing
"w-48 rounded-sm" %>
</div>
</div>
<div :class="language != 'english' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "english") books) %>
</div>
<div :class="language != 'french' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "french") books) %>
</div>
<div :class="language != 'italian' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "italian") books) %>
</div>
<div :class="language != 'portugese' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "portugese") books) %>
</div>
<div :class="language != 'japanese' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "japanese") books) %>
</div>
<div :class="language != 'chinese' ? 'hidden' : 'block'">
<%s! render_books (List.filter (fun x -> x.Data.Book.language = "chinese") books) %>
</form>
<div>
<%s! render_books books %>
</div>
</div>
</div>
36 changes: 35 additions & 1 deletion src/ocamlorg_web/lib/handler.ml
Expand Up @@ -112,7 +112,41 @@ let academic_users req =
Dream.html (Ocamlorg_frontend.academic_users users)

let about _req = Dream.html (Ocamlorg_frontend.about ())
let books _req = Dream.html (Ocamlorg_frontend.books Data.Book.all)

let books req =
let language = Dream.query req "language" in
let pricing = Dream.query req "pricing" in
let difficulty = Dream.query req "difficulty" in
let matches_criteria (book : Data.Book.t) language pricing difficulty =
let matches_language =
match language with
| Some lang when lang = "All" -> true
| Some lang -> book.language = lang
| None -> true
in
let matches_pricing =
match pricing with
| Some p when p = "All" -> true
| Some p -> book.pricing = p
| None -> true
in
let matches_difficulty =
match difficulty with
| Some d when d = "All" -> true
| Some d -> (
match book.difficulty with Some bd -> bd = d | None -> false)
| None -> true
in
matches_language && matches_pricing && matches_difficulty
in
let filter_books books language pricing difficulty =
List.filter
(fun book -> matches_criteria book language pricing difficulty)
books
in
let filtered_books = filter_books Data.Book.all language pricing difficulty in
Dream.html
(Ocamlorg_frontend.books ?language ?pricing ?difficulty filtered_books)

let releases req =
let search_release pattern t =
Expand Down
3 changes: 3 additions & 0 deletions tool/ood-gen/lib/book.ml
Expand Up @@ -15,6 +15,7 @@ type metadata = {
rating : int option;
featured : bool;
difficulty : string option;
pricing : string;
}
[@@deriving of_yaml, show { with_path = false }]

Expand All @@ -32,6 +33,7 @@ type t = {
rating : int option;
featured : bool;
difficulty : string option;
pricing : string;
body_md : string;
body_html : string;
}
Expand Down Expand Up @@ -72,6 +74,7 @@ type t =
; rating : int option
; featured : bool
; difficulty : string option
; pricing : string
; body_md : string
; body_html : string
}
Expand Down

0 comments on commit 9c2abab

Please sign in to comment.