2022-02-02 19:16:53 +01:00
|
|
|
include Bindings
|
2022-01-29 09:34:57 +01:00
|
|
|
include Babillard
|
|
|
|
|
open Db
|
|
|
|
|
|
2022-02-21 00:51:44 +01:00
|
|
|
let pp_post fmt ~hide_replies post =
|
|
|
|
|
let { id
|
|
|
|
|
; parent_id = _parent_id
|
|
|
|
|
; date
|
|
|
|
|
; nick
|
|
|
|
|
; comment
|
|
|
|
|
; image_info
|
|
|
|
|
; tags
|
|
|
|
|
; replies
|
|
|
|
|
; citations = _citations
|
|
|
|
|
} =
|
|
|
|
|
post
|
2022-02-18 19:40:19 +01:00
|
|
|
in
|
2022-01-29 09:34:57 +01:00
|
|
|
|
2022-02-18 01:37:25 +01:00
|
|
|
let image_view fmt () =
|
2022-01-29 09:34:57 +01:00
|
|
|
match image_info with
|
|
|
|
|
| Some (_image_name, image_alt) ->
|
2022-02-18 01:37:25 +01:00
|
|
|
Format.fprintf fmt
|
2022-01-29 09:34:57 +01:00
|
|
|
{|
|
2022-02-18 20:17:24 +01:00
|
|
|
<div class="post-image-container">
|
2022-02-18 19:40:19 +01:00
|
|
|
<a href="/img/%s">
|
2022-02-18 20:17:24 +01:00
|
|
|
<img class="post-image" src="/img/%s" alt="%s" title="%s" loading="lazy">
|
2022-01-29 09:34:57 +01:00
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|}
|
2022-02-18 19:40:19 +01:00
|
|
|
id id image_alt image_alt
|
2022-02-18 01:37:25 +01:00
|
|
|
| None -> Format.fprintf fmt ""
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
|
|
|
|
|
|
|
|
|
let pp_print_reply fmt reply =
|
2022-02-18 20:17:24 +01:00
|
|
|
Format.fprintf fmt {|<a class="reply-link" href="#%s">>>%s</a>|} reply
|
2022-01-29 09:34:57 +01:00
|
|
|
reply
|
|
|
|
|
in
|
2022-02-18 01:37:25 +01:00
|
|
|
let pp_print_replies fmt replies =
|
|
|
|
|
Format.fprintf fmt {|<div class="replies">%a</div>|}
|
2022-01-29 09:34:57 +01:00
|
|
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_print_reply)
|
2022-02-02 13:47:04 +01:00
|
|
|
replies
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
|
|
|
|
|
2022-02-18 01:37:25 +01:00
|
|
|
let replies_view fmt () =
|
2022-02-21 00:51:44 +01:00
|
|
|
if hide_replies then
|
|
|
|
|
(* TODO put thread_posts count in thread_info ? *)
|
2022-02-18 19:40:19 +01:00
|
|
|
let res_nb = Db.find Q.count_thread_posts id in
|
2022-01-29 09:34:57 +01:00
|
|
|
match res_nb with
|
2022-02-18 01:37:25 +01:00
|
|
|
| Error _ -> Format.fprintf fmt ""
|
2022-01-29 09:34:57 +01:00
|
|
|
| Ok ((1 | 2) as nb) ->
|
2022-02-18 01:37:25 +01:00
|
|
|
Format.fprintf fmt {|<div class="replies">%d reply</div>|} (nb - 1)
|
2022-01-29 09:34:57 +01:00
|
|
|
| Ok nb ->
|
2022-02-21 00:51:44 +01:00
|
|
|
Format.fprintf fmt {|<div class="replies">%d replies</div>|} (nb - 1)
|
|
|
|
|
else pp_print_replies fmt replies
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
|
|
|
|
|
2022-02-18 01:37:25 +01:00
|
|
|
let post_links_view fmt () =
|
2022-02-21 00:51:44 +01:00
|
|
|
if hide_replies then
|
|
|
|
|
Format.fprintf fmt {|
|
|
|
|
|
%a
|
|
|
|
|
|} replies_view ()
|
|
|
|
|
else
|
2022-02-18 01:37:25 +01:00
|
|
|
Format.fprintf fmt
|
2022-01-29 09:34:57 +01:00
|
|
|
{|
|
|
|
|
|
<span class=postNo>
|
2022-02-18 18:31:55 +01:00
|
|
|
<a href="#%s" title="Link to this post" class="quote">#</a>
|
2022-02-18 20:17:24 +01:00
|
|
|
<button data-id="%s" class="quote-link" title="Reply to this post">%s</button>
|
2022-01-29 09:34:57 +01:00
|
|
|
</span>
|
2022-02-18 01:37:25 +01:00
|
|
|
%a
|
2022-01-29 09:34:57 +01:00
|
|
|
|}
|
2022-02-18 19:40:19 +01:00
|
|
|
id id id replies_view ()
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
|
|
|
|
|
2022-02-18 01:37:25 +01:00
|
|
|
let post_info_view fmt () =
|
|
|
|
|
Format.fprintf fmt
|
2022-01-29 09:34:57 +01:00
|
|
|
{|
|
2022-02-18 20:17:24 +01:00
|
|
|
<div class="post-info">
|
2022-01-29 09:34:57 +01:00
|
|
|
<span class="nick">%s</span>
|
|
|
|
|
<span class="date" data-time="%d"></span>
|
2022-02-18 01:37:25 +01:00
|
|
|
%a
|
2022-01-29 09:34:57 +01:00
|
|
|
</div>|}
|
2022-02-18 01:37:25 +01:00
|
|
|
nick date post_links_view ()
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
2022-02-02 13:47:04 +01:00
|
|
|
|
|
|
|
|
let pp_print_tag fmt tag =
|
|
|
|
|
Format.fprintf fmt {|<span class="tag">%s</span>|} tag
|
|
|
|
|
in
|
2022-02-18 01:37:25 +01:00
|
|
|
let pp_print_tags fmt tags =
|
|
|
|
|
Format.fprintf fmt {|<div class="tags">%a</div>|}
|
2022-02-02 13:47:04 +01:00
|
|
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_print_tag)
|
|
|
|
|
tags
|
|
|
|
|
in
|
|
|
|
|
let tags = List.sort String.compare tags in
|
2022-02-18 01:37:25 +01:00
|
|
|
let tags_view fmt () = pp_print_tags fmt tags in
|
2022-02-02 13:47:04 +01:00
|
|
|
|
2022-02-21 00:51:44 +01:00
|
|
|
let pp =
|
|
|
|
|
Format.fprintf fmt
|
2022-01-29 09:34:57 +01:00
|
|
|
{|
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="post" id="%s">
|
2022-02-18 01:37:25 +01:00
|
|
|
%a
|
|
|
|
|
%a
|
2022-02-18 20:17:24 +01:00
|
|
|
<blockquote class="post-comment">%s</blockquote>
|
2022-02-18 01:37:25 +01:00
|
|
|
%a
|
2022-01-29 09:34:57 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|}
|
2022-02-18 19:40:19 +01:00
|
|
|
id post_info_view () image_view () comment tags_view ()
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
2022-02-21 00:51:44 +01:00
|
|
|
pp
|
2022-01-29 09:34:57 +01:00
|
|
|
|
2022-02-21 01:59:36 +01:00
|
|
|
let pp_thread_preview op =
|
|
|
|
|
let thread_data, post = op in
|
|
|
|
|
let post_view =
|
2022-02-21 00:51:44 +01:00
|
|
|
(Format.asprintf "%a" (fun fmt data -> pp_post fmt ~hide_replies:true data))
|
2022-02-21 01:59:36 +01:00
|
|
|
post
|
2022-02-21 00:51:44 +01:00
|
|
|
in
|
2022-02-02 11:58:18 +01:00
|
|
|
let thread_preview =
|
|
|
|
|
Format.sprintf
|
|
|
|
|
{|
|
2022-02-18 20:17:24 +01:00
|
|
|
<div class="thread-preview">
|
|
|
|
|
<div class="thread-subject">
|
2022-02-02 11:58:18 +01:00
|
|
|
%s
|
|
|
|
|
</div>
|
|
|
|
|
%s
|
|
|
|
|
</div>
|
|
|
|
|
|}
|
2022-02-21 01:59:36 +01:00
|
|
|
thread_data.subject post_view
|
2022-02-02 11:58:18 +01:00
|
|
|
in
|
2022-02-21 01:59:36 +01:00
|
|
|
thread_preview
|
2022-01-29 09:34:57 +01:00
|
|
|
|
2022-02-21 00:19:35 +01:00
|
|
|
let catalog_content () =
|
|
|
|
|
Format.printf "catalog_content@.";
|
|
|
|
|
let^ threads = Db.collect_list Q.get_threads () in
|
2022-02-21 01:59:36 +01:00
|
|
|
let res_previews =
|
|
|
|
|
List.map
|
|
|
|
|
(fun id ->
|
|
|
|
|
let* op = get_op id in
|
|
|
|
|
Ok (pp_thread_preview op) )
|
|
|
|
|
threads
|
|
|
|
|
in
|
|
|
|
|
|
2022-02-21 00:19:35 +01:00
|
|
|
let res_opt = List.find_opt Result.is_error res_previews in
|
|
|
|
|
if Option.is_some res_opt then Option.get res_opt
|
|
|
|
|
else
|
|
|
|
|
let previews = List.map Result.get_ok res_previews in
|
|
|
|
|
Ok
|
|
|
|
|
(Format.asprintf "%a"
|
|
|
|
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space
|
|
|
|
|
Format.pp_print_string )
|
|
|
|
|
previews )
|
|
|
|
|
|
2022-01-29 09:34:57 +01:00
|
|
|
let view_thread thread_id =
|
2022-02-18 19:40:19 +01:00
|
|
|
let^ _is_thread = Db.find Q.get_is_thread thread_id in
|
2022-02-21 00:19:35 +01:00
|
|
|
let^? subject, _lat, _lng = Db.find_opt Q.get_thread_info thread_id in
|
2022-02-18 01:37:25 +01:00
|
|
|
let^ thread_posts = Db.collect_list Q.get_thread_posts thread_id in
|
|
|
|
|
(*order by date *)
|
|
|
|
|
let dates = List.map (Db.find Q.get_post_date) thread_posts in
|
|
|
|
|
match List.find_opt Result.is_error dates with
|
|
|
|
|
| Some (Error e) -> Error (Format.sprintf "db error: %s" (Caqti_error.show e))
|
|
|
|
|
| Some (Ok _) -> assert false
|
2022-02-21 00:51:44 +01:00
|
|
|
| None ->
|
2022-02-18 01:37:25 +01:00
|
|
|
let dates = List.map Result.get_ok dates in
|
|
|
|
|
let posts_dates = List.combine thread_posts dates in
|
|
|
|
|
let sorted_posts_dates =
|
|
|
|
|
List.sort (fun (_, a) (_, b) -> compare a b) posts_dates
|
2022-01-29 09:34:57 +01:00
|
|
|
in
|
2022-02-18 01:37:25 +01:00
|
|
|
|
|
|
|
|
let posts, _ = List.split sorted_posts_dates in
|
2022-02-21 00:51:44 +01:00
|
|
|
let posts_data = List.map get_post posts in
|
|
|
|
|
let res_opt = List.find_opt Result.is_error posts_data in
|
|
|
|
|
if Option.is_some res_opt then
|
|
|
|
|
let res = Result.get_error (Option.get res_opt) in
|
|
|
|
|
Error res
|
|
|
|
|
else
|
|
|
|
|
let posts_data = List.map Result.get_ok posts_data in
|
2022-02-18 01:37:25 +01:00
|
|
|
let posts =
|
|
|
|
|
Format.asprintf "%a"
|
|
|
|
|
(Format.pp_print_list
|
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "\r\n")
|
2022-02-21 00:51:44 +01:00
|
|
|
(fun fmt data -> pp_post fmt ~hide_replies:false data) )
|
|
|
|
|
posts_data
|
2022-02-18 01:37:25 +01:00
|
|
|
in
|
|
|
|
|
let thread_view =
|
|
|
|
|
Format.sprintf
|
|
|
|
|
{|
|
2022-02-02 11:58:18 +01:00
|
|
|
<div class="thread">
|
2022-02-18 20:17:24 +01:00
|
|
|
<div class="thread-subject">
|
2022-02-02 11:58:18 +01:00
|
|
|
%s
|
|
|
|
|
</div>
|
2022-02-18 20:17:24 +01:00
|
|
|
<div class="thread-posts">
|
2022-02-02 11:58:18 +01:00
|
|
|
%s
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|}
|
2022-02-18 01:37:25 +01:00
|
|
|
subject posts
|
|
|
|
|
in
|
2022-02-21 00:51:44 +01:00
|
|
|
Ok thread_view
|
2022-01-29 09:34:57 +01:00
|
|
|
|
2022-02-17 03:59:23 +01:00
|
|
|
let get_markers () =
|
2022-02-21 01:59:36 +01:00
|
|
|
let^ ids = Db.collect_list Q.get_threads () in
|
|
|
|
|
let res_previews =
|
|
|
|
|
List.map
|
|
|
|
|
(fun id ->
|
|
|
|
|
let* op = get_op id in
|
|
|
|
|
Ok (pp_thread_preview op) )
|
|
|
|
|
ids
|
|
|
|
|
in
|
|
|
|
|
let res_infos = List.map (Db.find Q.get_thread_info) ids in
|
2022-02-21 00:19:35 +01:00
|
|
|
|
|
|
|
|
let res_previews_opt = List.find_opt Result.is_error res_previews in
|
|
|
|
|
let res_info_opt = List.find_opt Result.is_error res_infos in
|
|
|
|
|
if Option.is_some res_previews_opt then Option.get res_previews_opt
|
|
|
|
|
else if Option.is_some res_info_opt then
|
|
|
|
|
Error
|
|
|
|
|
(Result.fold
|
|
|
|
|
~ok:(assert false)
|
|
|
|
|
~error:Caqti_error.show (Option.get res_info_opt) )
|
|
|
|
|
else
|
|
|
|
|
let previews = List.map Result.get_ok res_previews in
|
|
|
|
|
let infos = List.map Result.get_ok res_infos in
|
|
|
|
|
let previews_infos = List.combine previews infos in
|
2022-02-21 01:59:36 +01:00
|
|
|
let previews_infos_ids = List.combine previews_infos ids in
|
2022-02-21 00:19:35 +01:00
|
|
|
|
|
|
|
|
let pp_marker fmt lat lng content thread_id =
|
|
|
|
|
(* geojson use lng lat, and not lat lng*)
|
|
|
|
|
let json =
|
|
|
|
|
`Assoc
|
|
|
|
|
[ ("type", `String "Feature")
|
|
|
|
|
; ( "geometry"
|
|
|
|
|
, `Assoc
|
|
|
|
|
[ ("type", `String "Point")
|
|
|
|
|
; ("coordinates", `List [ `Float lng; `Float lat ])
|
|
|
|
|
] )
|
|
|
|
|
; ( "properties"
|
|
|
|
|
, `Assoc
|
|
|
|
|
[ ("content", `String content)
|
|
|
|
|
; ("thread_id", `String thread_id)
|
|
|
|
|
] )
|
|
|
|
|
]
|
|
|
|
|
in
|
|
|
|
|
Yojson.pretty_print fmt json
|
2022-02-19 02:19:13 +01:00
|
|
|
in
|
2022-02-21 00:19:35 +01:00
|
|
|
|
|
|
|
|
let markers =
|
|
|
|
|
Format.asprintf "[%a]"
|
|
|
|
|
(Format.pp_print_list
|
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt ",")
|
|
|
|
|
(fun fmt ((preview, (_sub, lat, lng)), id) ->
|
|
|
|
|
pp_marker fmt lat lng preview id ) )
|
|
|
|
|
previews_infos_ids
|
|
|
|
|
in
|
|
|
|
|
Ok markers
|