summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-02-28 17:01:34 +0100
committerYorhel <git@yorhel.nl>2020-02-28 17:23:25 +0100
commit255dc704f4675326ebf6358c79b5b37fca903e4b (patch)
treec813749b0227bd61e3eefc7e7ca563b915dbf918
parent3378afa6ac969f8f43b510e60d27561c69176eef (diff)
v2rw/RelEdit: Allow creating a new release
Not totally super happy with this solution; I'd rather automatically create an empty entry and send that to 'RelEdit.Main', but initializing all fields in Perl is tricky. At least in Elm we get some sort of type checking (though Elm can't tell whether the default value makes sense) and doing this in Elm makes it possible to initialize to something invalid that the user has to change (not currently done yet). It's messy either way.
-rw-r--r--elm/ReleaseEdit/Main.elm64
-rw-r--r--elm/ReleaseEdit/New.elm13
-rw-r--r--lib/VNDB/ExtLinks.pm4
-rw-r--r--lib/VNDB/Handler/Releases.pm2
-rw-r--r--lib/VNWeb/Elm.pm23
-rw-r--r--lib/VNWeb/Releases/Edit.pm92
6 files changed, 138 insertions, 60 deletions
diff --git a/elm/ReleaseEdit/Main.elm b/elm/ReleaseEdit/Main.elm
index a24d34fe..acab0825 100644
--- a/elm/ReleaseEdit/Main.elm
+++ b/elm/ReleaseEdit/Main.elm
@@ -1,4 +1,4 @@
-module ReleaseEdit.Main exposing (Model, Msg, main, view, update)
+module ReleaseEdit.Main exposing (Model, Msg, main, new, view, update, sub)
import Html exposing (..)
import Html.Events exposing (..)
@@ -26,7 +26,7 @@ main = Browser.element
{ init = \e -> (init e, Cmd.none)
, view = view
, update = update
- , subscriptions = \m -> Sub.batch [ DD.sub m.langDd, DD.sub m.platDd ]
+ , subscriptions = sub
}
@@ -67,6 +67,17 @@ type alias Model =
}
+engineConf : List GRE.RecvEngines -> A.Config Msg GRE.RecvEngines
+engineConf lst =
+ { wrap = Engine
+ , id = "engine"
+ , source =
+ { source = A.Func (\s -> List.filter (\e -> String.contains (String.toLower s) (String.toLower e.engine)) lst |> List.take 10)
+ , view = \i -> [ text i.engine, b [ class "grayedout" ] [ text <| " (" ++ String.fromInt i.count ++ ")" ] ]
+ , key = \i -> i.engine
+ }
+ }
+
init : GRE.Recv -> Model
init d =
{ state = Api.Normal
@@ -92,14 +103,9 @@ init d =
, ani_story = d.ani_story
, ani_ero = d.ani_ero
, website = d.website
- , engineConf = { wrap = Engine
- , id = "engine"
- , source = { source = A.Func (\s -> List.filter (\e -> String.contains (String.toLower s) (String.toLower e.engine)) d.engines |> List.take 10)
- , view = \i -> [ text i.engine, b [ class "grayedout" ] [ text <| " (" ++ String.fromInt i.count ++ ")" ] ]
- , key = \i -> i.engine }
- }
+ , engineConf = engineConf d.engines
, engine = A.init d.engine
- , extlinks = EL.new d.extlinks GEL.releaseLinks
+ , extlinks = EL.new d.extlinks GEL.releaseSites
, vn = d.vn
, vnAdd = A.init ""
, prod = d.producers
@@ -110,6 +116,44 @@ init d =
}
+new : GRE.New -> Model
+new d =
+ { state = Api.Normal
+ , title = d.title
+ , original = d.original
+ , rtype = "complete"
+ , patch = False
+ , freeware = False
+ , doujin = False
+ , lang = Set.empty
+ , langDd = DD.init "lang" LangOpen
+ , plat = Set.empty
+ , platDd = DD.init "platforms" PlatOpen
+ , media = []
+ , gtinInput = formatGtin 0
+ , gtin = 0
+ , catalog = ""
+ , released = 99999999 -- TODO: Would be nice to set this to 'unknown' and force the user to change it
+ , minage = -1
+ , uncensored = False
+ , resolution = "unknown"
+ , voiced = 0
+ , ani_story = 0
+ , ani_ero = 0
+ , website = ""
+ , engineConf = engineConf d.engines
+ , engine = A.init ""
+ , extlinks = EL.new GEL.releaseNew GEL.releaseSites
+ , vn = d.vn
+ , vnAdd = A.init ""
+ , prod = []
+ , prodAdd = A.init ""
+ , notes = TP.bbcode ""
+ , editsum = Editsum.new
+ , id = Nothing
+ }
+
+
encode : Model -> GRE.Send
encode model =
{ id = model.id
@@ -148,6 +192,8 @@ vnConfig = { wrap = VNSearch, id = "vnadd", source = A.vnSource }
producerConfig : A.Config Msg GApi.ApiProducerResult
producerConfig = { wrap = ProdSearch, id = "prodadd", source = A.producerSource }
+sub : Model -> Sub Msg
+sub m = Sub.batch [ DD.sub m.langDd, DD.sub m.platDd ]
type Msg
= Title String
diff --git a/elm/ReleaseEdit/New.elm b/elm/ReleaseEdit/New.elm
new file mode 100644
index 00000000..ac34be8c
--- /dev/null
+++ b/elm/ReleaseEdit/New.elm
@@ -0,0 +1,13 @@
+module ReleaseEdit.New exposing (main)
+
+import Browser
+import ReleaseEdit.Main as Main
+import Gen.ReleaseEdit as GRE
+
+main : Program GRE.New Main.Model Main.Msg
+main = Browser.element
+ { init = \n -> (Main.new n, Cmd.none)
+ , view = Main.view
+ , update = Main.update
+ , subscriptions = Main.sub
+ }
diff --git a/lib/VNDB/ExtLinks.pm b/lib/VNDB/ExtLinks.pm
index 4c8ea413..9f73b51d 100644
--- a/lib/VNDB/ExtLinks.pm
+++ b/lib/VNDB/ExtLinks.pm
@@ -304,7 +304,7 @@ sub validate_extlinks {
# Returns a list of sites for use in VNWeb::Elm:
-# { id => $id, name => $label, fmt => $label, regex => $regex, int => $bool, multi => $bool, default => 0||'""' }
+# { id => $id, name => $label, fmt => $label, regex => $regex, int => $bool, multi => $bool, default => 0||'""'||'[]' }
sub extlinks_sites {
my($type) = @_;
my($schema) = grep +($_->{dbentry_type}||'') eq $type, values VNDB::Schema::schema->%*;
@@ -313,7 +313,7 @@ sub extlinks_sites {
my($s) = grep $_->{name} eq $f, $schema->{cols}->@*;
+{ id => $_, name => $p->{label}, fmt => $p->{fmt}, regex => full_regex($p->{regex})
, int => $s->{type} =~ /^int/?1:0, multi => $s->{type} =~ /\[\]/?1:0
- , default => $s->{type} =~ /^int/?0:'""' }
+ , default => $s->{type} =~ /\[\]/ ? '[]' : $s->{type} =~ /^int/ ? 0 : '""' }
} sort grep $LINKS{$type}{$_}{regex}, keys $LINKS{$type}->%*
}
diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm
index fbdd0c9a..ef277f15 100644
--- a/lib/VNDB/Handler/Releases.pm
+++ b/lib/VNDB/Handler/Releases.pm
@@ -12,7 +12,7 @@ our @EXPORT = ('releaseExtLinks');
TUWF::register(
- qr{(v)([1-9]\d*)/add} => \&edit,
+ qr{old/(v)([1-9]\d*)/add} => \&edit,
qr{r} => \&browse,
qr{old/r(?:([1-9]\d*)(?:\.([1-9]\d*))?/(edit|copy))}
=> \&edit,
diff --git a/lib/VNWeb/Elm.pm b/lib/VNWeb/Elm.pm
index cf6409cb..355fbdc2 100644
--- a/lib/VNWeb/Elm.pm
+++ b/lib/VNWeb/Elm.pm
@@ -202,7 +202,7 @@ sub write_module {
# elm_api FormName => $OUT_SCHEMA, $IN_SCHEMA, sub {
# my($data) = @_;
# elm_Success # Or any other elm_Response() function
-# };
+# }, %extra_schemas;
#
# That will create an endpoint at `POST /elm/FormName.json` that accepts JSON
# data that must validate $IN_SCHEMA. The subroutine is given the validated
@@ -220,11 +220,12 @@ sub write_module {
# -- Command to send an API request to the endpoint and receive a response
# send : Send -> (Gen.Api.Response -> msg) -> Cmd msg
#
+# Extra type aliases can be added using %extra_schemas.
sub elm_api {
- my($name, $out, $in, $sub) = @_;
+ my($name, $out, $in, $sub, %extra) = @_;
- $in = ref $in eq 'HASH' ? tuwf->compile({ type => 'hash', keys => $in }) : $in;
- $out = ref $out eq 'HASH' ? tuwf->compile({ type => 'hash', keys => $out }) : $out;
+ my sub comp { ref $_[0] eq 'HASH' ? tuwf->compile({ type => 'hash', keys => $_[0] }) : $_[0] }
+ $in = comp $in;
TUWF::post qr{/elm/\Q$name\E\.json} => sub {
if(!auth->csrfcheck(tuwf->reqHeader('X-CSRF-Token')||'')) {
@@ -245,8 +246,9 @@ sub elm_api {
if(tuwf->{elmgen}) {
my $data = "import Gen.Api as GApi\n";
$data .= "import Lib.Api as Api\n";
- $data .= def_type Recv => $out->analyze if $out;
+ $data .= def_type Recv => comp($out)->analyze if $out;
$data .= def_type Send => $in->analyze;
+ $data .= def_type $_ => comp($extra{$_})->analyze for sort keys %extra;
$data .= def_validation val => $in->analyze;
$data .= encoder encode => 'Send', $in->analyze;
$data .= "send : Send -> (GApi.Response -> msg) -> Cmd msg\n";
@@ -352,8 +354,8 @@ sub write_extlinks {
my sub links {
my($name, $type, @links) = @_;
- def $name => "List (Site $type)" => list map {
- my($i,$l) = ($_, $links[$_]);
+ $data .= def $name.'Sites' => "List (Site $type)" => list map {
+ my $l = $_;
my $addval = $l->{int} ? 'toint v' : 'v';
'{ '.join("\n , ",
'name = '.string($l->{name}),
@@ -364,9 +366,12 @@ sub write_extlinks {
'del = (\i m -> { m | '.$l->{id}.' = '.($l->{multi} ? "delidx i m.$l->{id}" : $l->{default}).' })',
'add = (\v m -> { m | '.$l->{id}.' = '.($l->{multi} ? "m.$l->{id} ++ [$addval]" : $addval).' })'
)."\n }";
- } 0..$#links;
+ } @links;
+
+ $data .= def $name.'New' => $type =>
+ "\n { ".join("\n , ", map sprintf('%-10s = %s', $_->{id}, $_->{default}), @links)."\n }";
}
- $data .= links releaseLinks => 'GRE.RecvExtlinks' => VNDB::ExtLinks::extlinks_sites('r');
+ links release => 'GRE.RecvExtlinks' => VNDB::ExtLinks::extlinks_sites('r');
write_module ExtLinks => $data;
}
diff --git a/lib/VNWeb/Releases/Edit.pm b/lib/VNWeb/Releases/Edit.pm
index a292261d..f569e7b0 100644
--- a/lib/VNWeb/Releases/Edit.pm
+++ b/lib/VNWeb/Releases/Edit.pm
@@ -4,46 +4,46 @@ use VNWeb::Prelude;
my $FORM = {
- id => { required => 0, id => 1 },
- title => { maxlength => 250 },
- original => { required => 0, default => '', maxlength => 250 },
- rtype => { enum => \%RELEASE_TYPE },
- patch => { anybool => 1 },
- freeware => { anybool => 1 },
- doujin => { anybool => 1 },
- lang => { aoh => { lang => { enum => \%LANGUAGE } } },
- platforms => { aoh => { platform => { enum => \%PLATFORM } } },
- media => { aoh => {
+ id => { _when => 'in out', required => 0, id => 1 },
+ title => { _when => 'in out new', maxlength => 250 },
+ original => { _when => 'in out new', required => 0, default => '', maxlength => 250 },
+ rtype => { _when => 'in out', enum => \%RELEASE_TYPE },
+ patch => { _when => 'in out', anybool => 1 },
+ freeware => { _when => 'in out', anybool => 1 },
+ doujin => { _when => 'in out', anybool => 1 },
+ lang => { _when => 'in out', aoh => { lang => { enum => \%LANGUAGE } } },
+ platforms => { _when => 'in out', aoh => { platform => { enum => \%PLATFORM } } },
+ media => { _when => 'in out', aoh => {
medium => { enum => \%MEDIUM },
qty => { uint => 1, range => [0,20] },
} },
- gtin => { gtin => 1 },
- catalog => { required => 0, default => '', maxlength => 50 },
- released => { rdate => 1 },
- minage => { int => 1, enum => \%AGE_RATING },
- uncensored => { anybool => 1 },
- resolution => { enum => \%RESOLUTION },
- voiced => { uint => 1, enum => \%VOICED },
- ani_story => { uint => 1, enum => \%ANIMATED },
- ani_ero => { uint => 1, enum => \%ANIMATED },
- website => { required => 0, default => '', weburl => 1 },
- engine => { required => 0, default => '', maxlength => 50 },
- extlinks => validate_extlinks('r'),
- notes => { required => 0, default => '', maxlength => 10240 },
- vn => { sort_keys => 'vid', aoh => {
+ gtin => { _when => 'in out', gtin => 1 },
+ catalog => { _when => 'in out', required => 0, default => '', maxlength => 50 },
+ released => { _when => 'in out', min => 1, rdate => 1 },
+ minage => { _when => 'in out', int => 1, enum => \%AGE_RATING },
+ uncensored => { _when => 'in out', anybool => 1 },
+ resolution => { _when => 'in out', enum => \%RESOLUTION },
+ voiced => { _when => 'in out', uint => 1, enum => \%VOICED },
+ ani_story => { _when => 'in out', uint => 1, enum => \%ANIMATED },
+ ani_ero => { _when => 'in out', uint => 1, enum => \%ANIMATED },
+ website => { _when => 'in out', required => 0, default => '', weburl => 1 },
+ engine => { _when => 'in out', required => 0, default => '', maxlength => 50 },
+ extlinks => { _when => 'in out', validate_extlinks('r')->%* },
+ notes => { _when => 'in out', required => 0, default => '', maxlength => 10240 },
+ vn => { _when => 'in out new', sort_keys => 'vid', aoh => {
vid => { id => 1 },
- title => { _when => 'out' },
+ title => { _when => 'out new' },
} },
- producers => { sort_keys => 'pid', aoh => {
+ producers => { _when => 'in out', sort_keys => 'pid', aoh => {
pid => { id => 1 },
developer => { anybool => 1 },
publisher => { anybool => 1 },
name => { _when => 'out' },
} },
- hidden => { anybool => 1 },
- locked => { anybool => 1 },
+ hidden => { _when => 'in out', anybool => 1 },
+ locked => { _when => 'in out', anybool => 1 },
- engines => { _when => 'out', aoh => {
+ engines => { _when => 'out new', aoh => {
engine => {},
count => { uint => 1 },
} },
@@ -53,10 +53,18 @@ my $FORM = {
my $FORM_OUT = form_compile out => $FORM;
my $FORM_IN = form_compile in => $FORM;
+my $FORM_NEW = form_compile new => $FORM;
my $FORM_CMP = form_compile cmp => $FORM;
sub to_extlinks { $_[0]{extlinks} = { map +($_, delete $_[0]{$_}), grep /^l_/, keys $_[0]->%* } }
+sub engines {
+ tuwf->dbAlli(q{
+ SELECT engine, count(*) AS count FROM releases WHERE NOT hidden AND engine <> ''
+ GROUP BY engine ORDER BY count(*) DESC, engine
+ })
+}
+
TUWF::get qr{/$RE{rrev}/(?<action>edit|copy)} => sub {
my $e = db_entry r => tuwf->capture('id'), tuwf->capture('rev') or return tuwf->resNotFound;
my $copy = tuwf->capture('action') eq 'copy';
@@ -64,12 +72,9 @@ TUWF::get qr{/$RE{rrev}/(?<action>edit|copy)} => sub {
$e->{rtype} = delete $e->{type};
$e->{authmod} = auth->permDbmod;
- $e->{editsum} = $e->{chrev} == $e->{maxrev} ? '' : "Reverted to revision r$e->{id}.$e->{chrev}";
+ $e->{editsum} = $copy ? "Copied from r$e->{id}.$e->{chrev}" : $e->{chrev} == $e->{maxrev} ? '' : "Reverted to revision r$e->{id}.$e->{chrev}";
- $e->{engines} = tuwf->dbAlli(q{
- SELECT engine, count(*) AS count FROM releases WHERE NOT hidden AND engine <> ''
- GROUP BY engine ORDER BY count(*) DESC, engine
- });
+ $e->{engines} = engines;
to_extlinks $e;
enrich_merge vid => 'SELECT id AS vid, title FROM vn WHERE id IN', $e->{vn};
@@ -86,11 +91,20 @@ TUWF::get qr{/$RE{rrev}/(?<action>edit|copy)} => sub {
TUWF::get qr{/$RE{vid}/add}, sub {
return tuwf->resDenied if !can_edit r => undef;
- # TODO: Auto-fill some fields
- framework_ title => 'Add release',
+ my $v = tuwf->dbRowi('SELECT id, title, original FROM vn WHERE id =', \tuwf->capture('id'));
+ return tuwf->resNotFound if !$v->{id};
+
+ # TODO: List deleted releases
+ framework_ title => "Add release to $v->{title}",
sub {
- editmsg_ r => undef, 'Add release';
- elm_ 'ReleaseEdit.New';
+ editmsg_ r => undef, "Add release to $v->{title}";
+ elm_ 'ReleaseEdit.New' => $FORM_NEW, {
+ title => $v->{title},
+ original => $v->{original},
+ engines => engines(),
+ authmod => auth->permDbmod(),
+ vn => [{vid => $v->{id}, title => $v->{title}}],
+ };
};
};
@@ -123,7 +137,7 @@ elm_api ReleaseEdit => $FORM_OUT, $FORM_IN, sub {
my($id,undef,$rev) = db_edit r => $e->{id}, $data;
elm_Redirect "/r$id.$rev";
-};
+}, New => $FORM_NEW;
1;