summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/style.css2
-rw-r--r--elm/Discussions/Reply.elm68
-rw-r--r--elm/Lib/TextPreview.elm2
-rw-r--r--lib/VNWeb/Discussions/Thread.pm50
4 files changed, 103 insertions, 19 deletions
diff --git a/data/style.css b/data/style.css
index c08c07f3..f73b45a0 100644
--- a/data/style.css
+++ b/data/style.css
@@ -204,7 +204,7 @@ span.spinner { width: 1em; height: 1em }
.textpreview .head { width: 100%; text-align: right }
.textpreview .head > * { margin-left: 10px; font-style: normal }
.textpreview textarea { width: 100%; box-sizing: border-box }
-.textpreview .preview { width: 100%; box-sizing: border-box; border: 1px solid $secborder$; margin: 1px; padding: 5px }
+.textpreview .preview { width: 100%; box-sizing: border-box; border: 1px solid $secborder$; margin: 1px; padding: 5px; text-align: left }
fieldset.submit .textpreview { margin: -15px auto 0 auto }
/* .compact input elements are smaller and can be embedded in tables/inline text
diff --git a/elm/Discussions/Reply.elm b/elm/Discussions/Reply.elm
new file mode 100644
index 00000000..79278a20
--- /dev/null
+++ b/elm/Discussions/Reply.elm
@@ -0,0 +1,68 @@
+module Discussions.Reply exposing (main)
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Browser
+import Browser.Navigation exposing (load)
+import Lib.Html exposing (..)
+import Lib.TextPreview as TP
+import Lib.Api as Api
+import Gen.Api as GApi
+import Gen.DiscussionsReply as GDR
+
+
+main : Program GDR.Recv Model Msg
+main = Browser.element
+ { init = \e -> (init e, Cmd.none)
+ , view = view
+ , update = update
+ , subscriptions = always Sub.none
+ }
+
+
+type alias Model =
+ { state : Api.State
+ , newurl : String
+ , tid : Int
+ , msg : TP.Model
+ }
+
+
+init : GDR.Recv -> Model
+init d =
+ { state = Api.Normal
+ , newurl = d.newurl
+ , tid = d.tid
+ , msg = TP.bbcode ""
+ }
+
+
+type Msg
+ = Content TP.Msg
+ | Submit
+ | Submitted GApi.Response
+
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+ Content m -> let (nm,nc) = TP.update m model.msg in ({ model | msg = nm }, Cmd.map Content nc)
+
+ Submit ->
+ let body = GDR.encode { msg = model.msg.data, tid = model.tid }
+ in ({ model | state = Api.Loading }, Api.post "/t/reply.json" body Submitted)
+ Submitted GApi.Success -> (model, load model.newurl)
+ Submitted r -> ({ model | state = Api.Error r }, Cmd.none)
+
+
+view : Model -> Html Msg
+view model =
+ form_ Submit (model.state == Api.Loading)
+ [ div [ class "mainbox" ]
+ [ fieldset [ class "submit" ]
+ [ h2 [] [ text "Quick reply", b [ class "standout" ] [ text " (English please!)" ] ]
+ , TP.view "msg" model.msg Content 600 ([rows 4, cols 50] ++ GDR.valMsg)
+ , submitButton "Submit" model.state True
+ ]
+ ]
+ ]
diff --git a/elm/Lib/TextPreview.elm b/elm/Lib/TextPreview.elm
index 8c9e3287..2d565e5f 100644
--- a/elm/Lib/TextPreview.elm
+++ b/elm/Lib/TextPreview.elm
@@ -74,7 +74,7 @@ view name model cmdmap width attr =
div [ class "textpreview", style "width" (String.fromInt width ++ "px") ]
[ p (class "head" :: (if model.data == "" then [class "invisible"] else []))
[ case model.state of
- Api.Loading -> div [ class "spinner" ] []
+ Api.Loading -> span [ class "spinner" ] []
Api.Error _ -> b [ class "grayedout" ] [ text "Error loading preview. " ]
Api.Normal -> text ""
, if display
diff --git a/lib/VNWeb/Discussions/Thread.pm b/lib/VNWeb/Discussions/Thread.pm
index 30827aaa..c81e02a9 100644
--- a/lib/VNWeb/Discussions/Thread.pm
+++ b/lib/VNWeb/Discussions/Thread.pm
@@ -29,6 +29,23 @@ my $POLL_IN = form_compile any => {
elm_form 'DiscussionsPoll' => $POLL_OUT, $POLL_IN;
+
+my $REPLY_OUT = form_compile any => {
+ tid => { id => 1 },
+ newurl => { },
+};
+
+
+my $REPLY_IN = form_compile any => {
+ tid => { id => 1 },
+ msg => { maxlength => 32768 }
+};
+
+
+elm_form 'DiscussionsReply' => $REPLY_OUT, $REPLY_IN;
+
+
+
sub metabox_ {
my($t) = @_;
div_ class => 'mainbox', sub {
@@ -96,22 +113,7 @@ sub reply_ {
my($t, $page) = @_;
return if $t->{count} > $page*25;
if(can_edit t => $t) {
- # TODO: Elmify
- form_ action => "/t$t->{id}/reply", method => 'post', 'accept-charset' => 'UTF-8', sub {
- div_ class => 'mainbox', sub {
- fieldset_ class => 'submit', sub {
- input_ type => 'hidden', class => 'hidden', name => 'formcode', value => auth->csrftoken;
- h2_ sub {
- txt_ 'Quick reply';
- b_ class => 'standout', ' (English please!)';
- };
- textarea_ name => 'msg', id => 'msg', rows => 4, cols => 50, '';
- br_;
- input_ type => 'submit', value => 'Reply', class => 'submit';
- input_ type => 'submit', value => 'Go advanced...', class => 'submit', name => 'fullreply';
- }
- }
- }
+ elm_ 'Discussions.Reply' => $REPLY_OUT, { tid => $t->{id}, newurl => post_url($t->{id}, $t->{count}+1) };
} else {
div_ class => 'mainbox', sub {
h1_ 'Reply';
@@ -183,7 +185,7 @@ json_api qr{/t/pollvote.json}, $POLL_IN, sub {
my($data) = @_;
return elm_Unauth if !auth;
- my $t = tuwf->dbRowi('SELECT poll_question, poll_max_options FROM threads WHERE id =', \$data->{tid});
+ my $t = tuwf->dbRowi('SELECT poll_question, poll_max_options FROM threads t WHERE id =', \$data->{tid}, 'AND', sql_visible_threads());
return tuwf->resNotFound if !$t->{poll_question};
die 'Too many options' if $data->{options}->@* > $t->{poll_max_options};
@@ -194,4 +196,18 @@ json_api qr{/t/pollvote.json}, $POLL_IN, sub {
elm_Success
};
+
+json_api qr{/t/reply.json}, $REPLY_IN, sub {
+ my($data) = @_;
+ my $t = tuwf->dbRowi('SELECT id, locked, count FROM threads t WHERE id =', \$data->{tid}, 'AND', sql_visible_threads());
+ return tuwf->resNotFound if !$t->{id};
+ return elm_Unauth if !can_edit t => $t;
+
+ my $num = $t->{count}+1;
+ my $msg = bb_subst_links $data->{msg};
+ tuwf->dbExeci('INSERT INTO threads_posts (tid, num, uid, msg) VALUES (', sql_comma(\$t->{id}, \$num, \auth->uid, \$msg), ')');
+ tuwf->dbExeci('UPDATE threads SET count =', \$num, 'WHERE id =', \$t->{id});
+ elm_Success
+};
+
1;