summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-07-25 14:03:37 +0200
committerYorhel <git@yorhel.nl>2020-07-25 14:03:37 +0200
commit025ab84a962f3c61fd4217f1518ef4928bf72bf3 (patch)
tree3c553ead5033006e51736922720af2f41568d8c7
parent40ea78ddfa265daea03f9904784bc0c35980b894 (diff)
Reports: Allow reporting DB entries
-rw-r--r--data/style.css2
-rw-r--r--elm/Report.elm102
-rw-r--r--lib/VNWeb/Discussions/Board.pm7
-rw-r--r--lib/VNWeb/Docs/Page.pm1
-rw-r--r--lib/VNWeb/HTML.pm17
-rw-r--r--lib/VNWeb/Misc/History.pm14
-rw-r--r--lib/VNWeb/Misc/Reports.pm29
-rw-r--r--lib/VNWeb/Prelude.pm23
-rw-r--r--lib/VNWeb/Producers/Page.pm5
-rw-r--r--lib/VNWeb/VN/Page.pm1
-rw-r--r--sql/schema.sql2
-rw-r--r--util/updates/2020-07-25-report-db.sql2
12 files changed, 158 insertions, 47 deletions
diff --git a/data/style.css b/data/style.css
index 6415d516..c7400504 100644
--- a/data/style.css
+++ b/data/style.css
@@ -100,7 +100,7 @@ div.warning h2, div.notice h2 { font-size: 13px; font-weight: bold; margin: 0; }
/* general text formatting */
ul, ol { margin-left: 35px; }
-p.locked { float: right; color: $standout$; font-style: italic; margin: 0!important; }
+p.itemmsg { float: right; color: $standout$; font-style: italic; margin: 0!important; }
.grayedout { color: $grayedout$ }
b.grayedout { font-weight: normal }
i.grayedout { font-style: normal }
diff --git a/elm/Report.elm b/elm/Report.elm
index 8cbf498e..e9ae59de 100644
--- a/elm/Report.elm
+++ b/elm/Report.elm
@@ -29,14 +29,93 @@ type Msg
| Submitted GApi.Response
--- These can be different depending on the rtype.
+type alias ReasonLabel =
+ { label : String
+ , vis : String -> String -> Bool -- Given an rtype & objectid, returns whether it should be listed
+ , submit : Bool -- Whether it allows submission of the form
+ , msg : String -> String -> List (Html Msg) -- Message to display
+ }
+
+
+vis _ _ = True
+nomsg _ _ = []
+initial = { label = "-- Select --" , vis = vis, submit = False , msg = nomsg }
+
+reasons : List ReasonLabel
reasons =
- [ "Spam"
- , "Links to piracy or illegal content"
- , "Off-topic / wrong board"
- , "Unmarked spoilers"
- , "Unwelcome behavior"
- , "Other"
+ [ initial
+ , { label = "Spam"
+ , vis = vis
+ , submit = True
+ , msg = nomsg
+ }
+ , { label = "Links to piracy or illegal content"
+ , vis = vis
+ , submit = True
+ , msg = nomsg
+ }
+ , { label = "Off-topic / wrong board"
+ , vis = \t _ -> t == "t"
+ , submit = True
+ , msg = nomsg
+ }
+ , { label = "Unwelcome behavior"
+ , vis = \t _ -> t == "t"
+ , submit = True
+ , msg = nomsg
+ }
+ , { label = "Unmarked spoilers"
+ , vis = vis
+ , submit = True
+ , msg = \t o -> if not (t == "db" && not (String.startsWith "d" o)) then [] else
+ [ text "VNDB is an open wiki, it is often easier if you removed the spoilers yourself by "
+ , a [ href ("/" ++ o ++ "/edit") ] [ text " editing the entry" ]
+ , text ". You likely know more about this entry than our moderators, after all. "
+ , br [] []
+ , text "If you're not sure whether something is a spoiler or if you need help with editing, you can also report this issue on the "
+ , a [ href "/t/db" ] [ text "discussion board" ]
+ , text " so that others may be able to help you."
+ ]
+ }
+ , { label = "Incorrect information"
+ , vis = \t o -> t == "db" && not (String.startsWith "d" o)
+ , submit = False
+ , msg = \_ o ->
+ [ text "VNDB is an open wiki, you can correct the information in this database yourself by "
+ , a [ href ("/" ++ o ++ "/edit") ] [ text " editing the entry" ]
+ , text ". You likely know more about this entry than our moderators, after all. "
+ , br [] []
+ , text "If you need help with editing, you can also report this issue on the "
+ , a [ href "/t/db" ] [ text "discussion board" ]
+ , text " so that others may be able to help you."
+ ]
+ }
+ , { label = "Not a visual novel"
+ , vis = \t o -> t == "db" && String.startsWith "v" o
+ , submit = False
+ , msg = \_ _ ->
+ [ text "If you suspect that this entry does not adhere to our "
+ , a [ href "/d2#1" ] [ text "inclusion criteria" ]
+ , text ", please report it in "
+ , a [ href "/t2108" ] [ text "this thread" ]
+ , text ", so that other users have a chance to provide feedback before a moderator makes their final decision."
+ ]
+ }
+ , { label = "Does not belong here"
+ , vis = \t o -> t == "db" && not (String.startsWith "v" o || String.startsWith "d" o)
+ , submit = True
+ , msg = nomsg
+ }
+ , { label = "Duplicate entry"
+ , vis = \t o -> t == "db" && not (String.startsWith "d" o)
+ , submit = True
+ , msg = \_ _ -> [ text "Please include a link to the entry that this is a duplicate of." ]
+ }
+ , { label = "Other"
+ , vis = vis
+ , submit = True
+ , msg = nomsg
+ }
]
@@ -51,6 +130,10 @@ update msg (state,model) =
view : Model -> Html Msg
view (state,model) =
+ let
+ lst = List.filter (\l -> l.vis model.rtype model.object) reasons
+ cur = List.filter (\l -> l.label == model.reason) lst |> List.head |> Maybe.withDefault initial
+ in
form_ Submit (state == Api.Loading)
[ div [ class "mainbox" ]
[ h1 [] [ text "Submit report" ]
@@ -67,8 +150,9 @@ view (state,model) =
then text "We generally do not provide feedback on reports, but a moderator may decide to contact you for clarification."
else text "We generally do not provide feedback on reports, but you may leave your email address in the message if you wish to be available for clarification."
]
- , formField "reason::Reason" [ inputSelect "reason" model.reason Reason [style "width" "300px"] (("","-- Select --") :: List.map (\s->(s,s)) reasons) ]
- ] ++ if model.reason == "" then [] else
+ , formField "reason::Reason" [ inputSelect "reason" model.reason Reason [style "width" "300px"] <| List.map (\l->(l.label,l.label)) lst ]
+ , formField "" (cur.msg model.rtype model.object)
+ ] ++ if not cur.submit then [] else
[ formField "message::Message" [ inputTextArea "message" model.message Message [] ]
, formField "" [ submitButton "Submit" state True ]
]
diff --git a/lib/VNWeb/Discussions/Board.pm b/lib/VNWeb/Discussions/Board.pm
index edce6789..6262deaf 100644
--- a/lib/VNWeb/Discussions/Board.pm
+++ b/lib/VNWeb/Discussions/Board.pm
@@ -9,13 +9,10 @@ TUWF::get qr{/t/(all|$BOARD_RE)}, sub {
my $page = tuwf->validate(get => p => { upage => 1 })->data;
- my $obj = !$id ? undef :
- $type eq 'v' ? tuwf->dbRowi('SELECT id, title, original, hidden AS entry_hidden, locked AS entry_locked FROM vn WHERE id =', \$id) :
- $type eq 'p' ? tuwf->dbRowi('SELECT id, name, original, hidden AS entry_hidden, locked AS entry_locked FROM producers WHERE id =', \$id) :
- $type eq 'u' ? tuwf->dbRowi('SELECT id,', sql_user(), 'FROM users u WHERE id =', \$id) : undef;
+ my $obj = $id ? dbobj $type, $id : undef;
return tuwf->resNotFound if $id && !$obj->{id};
- my $ititle = $obj && ($obj->{title} || $obj->{name} || user_displayname $obj);
+ my $ititle = $obj && ($obj->{title} || user_displayname $obj);
my $title = $obj ? "Related discussions for $ititle" : $type eq 'all' ? 'All boards' : $BOARD_TYPE{$type}{txt};
my $createurl = '/t/'.($id ? $type.$id : $type eq 'db' ? 'db' : 'ge').'/new';
diff --git a/lib/VNWeb/Docs/Page.pm b/lib/VNWeb/Docs/Page.pm
index 6bf6ebfe..eeda0d00 100644
--- a/lib/VNWeb/Docs/Page.pm
+++ b/lib/VNWeb/Docs/Page.pm
@@ -46,6 +46,7 @@ TUWF::get qr{/$RE{drev}} => sub {
sub {
_rev_ $d if tuwf->capture('rev');
div_ class => 'mainbox', sub {
+ itemmsg_ d => $d;
h1_ $d->{title};
div_ class => 'docs', sub {
_index_;
diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm
index 46905887..91c13526 100644
--- a/lib/VNWeb/HTML.pm
+++ b/lib/VNWeb/HTML.pm
@@ -752,14 +752,19 @@ sub searchbox_ {
}
-# Generate a message to display on an entry page when the entry has been locked or the user can't edit it.
+# Generate a message to display on an entry page to report the entry and to indicate it has been locked or the user can't edit it.
sub itemmsg_ {
my($type, $obj) = @_;
- if($obj->{entry_locked}) {
- p_ class => 'locked', 'Locked for editing';
- } elsif(auth && !can_edit $type => $obj) {
- p_ class => 'locked', 'You can not edit this page';
- }
+ p_ class => 'itemmsg', sub {
+ if($type ne 'd') {
+ if($obj->{entry_locked}) {
+ txt_ 'Locked for editing. ';
+ } elsif(auth && !can_edit $type => $obj) {
+ txt_ 'You can not edit this page. ';
+ }
+ }
+ a_ href => "/report/db/$type$obj->{id}", 'Report an issue on this page.';
+ };
}
diff --git a/lib/VNWeb/Misc/History.pm b/lib/VNWeb/Misc/History.pm
index 26ef5f48..7ce5584f 100644
--- a/lib/VNWeb/Misc/History.pm
+++ b/lib/VNWeb/Misc/History.pm
@@ -170,19 +170,7 @@ sub filters_ {
TUWF::get qr{/(?:([upvrcsd])([1-9]\d*)/)?hist} => sub {
my($type, $id) = (tuwf->capture(1)||'', tuwf->capture(2));
- my sub dbitem {
- my($table, $title) = @_;
- tuwf->dbRowi('SELECT id,', $title, ' AS title, hidden AS entry_hidden, locked AS entry_locked FROM', $table, 'WHERE id =', \$id);
- };
-
- my $obj = !$type ? undef :
- $type eq 'u' ? tuwf->dbRowi('SELECT id, ', sql_user(), 'FROM users u WHERE id =', \$id) :
- $type eq 'p' ? dbitem producers => 'name' :
- $type eq 'v' ? dbitem vn => 'title' :
- $type eq 'r' ? dbitem releases => 'title' :
- $type eq 'c' ? dbitem chars => 'name' :
- $type eq 's' ? dbitem staff => '(SELECT name FROM staff_alias WHERE aid = staff.aid)' :
- $type eq 'd' ? dbitem docs => 'title' : die;
+ my $obj = dbobj $type, $id;
return tuwf->resNotFound if $type && !$obj->{id};
$obj->{title} = user_displayname $obj if $type eq 'u';
diff --git a/lib/VNWeb/Misc/Reports.pm b/lib/VNWeb/Misc/Reports.pm
index d229d434..fa1cbb44 100644
--- a/lib/VNWeb/Misc/Reports.pm
+++ b/lib/VNWeb/Misc/Reports.pm
@@ -16,16 +16,23 @@ sub enrich_object {
FROM threads t JOIN threads_posts tp ON tp.tid = t.id LEFT JOIN users u ON u.id = tp.uid
WHERE NOT t.hidden AND NOT t.private AND t.id =', \"$+{id}", 'AND tp.num =', \"$+{num}"
);
- if($post->{num}) {
- $o->{title} = xml_string sub {
- txt_ 'Post ';
- a_ href => "/$o->{object}", "#$post->{num}";
- txt_ ' on ';
- a_ href => "/$o->{object}", $post->{title};
- txt_ ' by ';
- user_ $post;
- };
- }
+ $o->{title} = xml_string sub {
+ txt_ 'Post ';
+ a_ href => "/$o->{object}", "#$post->{num}";
+ txt_ ' on ';
+ a_ href => "/$o->{object}", $post->{title};
+ txt_ ' by ';
+ user_ $post;
+ } if $post->{num};
+
+ } elsif($o->{rtype} eq 'db' && $o->{object} =~ /^([vrpcsd])$RE{num}$/) {
+ my($t,$id) = ($1, $+{num});
+ my $obj = dbobj $t, $id;
+ $o->{title} = xml_string sub {
+ txt_ {qw/v VN r Release p Producer c Character s Staff d Doc/}->{$t};
+ txt_ ': ';
+ a_ href => "/$t$id", $obj->{title};
+ } if $obj->{id};
}
}
}
@@ -63,7 +70,7 @@ elm_api Report => undef, $FORM, sub {
};
-TUWF::get qr{/report/(?<rtype>t)/(?<object>.+)}, sub {
+TUWF::get qr{/report/(?<rtype>t|db)/(?<object>.+)}, sub {
my $obj = { rtype => tuwf->capture('rtype'), object => tuwf->capture('object') };
enrich_object $obj;
return tuwf->resNotFound if !$obj->{title};
diff --git a/lib/VNWeb/Prelude.pm b/lib/VNWeb/Prelude.pm
index c79cc09b..50906792 100644
--- a/lib/VNWeb/Prelude.pm
+++ b/lib/VNWeb/Prelude.pm
@@ -72,6 +72,7 @@ sub import {
*{$c.'::RE'} = *RE;
*{$c.'::in'} = \&in;
*{$c.'::idcmp'} = \&idcmp;
+ *{$c.'::dbobj'} = \&dbobj;
}
@@ -122,4 +123,26 @@ sub idcmp($$) {
$a1 cmp $b1 || $a2 <=> $b2
}
+
+# Returns very generic information on a DB entry object.
+# Only { id, title, entry_hidden, entry_locked } for now.
+# Suitable for passing to HTML::framework_'s dbobj argument.
+sub dbobj {
+ my($type, $id) = @_;
+
+ my sub item {
+ my($table, $title) = @_;
+ tuwf->dbRowi('SELECT id,', $title, ' AS title, hidden AS entry_hidden, locked AS entry_locked FROM', $table, 'WHERE id =', \$id);
+ };
+
+ !$type ? undef :
+ $type eq 'u' ? tuwf->dbRowi('SELECT id, ', sql_user(), 'FROM users u WHERE id =', \$id) :
+ $type eq 'p' ? item producers => 'name' :
+ $type eq 'v' ? item vn => 'title' :
+ $type eq 'r' ? item releases => 'title' :
+ $type eq 'c' ? item chars => 'name' :
+ $type eq 's' ? item staff => '(SELECT name FROM staff_alias WHERE aid = staff.aid)' :
+ $type eq 'd' ? item docs => 'title' : die;
+}
+
1;
diff --git a/lib/VNWeb/Producers/Page.pm b/lib/VNWeb/Producers/Page.pm
index 65196e76..802218d6 100644
--- a/lib/VNWeb/Producers/Page.pm
+++ b/lib/VNWeb/Producers/Page.pm
@@ -159,7 +159,10 @@ TUWF::get qr{/$RE{prev}(?:/(?<tab>vn|rel))?}, sub {
},
sub {
rev_ $p if tuwf->capture('rev');
- div_ class => 'mainbox', sub { info_ $p };
+ div_ class => 'mainbox', sub {
+ itemmsg_ p => $p;
+ info_ $p;
+ };
div_ class => 'maintabs right', sub {
ul_ sub {
li_ mkclass(tabselected => $tab eq 'vn'), sub { a_ href => "/p$p->{id}/vn", 'Visual Novels' };
diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm
index 72ccbf6c..4ff6dbdd 100644
--- a/lib/VNWeb/VN/Page.pm
+++ b/lib/VNWeb/VN/Page.pm
@@ -322,6 +322,7 @@ sub infobox_useroptions_ {
sub infobox_ {
my($v) = @_;
div_ class => 'mainbox', sub {
+ itemmsg_ v => $v;
h1_ $v->{title};
h2_ class => 'alttitle', lang_attr($v->{c_olang}), $v->{original} if $v->{original};
diff --git a/sql/schema.sql b/sql/schema.sql
index c6027f61..c7effd9c 100644
--- a/sql/schema.sql
+++ b/sql/schema.sql
@@ -64,7 +64,7 @@ CREATE TYPE producer_type AS ENUM ('co', 'in', 'ng');
CREATE TYPE producer_relation AS ENUM ('old', 'new', 'sub', 'par', 'imp', 'ipa', 'spa', 'ori');
CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial');
CREATE TYPE report_status AS ENUM ('new', 'busy', 'done', 'dismissed');
-CREATE TYPE report_type AS ENUM ('t');
+CREATE TYPE report_type AS ENUM ('t', 'db');
CREATE TYPE tag_category AS ENUM('cont', 'ero', 'tech');
CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig');
CREATE TYPE session_type AS ENUM ('web', 'pass', 'mail');
diff --git a/util/updates/2020-07-25-report-db.sql b/util/updates/2020-07-25-report-db.sql
new file mode 100644
index 00000000..54dbd03d
--- /dev/null
+++ b/util/updates/2020-07-25-report-db.sql
@@ -0,0 +1,2 @@
+ALTER TYPE report_type ADD VALUE 'db' AFTER 't';
+