add categories
This commit is contained in:
parent
4064fced95
commit
b5fc7e9a8d
6 changed files with 85 additions and 25 deletions
|
|
@ -78,9 +78,13 @@ let log =
|
||||||
|
|
||||||
let () = Dream.log "log: %b" log
|
let () = Dream.log "log: %b" log
|
||||||
|
|
||||||
let admins =
|
let get_dirs name =
|
||||||
let dirs = Scfg.Query.get_dirs "admin" config in
|
let dirs = Scfg.Query.get_dirs name config in
|
||||||
List.map
|
List.map
|
||||||
(fun dir ->
|
(fun dir ->
|
||||||
Result.fold ~error:failwith ~ok:Fun.id (Scfg.Query.get_param 0 dir) )
|
Result.fold ~error:failwith ~ok:Fun.id (Scfg.Query.get_param 0 dir) )
|
||||||
dirs
|
dirs
|
||||||
|
|
||||||
|
let admins = get_dirs "admin"
|
||||||
|
|
||||||
|
let categories = get_dirs "category"
|
||||||
|
|
|
||||||
|
|
@ -343,9 +343,8 @@ let upload_post ?image_content post =
|
||||||
let^ () = Db.exec Q.upload_thread_info (id, subject, lat, lng) in
|
let^ () = Db.exec Q.upload_thread_info (id, subject, lat, lng) in
|
||||||
Ok id
|
Ok id
|
||||||
|
|
||||||
let build_reply ~comment ?image ~tags ?parent_id user_id =
|
let build_reply ~comment ?image ~tag_list ?parent_id user_id =
|
||||||
let comment = Dream.html_escape comment in
|
let comment = Dream.html_escape comment in
|
||||||
let tags = Dream.html_escape tags in
|
|
||||||
let id = Uuidm.to_string (Uuidm.v4_gen random_state ()) in
|
let id = Uuidm.to_string (Uuidm.v4_gen random_state ()) in
|
||||||
(* parent_id is None if this reply is supposed to be a new thread *)
|
(* parent_id is None if this reply is supposed to be a new thread *)
|
||||||
let parent_id = Option.value parent_id ~default:id in
|
let parent_id = Option.value parent_id ~default:id in
|
||||||
|
|
@ -355,7 +354,9 @@ let build_reply ~comment ?image ~tags ?parent_id user_id =
|
||||||
match parse_image image with
|
match parse_image image with
|
||||||
| Error e -> Error e
|
| Error e -> Error e
|
||||||
| Ok image ->
|
| Ok image ->
|
||||||
if String.length tags > 1000 then Error "invalid tags"
|
if List.length tag_list > 30 then Error "too much tags"
|
||||||
|
else if List.exists (fun tag -> String.length tag > 100) tag_list then
|
||||||
|
Error "tag too long"
|
||||||
else
|
else
|
||||||
let image_info =
|
let image_info =
|
||||||
match image with
|
match image with
|
||||||
|
|
@ -367,7 +368,7 @@ let build_reply ~comment ?image ~tags ?parent_id user_id =
|
||||||
@@ List.sort_uniq String.compare
|
@@ List.sort_uniq String.compare
|
||||||
@@ List.filter (( <> ) "")
|
@@ List.filter (( <> ) "")
|
||||||
@@ List.map String.trim
|
@@ List.map String.trim
|
||||||
@@ Str.split (Str.regexp ",+") tags
|
@@ List.map Dream.html_escape tag_list
|
||||||
in
|
in
|
||||||
let date = Unix.time () in
|
let date = Unix.time () in
|
||||||
let comment, citations = parse_comment comment in
|
let comment, citations = parse_comment comment in
|
||||||
|
|
@ -387,31 +388,39 @@ let build_reply ~comment ?image ~tags ?parent_id user_id =
|
||||||
in
|
in
|
||||||
Ok reply
|
Ok reply
|
||||||
|
|
||||||
let build_op ~comment ?image ~tags ~subject ~lat ~lng user_id =
|
let build_op ~comment ?image ~tag_list ~categories ~subject ~lat ~lng user_id =
|
||||||
let subject = Dream.html_escape subject in
|
let subject = Dream.html_escape subject in
|
||||||
(* TODO latlng validation? *)
|
if List.exists (fun s -> not (List.mem s App.categories)) categories then
|
||||||
let is_valid_latlng = true in
|
Error "Invalid category"
|
||||||
if not is_valid_latlng then Error "Invalid coordinate"
|
|
||||||
else if String.length subject > 600 then Error "Invalid subject"
|
|
||||||
else
|
else
|
||||||
let thread_data = { subject; lng; lat } in
|
let tag_list = categories @ tag_list in
|
||||||
let* reply =
|
(* TODO latlng validation? *)
|
||||||
match image with
|
let is_valid_latlng = true in
|
||||||
| Some image -> build_reply ~comment ~image ~tags user_id
|
if not is_valid_latlng then Error "Invalid coordinate"
|
||||||
| None -> build_reply ~comment ~tags user_id
|
else if String.length subject > 600 then Error "Invalid subject"
|
||||||
in
|
else
|
||||||
let op = Op (thread_data, reply) in
|
let thread_data = { subject; lng; lat } in
|
||||||
Ok op
|
let* reply =
|
||||||
|
match image with
|
||||||
|
| Some image -> build_reply ~comment ~image ~tag_list user_id
|
||||||
|
| None -> build_reply ~comment ~tag_list user_id
|
||||||
|
in
|
||||||
|
let op = Op (thread_data, reply) in
|
||||||
|
Ok op
|
||||||
|
|
||||||
let make_reply ~comment ?image ~tags ~parent_id user_id =
|
let make_reply ~comment ?image ~tags ~parent_id user_id =
|
||||||
let* reply = build_reply ~comment ?image ~tags ~parent_id user_id in
|
let tag_list = Str.split (Str.regexp ",+") tags in
|
||||||
|
let* reply = build_reply ~comment ?image ~tag_list ~parent_id user_id in
|
||||||
let post = Post reply in
|
let post = Post reply in
|
||||||
match image with
|
match image with
|
||||||
| None -> upload_post post
|
| None -> upload_post post
|
||||||
| Some (_image_info, image_content) -> upload_post ~image_content post
|
| Some (_image_info, image_content) -> upload_post ~image_content post
|
||||||
|
|
||||||
let make_op ~comment ?image ~tags ~subject ~lat ~lng user_id =
|
let make_op ~comment ?image ~tags ~categories ~subject ~lat ~lng user_id =
|
||||||
let* op = build_op ~comment ?image ~tags ~subject ~lat ~lng user_id in
|
let tag_list = Str.split (Str.regexp ",+") tags in
|
||||||
|
let* op =
|
||||||
|
build_op ~comment ?image ~tag_list ~categories ~subject ~lat ~lng user_id
|
||||||
|
in
|
||||||
match image with
|
match image with
|
||||||
| None -> upload_post op
|
| None -> upload_post op
|
||||||
| Some (_image_info, image_content) -> upload_post ~image_content op
|
| Some (_image_info, image_content) -> upload_post ~image_content op
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ let f request =
|
||||||
<textarea name="thread-comment" type="text" class="form-control" id="thread-comment" aria-labelledby="thread-comment-label"></textarea>
|
<textarea name="thread-comment" type="text" class="form-control" id="thread-comment" aria-labelledby="thread-comment-label"></textarea>
|
||||||
<br />
|
<br />
|
||||||
<label for="tags" id="tags-label" class="form-label">Tags</label>
|
<label for="tags" id="tags-label" class="form-label">Tags</label>
|
||||||
|
<%s! Pp_babillard.pp_checkboxes () %>
|
||||||
<input name="tags" type="text" class="form-control" id="tags" aria-labelledby="tags-label"></input>
|
<input name="tags" type="text" class="form-control" id="tags" aria-labelledby="tags-label"></input>
|
||||||
<br />
|
<br />
|
||||||
<label for="file" id="file-label" class="form-label">Picture:</label>
|
<label for="file" id="file-label" class="form-label">Picture:</label>
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,14 @@ a.preview-link {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
background-color: #FFB300;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.off {
|
.off {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
include Bindings
|
||||||
|
|
||||||
let get_title content =
|
let get_title content =
|
||||||
let open Soup in
|
let open Soup in
|
||||||
try
|
try
|
||||||
|
|
@ -341,6 +343,7 @@ let babillard_post request =
|
||||||
match%lwt Dream.multipart request with
|
match%lwt Dream.multipart request with
|
||||||
| `Ok
|
| `Ok
|
||||||
[ ("alt", [ (_, alt) ])
|
[ ("alt", [ (_, alt) ])
|
||||||
|
; ("category", categories)
|
||||||
; ("file", file)
|
; ("file", file)
|
||||||
; ("lat-input", [ (_, lat) ])
|
; ("lat-input", [ (_, lat) ])
|
||||||
; ("lng-input", [ (_, lng) ])
|
; ("lng-input", [ (_, lng) ])
|
||||||
|
|
@ -348,17 +351,23 @@ let babillard_post request =
|
||||||
; ("tags", [ (_, tags) ])
|
; ("tags", [ (_, tags) ])
|
||||||
; ("thread-comment", [ (_, comment) ])
|
; ("thread-comment", [ (_, comment) ])
|
||||||
] -> (
|
] -> (
|
||||||
|
let categories =
|
||||||
|
List.map (fun (_name, category) -> category) categories
|
||||||
|
in
|
||||||
match (Float.of_string_opt lat, Float.of_string_opt lng) with
|
match (Float.of_string_opt lat, Float.of_string_opt lng) with
|
||||||
| None, _ -> render_unsafe "Invalide coordinate" request
|
| None, _ -> render_unsafe "Invalide coordinate" request
|
||||||
| _, None -> render_unsafe "Invalide coordinate" request
|
| _, None -> render_unsafe "Invalide coordinate" request
|
||||||
| Some lat, Some lng -> (
|
| Some lat, Some lng -> (
|
||||||
let res =
|
let res =
|
||||||
match file with
|
match file with
|
||||||
| [] -> Babillard.make_op ~comment ~lat ~lng ~subject ~tags user_id
|
| [] ->
|
||||||
|
Babillard.make_op ~comment ~lat ~lng ~subject ~tags ~categories
|
||||||
|
user_id
|
||||||
| _ :: _ :: _ -> Error "More than one image"
|
| _ :: _ :: _ -> Error "More than one image"
|
||||||
| [ (image_name, image_content) ] ->
|
| [ (image_name, image_content) ] ->
|
||||||
let image = ((image_name, alt), image_content) in
|
let image = ((image_name, alt), image_content) in
|
||||||
Babillard.make_op ~comment ~image ~lat ~lng ~subject ~tags user_id
|
Babillard.make_op ~comment ~image ~lat ~lng ~subject ~tags
|
||||||
|
~categories user_id
|
||||||
in
|
in
|
||||||
match res with
|
match res with
|
||||||
| Ok thread_id ->
|
| Ok thread_id ->
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,21 @@ let pp_post fmt t =
|
||||||
user_id nick date id id id post_links_view ()
|
user_id nick date id id id post_links_view ()
|
||||||
in
|
in
|
||||||
|
|
||||||
|
let pp_print_category fmt category =
|
||||||
|
Format.fprintf fmt {|<span class="category tag">%s</span>|} category
|
||||||
|
in
|
||||||
let pp_print_tag fmt tag =
|
let pp_print_tag fmt tag =
|
||||||
Format.fprintf fmt {|<span class="tag">%s</span>|} tag
|
Format.fprintf fmt {|<span class="tag">%s</span>|} tag
|
||||||
in
|
in
|
||||||
let pp_print_tags fmt tags =
|
let pp_print_tags fmt tags =
|
||||||
Format.fprintf fmt {|<div class="tags">%a</div>|}
|
let categories, tags =
|
||||||
|
List.partition (fun tag -> List.mem tag App.categories) tags
|
||||||
|
in
|
||||||
|
let categories = List.sort String.compare categories in
|
||||||
|
let tags = List.sort String.compare tags in
|
||||||
|
Format.fprintf fmt {|<div class="tags">%a%a</div>|}
|
||||||
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_print_category)
|
||||||
|
categories
|
||||||
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_print_tag)
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_print_tag)
|
||||||
tags
|
tags
|
||||||
in
|
in
|
||||||
|
|
@ -274,6 +284,25 @@ let get_markers () =
|
||||||
in
|
in
|
||||||
Ok markers
|
Ok markers
|
||||||
|
|
||||||
|
let pp_checkboxes () =
|
||||||
|
let pp_checkbox fmt category =
|
||||||
|
Format.fprintf fmt
|
||||||
|
{|
|
||||||
|
<div class="form-check col">
|
||||||
|
<input name="category" id="category-%s" type="checkbox" class"form-check-input" value="%s">
|
||||||
|
<label class="form-check-label" for="category-%s">%s</label>
|
||||||
|
</div>
|
||||||
|
|}
|
||||||
|
category category category category
|
||||||
|
in
|
||||||
|
Format.asprintf
|
||||||
|
{|
|
||||||
|
<div class="row">
|
||||||
|
%a
|
||||||
|
</div>|}
|
||||||
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space pp_checkbox)
|
||||||
|
App.categories
|
||||||
|
|
||||||
(* RFC-3339 date-time *)
|
(* RFC-3339 date-time *)
|
||||||
let pp_date fmt date =
|
let pp_date fmt date =
|
||||||
let date = Unix.gmtime date in
|
let date = Unix.gmtime date in
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue