summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2021-07-25 15:55:15 +0200
committerYorhel <git@yorhel.nl>2021-07-25 15:55:15 +0200
commit5ae9955a6016759355e1928372d1adff49c395ac (patch)
treedce4ac4165f1840933f10d9607fef50125603e5b
parent3fbc474ccc0f8c773e817397bb377961315929cb (diff)
Merge UList.VNPage into Widget + add start/finish date to VN pages
-rw-r--r--css/v2.css1
-rw-r--r--elm/UList/VNPage.elm166
-rw-r--r--elm/UList/Widget.elm91
-rw-r--r--lib/VNWeb/ULists/Elm.pm43
-rw-r--r--lib/VNWeb/ULists/Lib.pm31
-rw-r--r--lib/VNWeb/VN/Page.pm44
6 files changed, 143 insertions, 233 deletions
diff --git a/css/v2.css b/css/v2.css
index c6ae570e..3e2e3730 100644
--- a/css/v2.css
+++ b/css/v2.css
@@ -480,6 +480,7 @@ div.vndetails td.anime b { font-size: 10px; font-weight: normal; padding-ri
.ulistvn > b { font-size: 14px }
.ulistvn > span { float: right }
.ulistvn textarea { width: 100% }
+.ulistvn .date span:not(.spinner) { display: none }
div#vntags { margin: 0 30px 0 30px; border-top: 1px solid $border; padding: 3px 5% 0 5%; text-align: center; }
#vntags span { white-space: nowrap; margin-left: 15px; }
diff --git a/elm/UList/VNPage.elm b/elm/UList/VNPage.elm
index 53921388..96b3389b 100644
--- a/elm/UList/VNPage.elm
+++ b/elm/UList/VNPage.elm
@@ -1,125 +1,40 @@
+-- This is basically the same thing as UList.Widget, but with a slightly different UI.
+-- Release options are not available in this mode, as VN pages have a separate
+-- release listing anyway.
module UList.VNPage exposing (main)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Browser
-import Browser.Dom exposing (focus)
import Task
-import Process
-import Set
+import Date
import Lib.Html exposing (..)
import Lib.Util exposing (..)
import Lib.Api as Api
import Lib.DropDown as DD
-import Gen.Api as GApi
+import Gen.UListWidget as GUW
import Gen.UListVNNotes as GVN
-import Gen.UListDel as GDE
import UList.LabelEdit as LE
import UList.VoteEdit as VE
+import UList.DateEdit as DE
+import UList.Widget as UW
-main : Program GVN.VNPage Model Msg
+main : Program GUW.Recv UW.Model UW.Msg
main = Browser.element
- { init = \f -> (init f, Cmd.none)
- , subscriptions = \model -> Sub.batch [ Sub.map Labels (DD.sub model.labels.dd), Sub.map Vote (DD.sub model.vote.dd) ]
+ { init = \f -> (UW.init f, Date.today |> Task.perform UW.Today)
+ , subscriptions = \m -> Sub.batch
+ [ Sub.map UW.Label (DD.sub m.labels.dd)
+ , Sub.map UW.Vote (DD.sub m.vote.dd) ]
, view = view
- , update = update
+ , update = UW.update
}
-type alias Model =
- { flags : GVN.VNPage
- , onlist : Bool
- , del : Bool
- , state : Api.State -- For adding/deleting; Vote and label edit widgets have their own state
- , labels : LE.Model
- , vote : VE.Model
- , notes : String
- , notesRev : Int
- , notesState : Api.State
- , notesVis : Bool
- }
-
-init : GVN.VNPage -> Model
-init f =
- { flags = f
- , onlist = f.onlist
- , del = False
- , state = Api.Normal
- , labels = LE.init { uid = f.uid, vid = f.vid, labels = f.labels, selected = f.selected }
- , vote = VE.init { uid = f.uid, vid = f.vid, vote = f.vote }
- , notes = f.notes
- , notesRev = 0
- , notesState = Api.Normal
- , notesVis = f.notes /= ""
- }
-
-type Msg
- = Noop
- | Labels LE.Msg
- | Vote VE.Msg
- | NotesToggle
- | Notes String
- | NotesSave Int
- | NotesSaved Int GApi.Response
- | Del Bool
- | Delete
- | Deleted GApi.Response
-
-
-setOnList : Model -> Model
-setOnList model = { model | onlist = model.onlist || model.vote.ovote /= Nothing || not (Set.isEmpty model.labels.sel) || model.notes /= "" }
-
-update : Msg -> Model -> (Model, Cmd Msg)
-update msg model =
- case msg of
- Noop -> (model, Cmd.none)
- Labels m -> let (nm, cmd) = LE.update m model.labels in (setOnList { model | labels = nm}, Cmd.map Labels cmd)
- Vote m -> let (nm, cmd) = VE.update m model.vote in (setOnList { model | vote = nm}, Cmd.map Vote cmd)
-
- NotesToggle ->
- ( { model | notesVis = not model.notesVis }
- , if model.notesVis then Cmd.none else Task.attempt (always Noop) (focus "uvn_notes"))
- Notes s ->
- if s == model.notes then (model, Cmd.none)
- else ( { model | notes = s, notesRev = model.notesRev + 1 }
- , Task.perform (\_ -> NotesSave (model.notesRev+1)) <| Process.sleep 1000)
- NotesSave rev ->
- if rev /= model.notesRev || model.notes == model.flags.notes
- then (model, Cmd.none)
- else ( { model | notesState = Api.Loading }
- , GVN.send { uid = model.flags.uid, vid = model.flags.vid, notes = model.notes } (NotesSaved rev))
- NotesSaved rev GApi.Success ->
- let f = model.flags
- nf = { f | notes = model.notes }
- in if model.notesRev /= rev
- then (model, Cmd.none)
- else (setOnList {model | flags = nf, notesState = Api.Normal }, Cmd.none)
- NotesSaved _ e -> ({ model | notesState = Api.Error e }, Cmd.none)
-
- Del b -> ({ model | del = b }, Cmd.none)
- Delete -> ({ model | state = Api.Loading }, GDE.send { uid = model.flags.uid, vid = model.flags.vid } Deleted)
- Deleted GApi.Success ->
- ( { model
- | state = Api.Normal, onlist = False, del = False
- , labels = LE.init { uid = model.flags.uid, vid = model.flags.vid, labels = model.flags.labels, selected = [] }
- , vote = VE.init { uid = model.flags.uid, vid = model.flags.vid, vote = Nothing }
- , notes = "", notesVis = False
- }
- , Cmd.none)
- Deleted e -> ({ model | state = Api.Error e }, Cmd.none)
-
-isPublic : Model -> Bool
-isPublic model =
- LE.isPublic model.labels
- || (isJust model.vote.vote && List.any (\l -> l.id == 7 && not l.private) model.labels.labels)
-
-
-view : Model -> Html Msg
+view : UW.Model -> Html UW.Msg
view model =
- let canVote = model.flags.canvote || (Maybe.withDefault "-" model.flags.vote /= "-")
- notesBut =
- [ a [ href "#", onClickD NotesToggle ] [ text "💬" ]
+ let notesBut =
+ [ a [ href "#", onClickD UW.NotesToggle ] [ text "💬" ]
, span [ class "spinner", classList [("hidden", model.notesState /= Api.Loading)] ] []
, case model.notesState of
Api.Error e -> b [ class "standout" ] [ text <| Api.showResponse e ]
@@ -127,46 +42,29 @@ view model =
]
in
div [ class "ulistvn elm_dd_input" ]
- [ span [] <|
- case (model.state, model.del, model.onlist) of
- (Api.Loading, _, _) -> [ span [ class "spinner" ] [] ]
- (Api.Error e, _, _) -> [ b [ class "standout" ] [ text <| Api.showResponse e ] ]
- (Api.Normal, _, False) -> [ b [ class "grayedout" ] [ text "not on your list" ] ]
- (Api.Normal, True, _) ->
- [ a [ onClickD Delete ] [ text "Yes, delete" ]
- , text " | "
- , a [ onClickD (Del False) ] [ text "Cancel" ]
- ]
- (Api.Normal, False, True) ->
- [ span [ classList [("hidden", not (isPublic model))], title "This visual novel is on your public list" ] [ text "👁 " ]
- , text "On your list | "
- , a [ onClickD (Del True) ] [ text "Remove from list" ]
- ]
+ [ span [] (UW.viewStatus model)
, b [] [ text "User options" ]
- , table [ style "margin" "4px 0 0 0" ]
+ , table [ style "margin" "4px 0 0 0" ] <|
[ tr [ class "odd" ]
[ td [ class "key" ] [ text "My labels" ]
- , td [ colspan (if canVote then 2 else 1) ] [ Html.map Labels (LE.view model.labels "- select label -") ]
- , if canVote then text "" else td [] notesBut
+ , td [ colspan (if model.canvote then 2 else 1) ] [ Html.map UW.Label (LE.view model.labels "- select label -") ]
+ , if model.canvote then text "" else td [] notesBut
]
- , if canVote
+ , if model.canvote
then tr [ class "nostripe compact" ]
[ td [] [ text "My vote" ]
- , td [ style "width" "80px" ] [ Html.map Vote (VE.view model.vote "- vote -") ]
- , td [] <| notesBut ++
- [ case (model.vote.vote /= Nothing && model.flags.canreview, model.flags.review) of
- (False, _) -> text ""
- (True, Nothing) -> a [ href ("/" ++ model.flags.vid ++ "/addreview") ] [ text " write a review »" ]
- (True, Just w) -> a [ href ("/" ++ w ++ "/edit") ] [ text " edit review »" ]
- ]
- ]
- else text ""
- , if model.notesVis
- then tr [ class "nostripe compact" ]
- [ td [] [ text "Notes" ]
- , td [ colspan 2 ]
- [ textarea ([ id "uvn_notes", placeholder "Notes", rows 2, cols 30, onInput Notes, onBlur (NotesSave model.notesRev)] ++ GVN.valNotes) [ text model.notes ] ]
+ , td [ style "width" "80px" ] [ Html.map UW.Vote (VE.view model.vote "- vote -") ]
+ , td [] <| notesBut ++ [ UW.viewReviewLink model ]
]
else text ""
+ ] ++ if not model.notesVis then [] else
+ [ tr [ class "nostripe compact" ]
+ [ td [] [ text "Notes" ]
+ , td [ colspan 2 ]
+ [ textarea ([ id "widget-notes", placeholder "Notes", rows 2, cols 30, onInput UW.Notes, onBlur (UW.NotesSave model.notesRev)] ++ GVN.valNotes) [ text model.notes ] ]
+ ]
+ ] ++ if not model.onlist then [] else
+ [ tr [] [ td [] [ text "Start date" ], td [ colspan 2, class "date" ] [ Html.map UW.Started (DE.view model.started ) ] ]
+ , tr [] [ td [] [ text "Finish date" ], td [ colspan 2, class "date" ] [ Html.map UW.Finished (DE.view model.finished) ] ]
]
]
diff --git a/elm/UList/Widget.elm b/elm/UList/Widget.elm
index 3f56764e..105653b9 100644
--- a/elm/UList/Widget.elm
+++ b/elm/UList/Widget.elm
@@ -1,11 +1,16 @@
--- TODO: Integrate this with UList.VNPage and have this replace UList.Opt.
--- XXX: Only one widget can be instantiated per VN on a single page.
-module UList.Widget exposing (main)
+-- This module provides a ulist management widget. By default it shows as a
+-- small icon indicating the list status, which can be clicked on to open a
+-- full management modal for the VN.
+--
+-- It is also used by UList.VNPage to provide a different view for essentially
+-- the same functionality.
+module UList.Widget exposing (Model, Msg(..), main, init, update, viewStatus, viewReviewLink)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Browser
+import Browser.Dom exposing (focus)
import Task
import Process
import Set
@@ -57,6 +62,7 @@ type alias Model =
, notesRev : Int
, notesSaved : String
, notesState : Api.State
+ , notesVis : Bool -- For UList.VNPage
, started : DE.Model
, finished : DE.Model
, rels : List RE.Model
@@ -91,6 +97,7 @@ init f =
, notesRev = 0
, notesSaved = Maybe.map (\full -> full.notes ) f.full |> Maybe.withDefault ""
, notesState = Api.Normal
+ , notesVis = Maybe.map (\full -> full.notes /= "") f.full == Just True
, started = let m = DE.init { uid = f.uid, vid = f.vid, date = Maybe.map (\full -> full.started ) f.full |> Maybe.withDefault "", start = True } in { m | visible = True }
, finished = let m = DE.init { uid = f.uid, vid = f.vid, date = Maybe.map (\full -> full.finished) f.full |> Maybe.withDefault "", start = False } in { m | visible = True }
, rels = List.map (\st -> RE.init ("widget-" ++ f.vid) { uid = f.uid, rid = st.id, status = Just st.status, empty = "" }) <| Maybe.withDefault [] <| Maybe.map (\full -> full.rlist) f.full
@@ -98,9 +105,30 @@ init f =
, relOptions = Maybe.withDefault [] <| Maybe.map (\full -> List.map (\r -> (r.id, showrel r)) full.releases) f.full
}
+reset : Model -> Model
+reset m = init
+ { uid = m.uid
+ , vid = m.vid
+ , labels = Nothing
+ , full = Maybe.map (\t ->
+ { title = t
+ , labels = m.labels.labels
+ , canvote = m.canvote
+ , canreview = m.canreview
+ , vote = Nothing
+ , review = m.review
+ , notes = ""
+ , started = ""
+ , finished = ""
+ , releases = Dict.values m.relNfo
+ , rlist = []
+ }) m.title
+ }
+
type Msg
- = Today Date.Date
+ = Noop
+ | Today Date.Date
| Open Bool
| Loaded GApi.Response
| Label LE.Msg
@@ -108,6 +136,7 @@ type Msg
| Notes String
| NotesSave Int
| NotesSaved Int GApi.Response
+ | NotesToggle
| Started DE.Msg
| Finished DE.Msg
| Del Bool
@@ -142,6 +171,7 @@ showrel r = "[" ++ (RDate.format (RDate.expand r.released)) ++ " " ++ (String.jo
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
+ Noop -> (model, Cmd.none)
Today d -> ({ model | today = d }, Cmd.none)
Open b ->
if b && model.title == Nothing
@@ -169,10 +199,13 @@ update msg model =
then (model, Cmd.none)
else (setOnList {model | notesSaved = model.notes, notesState = Api.Normal }, Cmd.none)
NotesSaved _ e -> ({ model | notesState = Api.Error e }, Cmd.none)
+ NotesToggle ->
+ ( { model | notesVis = not model.notesVis }
+ , if model.notesVis then Cmd.none else Task.attempt (always Noop) (focus "widget-notes"))
Del b -> ({ model | del = b }, Cmd.none)
Delete -> ({ model | loadState = Api.Loading }, GDE.send { uid = model.uid, vid = model.vid } Deleted)
- Deleted GApi.Success -> (init { uid = model.uid, vid = model.vid, labels = Nothing, full = Nothing }, Cmd.none)
+ Deleted GApi.Success -> (reset model, Cmd.none)
Deleted e -> ({ model | loadState = Api.Error e }, Cmd.none)
Rel rid m ->
@@ -189,6 +222,32 @@ update msg model =
, Task.perform (always <| Rel rid <| RE.Set (Just 2) True) <| Task.succeed True)
+viewStatus : Model -> List (Html Msg)
+viewStatus model =
+ case (model.loadState, model.del, model.onlist) of
+ (Api.Loading, _, _) -> [ span [ class "spinner" ] [] ]
+ (Api.Error e, _, _) -> [ b [ class "standout" ] [ text <| Api.showResponse e ] ]
+ (_, _, False) -> [ b [ class "grayedout" ] [ text "not on your list" ] ]
+ (_, True, _) ->
+ [ a [ onClickD Delete ] [ text "Yes, delete" ]
+ , text " | "
+ , a [ onClickD (Del False) ] [ text "Cancel" ]
+ ]
+ (_, False, True) ->
+ [ span [ classList [("hidden", not (isPublic model))], title "This visual novel is on your public list" ] [ text "👁 " ]
+ , text "On your list | "
+ , a [ onClickD (Del True) ] [ text "Remove from list" ]
+ ]
+
+viewReviewLink : Model -> Html Msg
+viewReviewLink model =
+ case (model.vote.vote /= Nothing && model.canreview, model.review) of
+ (False, _) -> text ""
+ (True, Nothing) -> a [ href ("/" ++ model.vid ++ "/addreview") ] [ text " write a review »" ]
+ (True, Just w) -> a [ href ("/" ++ w ++ "/edit") ] [ text " edit review »" ]
+
+
+
view : Model -> Html Msg
view model =
let
@@ -221,31 +280,15 @@ view model =
box () =
[ h2 [] [ text (Maybe.withDefault "" model.title) ]
- , div [ style "text-align" "right", style "margin" "3px 0" ] <|
- case (model.del, model.onlist) of
- ( _, False) -> [ b [ class "grayedout" ] [ text "not on your list" ] ]
- (True, _) ->
- [ a [ onClickD Delete ] [ text "Yes, delete" ]
- , text " | "
- , a [ onClickD (Del False) ] [ text "Cancel" ]
- ]
- (False, True) ->
- [ span [ classList [("hidden", not (isPublic model))], title "This visual novel is on your public list" ] [ text "👁 " ]
- , text "On your list | "
- , a [ onClickD (Del True) ] [ text "Remove from list" ]
- ]
- , table []
+ , div [ style "text-align" "right", style "margin" "3px 0" ] (viewStatus model)
+ , table [] <|
[ tr [] [ td [] [ text "Labels" ], td [] [ Html.map Label (LE.view model.labels "- select label -") ] ]
, if not model.canvote then text "" else
tr []
[ td [] [ text "Vote" ]
, td []
[ div [ style "width" "80px", style "display" "inline-block" ] [ Html.map Vote (VE.view model.vote "- vote -") ]
- , case (model.vote.vote /= Nothing && model.canreview, model.review) of
- (False, _) -> text ""
- (True, Nothing) -> a [ href ("/" ++ model.vid ++ "/addreview") ] [ text " write a review »" ]
- (True, Just w) -> a [ href ("/" ++ w ++ "/edit") ] [ text " edit review »" ]
- ]
+ , viewReviewLink model ]
]
, tr [] [ td [] [ text "Start date" ], td [ class "date" ] [ Html.map Started (DE.view model.started ) ] ]
, tr [] [ td [] [ text "Finish date" ], td [ class "date" ] [ Html.map Finished (DE.view model.finished) ] ]
diff --git a/lib/VNWeb/ULists/Elm.pm b/lib/VNWeb/ULists/Elm.pm
index 0d9eeb06..c88156df 100644
--- a/lib/VNWeb/ULists/Elm.pm
+++ b/lib/VNWeb/ULists/Elm.pm
@@ -2,7 +2,6 @@ package VNWeb::ULists::Elm;
use VNWeb::Prelude;
use VNWeb::ULists::Lib;
-use VNWeb::Releases::Lib 'releases_by_vn';
# Should be called after any change to the ulist_* tables.
@@ -167,21 +166,7 @@ our $VNOPT = form_compile any => {
};
-our $VNPAGE = form_compile any => {
- uid => { vndbid => 'u' },
- vid => { vndbid => 'v' },
- onlist => { anybool => 1 },
- canvote => { anybool => 1 },
- vote => { vnvote => 1 },
- notes => { required => 0, default => '' },
- review => { required => 0, vndbid => 'w' },
- canreview=> { anybool => 1 },
- labels => { aoh => { id => { int => 1 }, label => {}, private => { anybool => 1 } } },
- selected => { type => 'array', values => { id => 1 } },
-};
-
-
-# UListVNNotes module is abused for the UList.Opts and UList.VNPage flag definition
+# UListVNNotes module is abused for the UList.Opts flag definition
elm_api UListVNNotes => $VNOPT, {
uid => { vndbid => 'u' },
vid => { vndbid => 'v' },
@@ -194,7 +179,7 @@ elm_api UListVNNotes => $VNOPT, {
);
# Doesn't need `updcache()`
elm_Success
-}, VNPage => $VNPAGE;
+};
@@ -241,29 +226,9 @@ our $WIDGET = form_compile out => $VNWeb::Elm::apis{UListWidget}[0]{keys};
elm_api UListWidget => $WIDGET, { uid => { vndbid => 'u' }, vid => { vndbid => 'v' } }, sub {
my($data) = @_;
return elm_Unauth if !ulists_own $data->{uid};
- my $v = tuwf->dbRowi('SELECT title, c_released FROM vn WHERE id =', \$data->{vid});
+ my $v = tuwf->dbRowi('SELECT id, title, c_released FROM vn WHERE id =', \$data->{vid});
return elm_Invalid if !defined $v->{title};
- my $lst = tuwf->dbRowi('SELECT vid, vote, notes, started, finished FROM ulist_vns WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
- my $review = tuwf->dbVali('SELECT id FROM reviews WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid});
- my $canvote = sprintf('%08d', $v->{c_released}||0) < strftime '%Y%m%d', gmtime;
- elm_UListWidget {
- uid => $data->{uid},
- vid => $data->{vid},
- labels => !$lst->{vid} ? undef : tuwf->dbAlli('SELECT lbl AS id, \'\' AS label FROM ulist_vns_labels WHERE uid =', \$data->{uid}, 'AND vid =', \$data->{vid}),
- full => {
- title => $v->{title},
- labels => tuwf->dbAlli('SELECT id, label, private FROM ulist_labels WHERE uid =', \$data->{uid}, 'ORDER BY CASE WHEN id < 10 THEN id ELSE 10 END, label'),
- canvote => $lst->{vote} || $canvote || 0,
- canreview => $review || ($canvote && can_edit(w => {})) || 0,
- vote => fmtvote($lst->{vote}),
- review => $review,
- notes => $lst->{notes}||'',
- started => $lst->{started}||'',
- finished => $lst->{finished}||'',
- releases => releases_by_vn($data->{vid}),
- rlist => tuwf->dbAlli('SELECT rid AS id, status FROM rlists WHERE uid =', \$data->{uid}, 'AND rid IN(SELECT id FROM releases_vn WHERE vid =', \$data->{vid}, ')'),
- },
- };
+ elm_UListWidget ulists_widget_full_data $v, $data->{uid};
};
diff --git a/lib/VNWeb/ULists/Lib.pm b/lib/VNWeb/ULists/Lib.pm
index b983a13c..766378c0 100644
--- a/lib/VNWeb/ULists/Lib.pm
+++ b/lib/VNWeb/ULists/Lib.pm
@@ -1,9 +1,10 @@
package VNWeb::ULists::Lib;
use VNWeb::Prelude;
+use VNWeb::Releases::Lib 'releases_by_vn';
use Exporter 'import';
-our @EXPORT = qw/ulists_own enrich_ulists_widget ulists_widget_/;
+our @EXPORT = qw/ulists_own enrich_ulists_widget ulists_widget_ ulists_widget_full_data/;
# Do we have "ownership" access to this users' list (i.e. can we edit and see private stuff)?
sub ulists_own {
@@ -38,4 +39,32 @@ sub ulists_widget_ {
} if auth;
}
+
+# Returns the data structure for the elm_UListWidget API response for the given VN.
+sub ulists_widget_full_data {
+ my($v, $uid, $vnpage) = @_;
+ my $lst = tuwf->dbRowi('SELECT vid, vote, notes, started, finished FROM ulist_vns WHERE uid =', \$uid, 'AND vid =', \$v->{id});
+ my $review = tuwf->dbVali('SELECT id FROM reviews WHERE uid =', \$uid, 'AND vid =', \$v->{id});
+ my $canvote = sprintf('%08d', $v->{c_released}||0) < strftime '%Y%m%d', gmtime;
+ +{
+ uid => $uid,
+ vid => $v->{id},
+ labels => !$lst->{vid} ? undef : tuwf->dbAlli('SELECT lbl AS id, \'\' AS label FROM ulist_vns_labels WHERE uid =', \$uid, 'AND vid =', \$v->{id}),
+ full => {
+ title => $vnpage ? '' : $v->{title},
+ labels => tuwf->dbAlli('SELECT id, label, private FROM ulist_labels WHERE uid =', \$uid, 'ORDER BY CASE WHEN id < 10 THEN id ELSE 10 END, label'),
+ canvote => $lst->{vote} || $canvote || 0,
+ canreview => $review || ($canvote && can_edit(w => {})) || 0,
+ vote => fmtvote($lst->{vote}),
+ review => $review,
+ notes => $lst->{notes}||'',
+ started => $lst->{started}||'',
+ finished => $lst->{finished}||'',
+ releases => $vnpage ? [] : releases_by_vn($v->{id}),
+ rlist => $vnpage ? [] : tuwf->dbAlli('SELECT rid AS id, status FROM rlists WHERE uid =', \$uid, 'AND rid IN(SELECT id FROM releases_vn WHERE vid =', \$v->{id}, ')'),
+ },
+ };
+
+}
+
1;
diff --git a/lib/VNWeb/VN/Page.pm b/lib/VNWeb/VN/Page.pm
index 7c4e3529..72187b4f 100644
--- a/lib/VNWeb/VN/Page.pm
+++ b/lib/VNWeb/VN/Page.pm
@@ -3,6 +3,7 @@ package VNWeb::VN::Page;
use VNWeb::Prelude;
use VNWeb::Releases::Lib;
use VNWeb::Images::Lib qw/image_flagging_display image_ enrich_image_obj/;
+use VNWeb::ULists::Lib 'ulists_widget_full_data';
use VNDB::Func 'fmtrating';
@@ -10,7 +11,7 @@ use VNDB::Func 'fmtrating';
# Also used by Chars::VNTab & Reviews::VNTab
sub enrich_vn {
my($v, $revonly) = @_;
- enrich_merge id => 'SELECT id, c_votecount FROM vn WHERE id IN', $v;
+ enrich_merge id => 'SELECT id, c_votecount, c_released FROM vn WHERE id IN', $v;
enrich_merge vid => 'SELECT id AS vid, title, original FROM vn WHERE id IN', $v->{relations};
enrich_merge aid => 'SELECT id AS aid, title_romaji, title_kanji, year, type, ann_id, lastfetch FROM anime WHERE id IN', $v->{anime};
enrich_extlinks v => $v;
@@ -319,39 +320,6 @@ sub infobox_tags_ {
}
-sub infobox_useroptions_ {
- my($v) = @_;
- return if !auth;
-
- my $labels = tuwf->dbAlli('
- SELECT l.id, l.label, l.private, uvl.vid IS NOT NULL as assigned
- FROM ulist_labels l
- LEFT JOIN ulist_vns_labels uvl ON uvl.uid = l.uid AND uvl.lbl = l.id AND uvl.vid =', \$v->{id}, '
- WHERE l.uid =', \auth->uid, '
- ORDER BY CASE WHEN l.id < 10 THEN l.id ELSE 10 END, l.label'
- );
- my $lst = tuwf->dbRowi('SELECT vid, vote, notes FROM ulist_vns WHERE uid =', \auth->uid, 'AND vid =', \$v->{id});
- my $review = tuwf->dbVali('SELECT id FROM reviews WHERE uid =', \auth->uid, 'AND vid =', \$v->{id});
-
- tr_ class => 'nostripe', sub {
- td_ colspan => 2, sub {
- elm_ 'UList.VNPage', $VNWeb::ULists::Elm::VNPAGE, {
- uid => auth->uid,
- vid => $v->{id},
- onlist => $lst->{vid}||0,
- canvote => canvote($v)||0,
- vote => fmtvote($lst->{vote}),
- notes => $lst->{notes}||'',
- review => $review,
- canreview=> $review || (canvote($v) && can_edit(w => {})) || 0,
- labels => $labels,
- selected => [ map $_->{id}, grep $_->{assigned}, @$labels ],
- };
- }
- }
-}
-
-
# Also used by Chars::VNTab & Reviews::VNTab
sub infobox_ {
my($v, $notags) = @_;
@@ -398,7 +366,13 @@ sub infobox_ {
infobox_affiliates_ $v;
infobox_anime_ $v;
- infobox_useroptions_ $v;
+
+ tr_ class => 'nostripe', sub {
+ td_ colspan => 2, sub {
+ elm_ 'UList.VNPage', $VNWeb::ULists::Elm::WIDGET,
+ ulists_widget_full_data $v, auth->uid, 1;
+ }
+ } if auth;
tr_ class => 'nostripe', sub {
td_ class => 'vndesc', colspan => 2, sub {