diff options
author | Yorhel <git@yorhel.nl> | 2021-07-25 15:55:15 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2021-07-25 15:55:15 +0200 |
commit | 5ae9955a6016759355e1928372d1adff49c395ac (patch) | |
tree | dce4ac4165f1840933f10d9607fef50125603e5b | |
parent | 3fbc474ccc0f8c773e817397bb377961315929cb (diff) |
Merge UList.VNPage into Widget + add start/finish date to VN pages
-rw-r--r-- | css/v2.css | 1 | ||||
-rw-r--r-- | elm/UList/VNPage.elm | 166 | ||||
-rw-r--r-- | elm/UList/Widget.elm | 91 | ||||
-rw-r--r-- | lib/VNWeb/ULists/Elm.pm | 43 | ||||
-rw-r--r-- | lib/VNWeb/ULists/Lib.pm | 31 | ||||
-rw-r--r-- | lib/VNWeb/VN/Page.pm | 44 |
6 files changed, 143 insertions, 233 deletions
@@ -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 { |