summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-07-19 10:53:48 +0200
committerYorhel <git@yorhel.nl>2020-07-19 10:55:06 +0200
commitd7767fa0f907e7b2a0a3d879d9000fa137bd81db (patch)
tree4c04045145cb43f95074a3dc03970c873ae262c4
parent2fd1910f7f6f1218f68c404d86b25a7831725b43 (diff)
Delete old VN edit form + some other unreferenced code
There's a lot more unreferenced code in VNDB::DB::*, but I'll not spend too much effort cleaning that up right now. All of it can be deleted in bulk at some point.
-rw-r--r--data/js/iv.js138
-rw-r--r--data/js/main.js7
-rw-r--r--data/js/vncast.js112
-rw-r--r--data/js/vnrel.js124
-rw-r--r--data/js/vnscr.js206
-rw-r--r--data/js/vnstaff.js123
-rw-r--r--data/style.css19
-rw-r--r--lib/VNDB/DB/Misc.pm19
-rw-r--r--lib/VNDB/DB/VN.pm77
-rw-r--r--lib/VNDB/Handler/VNEdit.pm541
-rw-r--r--lib/VNWeb/HTML.pm5
11 files changed, 7 insertions, 1364 deletions
diff --git a/data/js/iv.js b/data/js/iv.js
deleted file mode 100644
index 98889c5e..00000000
--- a/data/js/iv.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Simple image viewer widget. Usage:
- *
- * <a href="full_image.jpg" data-iv="{width}x{height}:{category}">..</a>
- *
- * Clicking on the above link will cause the image viewer to open
- * full_image.jpg. The {category} part can be empty or absent. If it is not
- * empty, next/previous links will show up to point to the other images within
- * the same category.
- *
- * ivInit() should be called when links with "data-iv" attributes are
- * dynamically added or removed from the DOM.
- */
-
-// Cache of image categories and the list of associated link objects. Used to
-// quickly generate the next/prev links.
-var cats;
-
-function init() {
- cats = {};
- var n = 0;
- var l = byName('a');
- for(var i=0;i<l.length;i++) {
- var o = l[i];
- if(o.getAttribute('data-iv') && o.id != 'ivprev' && o.id != 'ivnext') {
- n++;
- o.onclick = show;
- var cat = o.getAttribute('data-iv').split(':')[1];
- if(cat) {
- if(!cats[cat])
- cats[cat] = [];
- o.iv_i = cats[cat].length;
- cats[cat].push(o);
- }
- }
- }
-
- if(n && !byId('iv_view')) {
- addBody(tag('div', {id: 'iv_view','class':'hidden', onclick: function(ev) { ev.stopPropagation(); return true } },
- tag('b', {id:'ivimg'}, ''),
- tag('br', null),
- tag('a', {href:'#', id:'ivfull'}, ''),
- tag('a', {href:'#', onclick: close, id:'ivclose'}, 'close'),
- tag('a', {href:'#', onclick: show, id:'ivprev'}, '« previous'),
- tag('a', {href:'#', onclick: show, id:'ivnext'}, 'next »')
- ));
- addBody(tag('b', {id:'ivimgload','class':'hidden'}, 'Loading...'));
- }
-}
-
-// Find the next (dir=1) or previous (dir=-1) non-hidden link object for the category.
-function findnav(cat, i, dir) {
- for(var j=i+dir; j>=0 && j<cats[cat].length; j+=dir)
- if(!hasClass(cats[cat][j], 'hidden') && cats[cat][j].offsetWidth > 0 && cats[cat][j].offsetHeight > 0)
- return cats[cat][j];
- return 0
-}
-
-// fix properties of the prev/next links
-function fixnav(lnk, cat, i, dir) {
- var a = cat ? findnav(cat, i, dir) : 0;
- lnk.style.visibility = a ? 'visible' : 'hidden';
- lnk.href = a ? a.href : '#';
- lnk.iv_i = a ? a.iv_i : 0;
- lnk.setAttribute('data-iv', a ? a.getAttribute('data-iv') : '');
-}
-
-function show(ev) {
- var u = this.href;
- var opt = this.getAttribute('data-iv').split(':');
- var idx = this.iv_i;
- var view = byId('iv_view');
- var full = byId('ivfull');
-
- fixnav(byId('ivprev'), opt[1], idx, -1);
- fixnav(byId('ivnext'), opt[1], idx, 1);
-
- // calculate dimensions
- var w = Math.floor(opt[0].split('x')[0]);
- var h = Math.floor(opt[0].split('x')[1]);
- var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth;
- var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight;
- var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
- if(w+100 > ww || h+70 > wh) {
- full.href = u;
- setText(full, w+'x'+h);
- full.style.visibility = 'visible';
- if(w/h > ww/wh) { // width++
- h *= (ww-100)/w;
- w = ww-100;
- } else { // height++
- w *= (wh-70)/h;
- h = wh-70;
- }
- } else
- full.style.visibility = 'hidden';
- var dw = w;
- var dh = h+20;
- dw = dw < 200 ? 200 : dw;
-
- // update document
- setClass(view, 'hidden', false);
- setContent(byId('ivimg'), tag('img', {src:u, onclick:close,
- onload: function() { setClass(byId('ivimgload'), 'hidden', true); },
- style: 'width: '+w+'px; height: '+h+'px'
- }));
- view.style.width = dw+'px';
- view.style.height = dh+'px';
- view.style.left = ((ww - dw) / 2 - 10)+'px';
- view.style.top = ((wh - dh) / 2 + st - 20)+'px';
- byId('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px';
- byId('ivimgload').style.top = ((wh - 20) / 2 + st)+'px';
- setClass(byId('ivimgload'), 'hidden', false);
-
- document.onclick = close;
- // Capture left/right arrow keys
- document.onkeydown = function(e) {
- if(e.keyCode == 37 && byId('ivprev').style.visibility == 'visible') {
- byId('ivprev').click();
- }
- if(e.keyCode == 39 && byId('ivnext').style.visibility == 'visible') {
- byId('ivnext').click();
- }
- };
- ev.stopPropagation();
- return false;
-}
-
-function close() {
- document.onclick = null;
- document.onkeydown = null;
- setClass(byId('iv_view'), 'hidden', true);
- setClass(byId('ivimgload'), 'hidden', true);
- setText(byId('ivimg'), '');
- return false;
-}
-
-window.ivInit = init;
-init();
diff --git a/data/js/main.js b/data/js/main.js
index b04b02d0..f335f1f5 100644
--- a/data/js/main.js
+++ b/data/js/main.js
@@ -28,7 +28,6 @@ VARS.resolutions = [
//include lib.js
// Reusable widgets
-//include iv.js
//include dropdown.js
//include dateselector.js
//include dropdownsearch.js
@@ -38,12 +37,6 @@ VARS.resolutions = [
//include filter.js
//include misc.js
-// VN editing (/v+/edit)
-//include vnrel.js
-//include vnscr.js
-//include vnstaff.js
-//include vncast.js
-
// Producer editing (/p+/edit)
//include prodrel.js
diff --git a/data/js/vncast.js b/data/js/vncast.js
deleted file mode 100644
index 20d7fb39..00000000
--- a/data/js/vncast.js
+++ /dev/null
@@ -1,112 +0,0 @@
-function vncLoad() {
- var cast = jsonParse(byId('seiyuu').value) || [];
- var copt = byId('cast_chars').options;
- var chars = {};
- for(var i = 0; i < copt.length; i++) {
- if(copt[i].value)
- chars[copt[i].value] = copt[i].text;
- }
- cast.sort(function(a, b) {
- if(chars[a.cid] < chars[b.cid]) return -1;
- if(chars[a.cid] > chars[b.cid]) return 1;
- return 0;
- });
- for(var i = 0; i < cast.length; i++) {
- var aid = cast[i].aid;
- if(vnsStaffData[aid]) // vnsStaffData is filled by vnsLoad()
- vncAdd(vnsStaffData[aid], cast[i].cid, cast[i].note);
- }
- vncEmpty();
-
- onSubmit(byName(byId('maincontent'), 'form')[0], vncSerialize);
-
- // dropdown search
- dsInit(byId('cast_input'), '/xml/staff.xml?q=', function(item, tr) {
- tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 's'+item.getAttribute('sid')));
- tr.appendChild(tag('td', item.firstChild.nodeValue));
- tr.appendChild(tag('td', item.getAttribute('orig')));
- }, vncFormAdd);
-}
-
-function vncAdd(seiyuu, chr, note) {
- var tbl = byId('cast_tbl');
-
- var csel = byId('cast_chars').cloneNode(true);
- csel.removeAttribute('id');
- csel.value = chr;
-
- tbl.appendChild(tag('tr', {id:'vnc_a'+seiyuu.aid},
- tag('td', {'class':'tc_char'}, csel),
- tag('td', {'class':'tc_name'},
- tag('input', {type:'hidden', value:seiyuu.aid}),
- tag('a', {href:'/s'+seiyuu.id}, seiyuu.name)),
- tag('td', {'class':'tc_note'}, tag('input', {type:'text', 'class':'text', value:note})),
- tag('td', {'class':'tc_del'}, tag('a', {href:'#', onclick:vncDel}, 'remove'))
- ));
- vncEmpty();
- vncSerialize();
-}
-
-function vncFormAdd(item) {
- var chr = byId('cast_chars').value;
- if (chr) {
- var s = { id:item.getAttribute('sid'), aid:item.getAttribute('id'), name:item.firstChild.nodeValue };
- vncAdd(s, chr, '');
- } else
- alert('Select character first please.');
- return '';
-}
-
-function vncEmpty() {
- var x = byId('cast_loading');
- var tbody = byId('cast_tbl');
- var tbl = tbody.parentNode;
- var thead = byName(tbl, 'thead');
- if(x)
- tbody.removeChild(x);
- if(byName(tbody, 'tr').length < 1) {
- tbody.appendChild(tag('tr', {id:'cast_tr_none'},
- tag('td', {colspan:4}, 'None')));
- if (thead.length)
- tbl.removeChild(thead[0]);
- } else {
- if(byId('cast_tr_none'))
- tbody.removeChild(byId('cast_tr_none'));
- if (thead.length < 1) {
- thead = tag('thead', tag('tr',
- tag('td', {'class':'tc_char'}, 'Character'),
- tag('td', {'class':'tc_name'}, 'Seiyuu'),
- tag('td', {'class':'tc_note'}, 'Note'),
- tag('td', '')));
- tbl.insertBefore(thead, tbody);
- }
- }
-}
-
-function vncSerialize() {
- var l = byName(byId('cast_tbl'), 'tr');
- var c = [];
- for (var i = 0; i < l.length; i++) {
- if(l[i].id == 'cast_tr_none')
- continue;
- var aid = byName(byClass(l[i], 'tc_name')[0], 'input')[0];
- var role = byName(byClass(l[i], 'tc_char')[0], 'select')[0];
- var note = byName(byClass(l[i], 'tc_note')[0], 'input')[0];
- c.push({ aid:Number(aid.value), cid:Number(role.value), note:note.value });
- }
- byId('seiyuu').value = JSON.stringify(c);
- return true;
-}
-
-function vncDel() {
- var tr = this;
- while (tr.nodeName.toLowerCase() != 'tr')
- tr = tr.parentNode;
- byId('cast_tbl').removeChild(tr);
- vncEmpty();
- vncSerialize();
- return false;
-}
-
-if(byId('jt_box_vn_cast'))
- vncLoad();
diff --git a/data/js/vnrel.js b/data/js/vnrel.js
deleted file mode 100644
index 2ccb91bb..00000000
--- a/data/js/vnrel.js
+++ /dev/null
@@ -1,124 +0,0 @@
-function vnrLoad() {
- // read the current relations
- var rels = byId('vnrelations').value.split('|||');
- for(var i=0; i<rels.length && rels[0].length>1; i++) {
- var rel = rels[i].split(',');
- // fix for titles containing commas
- rel[3] = rel.splice(3).join();
- vnrAdd(rel[0], rel[1], rel[2]==1?true:false, rel[3]);
- }
- vnrEmpty();
-
- // make sure the title is up-to-date
- byId('title').onchange = function() {
- var l = byClass(byId('jt_box_vn_rel'), 'td', 'tc_title');
- for(i=0; i<l.length; i++)
- setText(l[i], shorten(this.value, 40));
- };
-
- // bind the add-link
- byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = vnrFormAdd;
-
- // dropdown
- dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_vn')[0], 'input')[0], '/xml/vn.xml?q=', function(item, tr) {
- tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id')));
- tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40)));
- }, function(item) {
- return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue;
- }, vnrFormAdd);
-}
-
-function vnrAdd(rel, vid, official, title) {
- var sel = tag('select', {onchange: vnrSerialize});
- var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options;
- for(var i=0; i<ops.length; i++)
- sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i])));
-
- byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid},
- tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))),
- tag('td', {'class':'tc_rel' },
- 'is an ',
- tag('input', {type: 'checkbox', onclick:vnrSerialize, id:'official_'+vid, checked:official}),
- tag('label', {'for':'official_'+vid}, 'official'),
- sel, ' of'),
- tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)),
- tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'remove'))
- ));
-
- vnrEmpty();
-}
-
-function vnrEmpty() {
- var tbl = byId('relation_tbl');
- if(byName(tbl, 'tr').length < 1)
- tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.')));
- else if(byId('relation_tr_none'))
- tbl.removeChild(byId('relation_tr_none'));
-}
-
-function vnrSerialize() {
- var r = [];
- var trs = byName(byId('relation_tbl'), 'tr');
- for(var i=0; i<trs.length; i++) {
- if(trs[i].id == 'relation_tr_none')
- continue;
- var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0];
- r[r.length] = [
- rel.options[rel.selectedIndex].value, // relation
- trs[i].id.substr(12), // vid
- byName(byClass(trs[i], 'td', 'tc_rel')[0], 'input')[0].checked ? '1' : '0', // official
- getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title
- ].join(',');
- }
- byId('vnrelations').value = r.join('|||');
-}
-
-function vnrDel() {
- var tr = this;
- while(tr.nodeName.toLowerCase() != 'tr')
- tr = tr.parentNode;
- byId('relation_tbl').removeChild(tr);
- vnrSerialize();
- vnrEmpty();
- return false;
-}
-
-function vnrFormAdd() {
- var relnew = byId('relation_new');
- var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0];
- var off = byName(byClass(relnew, 'td', 'tc_rel')[0], 'input')[0];
- var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0];
- var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0];
- var input = txt.value;
-
- if(!input.match(/^v[0-9]+/)) {
- alert('Visual novel textbox must start with an ID (e.g. v17)');
- return false;
- }
-
- txt.disabled = sel.disabled = off.disabled = true;
- txt.value = 'Loading...';
- setText(lnk, 'Loading...');
-
- ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) {
- txt.disabled = sel.disabled = off.disabled = false;
- txt.value = '';
- setText(lnk, 'add');
-
- var items = hr.responseXML.getElementsByTagName('item');
- if(items.length < 1)
- return alert('Visual novel not found!');
-
- var id = items[0].getAttribute('id');
- if(byId('relation_tr_'+id))
- return alert('This visual novel has already been selected!');
-
- vnrAdd(sel.options[sel.selectedIndex].value, id, off.checked, items[0].firstChild.nodeValue);
- sel.selectedIndex = 0;
- vnrSerialize();
- });
- return false;
-}
-
-if(byId('vnrelations'))
- vnrLoad();
diff --git a/data/js/vnscr.js b/data/js/vnscr.js
deleted file mode 100644
index bf583e15..00000000
--- a/data/js/vnscr.js
+++ /dev/null
@@ -1,206 +0,0 @@
-var rels;
-var defRid = 0;
-var staticUrl;
-
-function init() {
- var data = jsonParse(getText(byId('screendata'))) || {};
- rels = data.rel;
- rels.unshift([ 0, '-- select release --' ]);
- staticUrl = data.staticurl;
-
- var scr = jsonParse(byId('screenshots').value) || {};
- for(i=0; i<scr.length; i++) {
- var r = scr[i];
- var s = data.size[r.id];
- loaded(add(r.nsfw, r.rid), r.id, s[0], s[1]);
- }
-
- var frm = byId('screenshots');
- while(frm.nodeName.toLowerCase() != 'form')
- frm = frm.parentNode;
- onSubmit(frm, handleSubmit);
-
- addLast();
- ivInit();
-}
-
-function handleSubmit() {
- var loading = 0;
- var norelease = 0;
-
- var r = [];
- var l = byName(byId('scr_table'), 'tr');
- for(var i=0; i<l.length-1; i++)
- if(l[i].scr_loading)
- loading = 1;
- else if(l[i].scr_rid == 0)
- norelease = 1;
- else
- r.push({ rid: l[i].scr_rid, nsfw: l[i].scr_nsfw, id: l[i].scr_id });
-
- if(loading)
- alert('Please wait for the screenshots to be uploaded before submitting the form.');
- else if(norelease)
- alert('Please select the appropriate release for every screenshot.');
- else
- byId('screenshots').value = JSON.stringify(r);
- return !loading && !norelease;
-}
-
-function genRels(sel) {
- var r = tag('select', {'class':'scr_relsel'});
- for(var i=0; i<rels.length; i++)
- r.appendChild(tag('option', {value: rels[i][0], selected: rels[i][0] == sel}, rels[i][1]));
- return r;
-}
-
-function URL(id, t) {
- return staticUrl+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg';
-}
-
-// Need to run addLast() after this function
-function add(nsfw, rid) {
- var tr = tag('tr', { scr_id: 0, scr_loading: 1, scr_rid: rid, scr_nsfw: nsfw?1:0},
- tag('td', { 'class': 'thumb'}, 'Loading...'),
- tag('td',
- tag('b', 'Uploading screenshot'),
- tag('br', null),
- 'This can take a while, depending on the file size and your upload speed.',
- tag('br', null),
- tag('a', {href:'#', onclick:del}, 'cancel')
- )
- );
- byId('scr_table').appendChild(tr);
- return tr;
-}
-
-function oddDim(dim) {
- if(dim == '256x384') // special-case NDS resolution (not in the DB)
- return false;
- for(var j=0; j<VARS.resolutions.length; j++) {
- if(typeof VARS.resolutions[j][1] != 'object') {
- if(VARS.resolutions[j][0] == dim)
- return false;
- } else {
- for(var k=1; k<VARS.resolutions[j].length; k++)
- if(VARS.resolutions[j][k][1] == dim)
- return false;;
- }
- }
- return true;
-}
-
-// Need to run ivInit() after this function
-function loaded(tr, id, width, height) {
- var dim = width+'x'+height;
- tr.id = 'scr_tr_'+id;
- tr.scr_id = id;
- tr.scr_loading = 0;
-
- setContent(byName(tr, 'td')[0],
- tag('a', {href: URL(tr.scr_id, 'f'), 'data-iv':dim+':edit'},
- tag('img', {src: URL(tr.scr_id, 't')})
- )
- );
-
- var rel = genRels(tr.scr_rid);
- rel.onchange = function() { tr.scr_rid = this.options[this.selectedIndex].value };
-
- var nsfwid = 'scr_nsfw_'+id;
- setContent(byName(tr, 'td')[1],
- tag('b', 'Screenshot #'+id),
- ' (', tag('a', {href: '#', onclick:del}, 'remove'), ')',
- tag('br', null),
- 'Full size: '+dim,
- !oddDim(dim) ? null : tag('b', {'class':'standout', 'style':'font-weight: bold'},
- ' WARNING: Odd resolution! Please check whether the image has been cropped correctly.'),
- tag('br', null),
- tag('br', null),
- tag('input', {type:'checkbox', name:nsfwid, id:nsfwid, checked: tr.scr_nsfw!=0, onclick: function() { tr.scr_nsfw = this.checked?1:0 }, 'class':'scr_nsfw'}),
- tag('label', {'for':nsfwid}, 'This screenshot is NSFW'),
- tag('br', null),
- rel
- );
-}
-
-function addLast() {
- if(byId('scr_last'))
- byId('scr_table').removeChild(byId('scr_last'));
- var full = byName(byId('scr_table'), 'tr').length >= 10;
-
- var rel = genRels(defRid);
- rel.onchange = function() { defRid = this.options[this.selectedIndex].value };
- rel.id = 'scradd_relsel';
-
- byId('scr_table').appendChild(tag('tr', {id:'scr_last'},
- tag('td', {'class': 'thumb'}),
- full ? tag('td',
- tag('b', 'Enough screenshots'),
- tag('br', null),
- 'The limit of 10 screenshots per visual novel has been reached.\nIf you want to add a new screenshot, please remove an existing one first.'
- ) : tag('td',
- tag('b', 'Add screenshot'),
- tag('br', null),
- 'Image must be smaller than 5MB and in PNG or JPEG format.',
- tag('br', null),
- rel,
- tag('br', null),
- tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text', multiple:true}),
- tag('br', null),
- tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:upload})
- )
- ));
-}
-
-function del(what) {
- var tr = what && what.scr_id != null ? what : this;
- while(tr.scr_id == null)
- tr = tr.parentNode;
- if(tr.scr_ajax)
- tr.scr_ajax.abort();
- byId('scr_table').removeChild(tr);
- addLast();
- ivInit();
- return false;
-}
-
-function uploadFile(f) {
- var tr = add(0, defRid);
- var fname = f.name;
- var frm = new FormData();
- frm.append('file', f);
- tr.scr_ajax = ajax('/xml/screenshots.xml', function(hr) {
- tr.scr_ajax = null;
- var img = hr.responseXML.getElementsByTagName('image')[0];
- var id = img.getAttribute('id');
- if(id < 0) {
- alert(fname + ":\n" + (
- id == -1 ? 'Upload failed!\nOnly JPEG or PNG images are accepted.'
- : 'Upload failed!\nNo file selected, or an empty file?'));
- del(tr);
- } else {
- loaded(tr, id, img.getAttribute('width'), img.getAttribute('height'));
- ivInit();
- }
- }, true, frm);
-}
-
-function upload() {
- var files = byId('scr_upload').files;
-
- if(files.length < 1) {
- alert('Upload failed!\nNo file selected, or an empty file?');
- return false;
- } else if(files.length + byName(byId('scr_table'), 'tr').length - 1 > 10) {
- alert('Too many files selected. The total number of screenshots may not exceed 10.');
- return false;
- }
-
- for(var i=0; i<files.length; i++)
- uploadFile(files[i]);
- addLast();
- return false;
-}
-
-if(byId('jt_box_vn_scr') && byId('screenshots'))
- init();
diff --git a/data/js/vnstaff.js b/data/js/vnstaff.js
deleted file mode 100644
index 62e262e9..00000000
--- a/data/js/vnstaff.js
+++ /dev/null
@@ -1,123 +0,0 @@
-// vnsStaffData maps alias id to staff data { NNN: { id: ..., aid: NNN, name: ...} }
-// used to fill form fields instead of ajax queries in vnsLoad() and vncLoad()
-// Also used by vncast.js
-window.vnsStaffData = {};
-
-function vnsLoad() {
- window.vnsStaffData = jsonParse(getText(byId('staffdata'))) || {};
- var credits = jsonParse(byId('credits').value) || [];
- for(var i = 0; i < credits.length; i++) {
- var aid = credits[i].aid;
- if(window.vnsStaffData[aid])
- vnsAdd(window.vnsStaffData[aid], credits[i].role, credits[i].note);
- }
- vnsEmpty();
-
- onSubmit(byName(byId('maincontent'), 'form')[0], vnsCheckAndSerialize);
-
- // dropdown search
- dsInit(byId('credit_input'), '/xml/staff.xml?q=', function(item, tr) {
- tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 's'+item.getAttribute('sid')));
- tr.appendChild(tag('td', item.firstChild.nodeValue));
- tr.appendChild(tag('td', item.getAttribute('orig')));
- }, vnsFormAdd);
-}
-
-function vnsAdd(staff, role, note) {
- var tbl = byId('credits_tbl');
-
- var rlist = tag('select', {onchange:vnsSerialize});
- var r = VARS.credit_type;
- for (var i = 0; i<r.length; i++)
- rlist.appendChild(tag('option', {value:r[i][0], selected:r[i][0]==role}, r[i][1]));
-
- tbl.appendChild(tag('tr', {id:'vns_a'+staff.aid},
- tag('td', {'class':'tc_name'},
- tag('input', {type:'hidden', value:staff.aid}),
- tag('a', {href:'/s'+staff.id}, staff.name)),
- tag('td', {'class':'tc_role'}, rlist),
- tag('td', {'class':'tc_note'}, tag('input', {type:'text', 'class':'text', value:note})),
- tag('td', {'class':'tc_del'}, tag('a', {href:'#', onclick:vnsDel}, 'remove'))
- ));
- vnsEmpty();
- vnsSerialize();
-}
-
-function vnsEmpty() {
- var x = byId('credits_loading');
- var tbody = byId('credits_tbl');
- var tbl = tbody.parentNode;
- var thead = byName(tbl, 'thead');
- if(x)
- tbody.removeChild(x);
- if(byName(tbody, 'tr').length < 1) {
- tbody.appendChild(tag('tr', {id:'credits_tr_none'},
- tag('td', {colspan:4}, 'None')));
- if (thead.length)
- tbl.removeChild(thead[0]);
- } else {
- if(byId('credits_tr_none'))
- tbody.removeChild(byId('credits_tr_none'));
- if (thead.length < 1) {
- thead = tag('thead', tag('tr',
- tag('td', {'class':'tc_name'}, 'Staff'),
- tag('td', {'class':'tc_role'}, 'Credit'),
- tag('td', {'class':'tc_note'}, 'Note'),
- tag('td', '')));
- tbl.insertBefore(thead, tbody);
- }
- }
-}
-
-function vnsSerialize() {
- var l = byName(byId('credits_tbl'), 'tr');
- var c = [];
- for (var i = 0; i < l.length; i++) {
- if(l[i].id == 'credits_tr_none')
- continue;
- var aid = byName(byClass(l[i], 'tc_name')[0], 'input')[0];
- var role = byName(byClass(l[i], 'tc_role')[0], 'select')[0];
- var note = byName(byClass(l[i], 'tc_note')[0], 'input')[0];
- c.push({ aid:Number(aid.value), role:role.value, note:note.value });
- }
- byId('credits').value = JSON.stringify(c);
- return true;
-}
-
-function vnsCheckAndSerialize() {
- var l = byName(byId('credits_tbl'), 'tr');
- var tbl = {};
- for (var i = 0; i < l.length; i++) {
- if(l[i].id == 'credits_tr_none')
- continue;
- var aid = byName(byClass(l[i], 'tc_name')[0], 'input')[0];
- var name = byName(byClass(l[i], 'tc_name')[0], 'a')[0];
- var role = byName(byClass(l[i], 'tc_role')[0], 'select')[0];
- var idx = aid.value + ' ' + role.value;
- if(tbl[idx]) {
- alert("Invalid input in staff listing: '" + name.innerText + "' is credited multiple times with '" + role.options[role.selectedIndex].value + "'.");
- return false;
- }
- tbl[idx] = 1;
- }
- return vnsSerialize();
-}
-
-function vnsDel() {
- var tr = this;
- while (tr.nodeName.toLowerCase() != 'tr')
- tr = tr.parentNode;
- byId('credits_tbl').removeChild(tr);
- vnsEmpty();
- vnsSerialize();
- return false;
-}
-
-function vnsFormAdd(item) {
- var s = { id:item.getAttribute('sid'), aid:item.getAttribute('id'), name:item.firstChild.nodeValue };
- vnsAdd(s, 'staff', '');
- return '';
-}
-
-if(byId('jt_box_vn_staff'))
- vnsLoad();
diff --git a/data/style.css b/data/style.css
index 2c482e8c..81076de0 100644
--- a/data/style.css
+++ b/data/style.css
@@ -547,25 +547,6 @@ div#vntags { margin: 0 30px 0 30px; border-top: 1px solid $bo
/***** VN edit *****/
-#jt_box_vn_rel table { margin-bottom: 10px; }
-#jt_box_vn_rel h2 { margin: 0 0 3px 0px; }
-#jt_box_vn_rel td { padding: 1px 2px; vertical-align: middle; }
-#jt_box_vn_rel td.tc_vn { width: 300px; text-align: right }
-#jt_box_vn_rel td.tc_rel { width: 220px; white-space: nowrap }
-#jt_box_vn_rel td.tc_title { width: 200px; }
-#jt_box_vn_rel td.tc_add { width: 40px; text-align: right }
-#jt_box_vn_rel td.tc_vn input { width: 280px; }
-#jt_box_vn_rel td.tc_rel select { width: 130px; }
-
-#jt_box_vn_img div.img { float: left; height: 400px; padding-right: 20px; }
-#jt_box_vn_img h2 { margin: 0; }
-
-#jt_box_vn_scr table { width: 95% }
-#scr_table td { height: 108px; border-top: 1px solid #258; padding: 0; padding-right: 5px }
-#scr_table td.thumb { width: 136px; vertical-align: middle }
-#scr_table select { width: 400px; }
-div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; display: none; left: 0; top: 0; }
-
.vnedit_scr { width: 95%; margin: auto }
.vnedit_scr > tr:nth-child(odd) > td { background: $boxbg$ }
.vnedit_scr > tr > td { border-bottom: 1px solid $border$ }
diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm
index 3921db3a..2bd18c4c 100644
--- a/lib/VNDB/DB/Misc.pm
+++ b/lib/VNDB/DB/Misc.pm
@@ -6,7 +6,7 @@ use warnings;
use Exporter 'import';
our @EXPORT = qw|
- dbItemEdit dbRevisionGet dbWikidata dbImageAdd
+ dbItemEdit dbRevisionGet
|;
@@ -26,7 +26,7 @@ sub dbItemEdit {
exists($o{ilock}) ? ('ilock = ?' => $o{ilock}?1:0) : (),
});
- $self->dbVNRevisionInsert( \%o) if $type eq 'v';
+ die if $type ne 'p';
$self->dbProducerRevisionInsert(\%o) if $type eq 'p';
return $self->dbRow('SELECT * FROM edit_!s_commit()', $type);
@@ -96,20 +96,5 @@ sub dbRevisionGet {
return wantarray ? ($r, $np) : $r;
}
-
-# Returns a row from wikidata
-sub dbWikidata {
- return $_[0]->dbRow('SELECT * FROM wikidata WHERE id = ?', $_[1]);
-}
-
-
-# insert a new image and return its ID
-sub dbImageAdd {
- my($s, $type, $width, $height) = @_;
- my $seq = {qw/sf screenshots_seq cv covers_seq ch charimg_seq/}->{$type}||die;
- return $s->dbRow(q|INSERT INTO images (id, width, height) VALUES (vndbid(?, nextval(?)::int), ?, ?) RETURNING vndbid_num(id) as id|, $type, $seq, $width, $height)->{id};
-}
-
-
1;
diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm
index 6061c57c..734ae69b 100644
--- a/lib/VNDB/DB/VN.pm
+++ b/lib/VNDB/DB/VN.pm
@@ -9,13 +9,13 @@ use POSIX 'strftime';
use Exporter 'import';
use VNDB::Func 'normalize_query', 'gtintype';
-our @EXPORT = qw|dbVNGet dbVNGetRev dbVNRevisionInsert dbScreenshotGet dbScreenshotRandom|;
+our @EXPORT = qw|dbVNGet dbVNGetRev dbScreenshotRandom|;
# Options: id, char, search, gtin, length, lang, olang, plat, tag_inc, tag_exc, tagspoil,
# hasani, hasshot, ul_notblack, ul_onwish, results, page, what, sort,
# reverse, inc_hidden, date_before, date_after, released, release, character
-# What: extended anime staff seiyuu relations screenshots rating ranking vnlist
+# What: extended anime staff seiyuu relations rating ranking vnlist
# Note: vnlist is ignored (no db search) unless a user is logged in
# Sort: id rel pop rating title tagscore rand
sub dbVNGet {
@@ -111,7 +111,7 @@ sub dbVNGet {
my @select = ( # see https://rt.cpan.org/Ticket/Display.html?id=54224 for the cast on c_languages and c_platforms
qw|v.id v.locked v.hidden v.c_released v.c_languages::text[] v.c_olang::text[] v.c_platforms::text[] v.title v.original|,
$o{what} =~ /extended/ ? (
- qw|v.alias v.img_nsfw v.length v.desc v.l_wp v.l_encubed v.l_renai v.l_wikidata|, 'coalesce(vndbid_num(v.image),0) as image' ) : (),
+ qw|v.alias v.length v.desc v.l_wp v.l_encubed v.l_renai v.l_wikidata|, 'coalesce(vndbid_num(v.image),0) as image' ) : (),
$o{what} =~ /rating/ ? (qw|v.c_popularity v.c_rating v.c_votecount|) : (),
$o{what} =~ /ranking/ ? (
'(SELECT COUNT(*)+1 FROM vn iv WHERE iv.hidden = false AND iv.c_popularity > COALESCE(v.c_popularity, 0.0)) AS p_ranking',
@@ -159,7 +159,7 @@ sub dbVNGetRev {
my $select = 'c.itemid AS id, vo.c_released, vo.c_languages::text[], vo.c_olang::text[], vo.c_platforms::text[], v.title, v.original';
$select .= ', extract(\'epoch\' from c.added) as added, c.comments, c.rev, c.ihid, c.ilock, '.VNWeb::DB::sql_user();
$select .= ', c.id AS cid, NOT EXISTS(SELECT 1 FROM changes c2 WHERE c2.type = c.type AND c2.itemid = c.itemid AND c2.rev = c.rev+1) AS lastrev';
- $select .= ', v.alias, coalesce(vndbid_num(v.image), 0) as image, v.img_nsfw, v.length, v.desc, v.l_wp, v.l_encubed, v.l_renai, v.l_wikidata, vo.hidden, vo.locked' if $o{what} =~ /extended/;
+ $select .= ', v.alias, coalesce(vndbid_num(v.image), 0) as image, v.length, v.desc, v.l_wp, v.l_encubed, v.l_renai, v.l_wikidata, vo.hidden, vo.locked' if $o{what} =~ /extended/;
$select .= ', vo.c_popularity, vo.c_rating, vo.c_votecount' if $o{what} =~ /rating/;
$select .= ', (SELECT COUNT(*)+1 FROM vn iv WHERE iv.hidden = false AND iv.c_popularity > COALESCE(vo.c_popularity, 0.0)) AS p_ranking'
.', (SELECT COUNT(*)+1 FROM vn iv WHERE iv.hidden = false AND iv.c_rating > COALESCE(vo.c_rating, 0.0)) AS r_ranking' if $o{what} =~ /ranking/;
@@ -181,14 +181,13 @@ sub dbVNGetRev {
sub _enrich {
my($self, $r, $np, $rev, $what) = @_;
- if(@$r && $what =~ /anime|relations|screenshots|staff|seiyuu/) {
+ if(@$r && $what =~ /anime|relations|staff|seiyuu/) {
my($col, $hist, $colname) = $rev ? ('cid', '_hist', 'chid') : ('id', '', 'id');
my %r = map {
$r->[$_]{anime} = [];
$r->[$_]{credits} = [];
$r->[$_]{seiyuu} = [];
$r->[$_]{relations} = [];
- $r->[$_]{screenshots} = [];
($r->[$_]{$col}, $_)
} 0..$#$r;
@@ -241,17 +240,6 @@ sub _enrich {
[ keys %r ]
)});
}
-
- if($what =~ /screenshots/) {
- push(@{$r->[$r{ delete $_->{xid} }]{screenshots}}, $_) for (@{$self->dbAll("
- SELECT vs.$colname AS xid, vndbid_num(s.id) as id, vs.nsfw, vs.rid, s.width, s.height
- FROM vn_screenshots$hist vs
- JOIN images s ON vs.scr = s.id
- WHERE vs.$colname IN(!l)
- ORDER BY vs.scr",
- [ keys %r ]
- )});
- }
}
VNWeb::DB::enrich_flatten(vnlist_labels => id => vid => sub { VNWeb::DB::sql('
@@ -266,61 +254,6 @@ sub _enrich {
}
-# Updates the edit_* tables, used from dbItemEdit()
-# Arguments: { columns in producers_rev + anime + relations + screenshots }
-# screenshots = [ [ scrid, nsfw, rid ], .. ]
-# relations = [ [ rel, vid ], .. ]
-# anime = [ aid, .. ]
-sub dbVNRevisionInsert {
- my($self, $o) = @_;
-
- $o->{img_nsfw} = $o->{img_nsfw}?1:0 if exists $o->{img_nsfw};
- my %set = map exists($o->{$_}) ? (qq|"$_" = ?| => $o->{$_}) : (),
- qw|title original desc alias img_nsfw length l_wp l_encubed l_renai l_wikidata|;
- $set{'image = vndbid(\'cv\',?)'} = $o->{image}||undef if exists $o->{image};
- $self->dbExec('UPDATE edit_vn !H', \%set) if keys %set;
-
- if($o->{screenshots}) {
- $self->dbExec('DELETE FROM edit_vn_screenshots');
- my $q = join ',', map '(vndbid(\'sf\', ?), ?, ?)', @{$o->{screenshots}};
- my @val = map +($_->{id}, $_->{nsfw}?1:0, $_->{rid}), @{$o->{screenshots}};
- $self->dbExec("INSERT INTO edit_vn_screenshots (scr, nsfw, rid) VALUES $q", @val) if @val;
- }
-
- if($o->{relations}) {
- $self->dbExec('DELETE FROM edit_vn_relations');
- my $q = join ',', map '(?, ?, ?)', @{$o->{relations}};
- my @val = map +($_->[1], $_->[0], $_->[2]?1:0), @{$o->{relations}};
- $self->dbExec("INSERT INTO edit_vn_relations (vid, relation, official) VALUES $q", @val) if @val;
- }
-
- if($o->{anime}) {
- $self->dbExec('DELETE FROM edit_vn_anime');
- my $q = join ',', map '(?)', @{$o->{anime}};
- $self->dbExec("INSERT INTO edit_vn_anime (aid) VALUES $q", @{$o->{anime}}) if @{$o->{anime}};
- }
-
- if($o->{credits}) {
- $self->dbExec('DELETE FROM edit_vn_staff');
- my $q = join ',', ('(?, ?, ?)') x @{$o->{credits}};
- my @val = map +($_->{aid}, $_->{role}, $_->{note}), @{$o->{credits}};
- $self->dbExec("INSERT INTO edit_vn_staff (aid, role, note) VALUES $q", @val) if @val;
- }
-
- if($o->{seiyuu}) {
- $self->dbExec('DELETE FROM edit_vn_seiyuu');
- my $q = join ',', ('(?, ?, ?)') x @{$o->{seiyuu}};
- my @val = map +($_->{aid}, $_->{cid}, $_->{note}), @{$o->{seiyuu}};
- $self->dbExec("INSERT INTO edit_vn_seiyuu (aid, cid, note) VALUES $q", @val) if @val;
- }
-}
-
-
-# arrayref of screenshot IDs as argument
-sub dbScreenshotGet {
- return shift->dbAll(q|SELECT vndbid_num(id) AS id, width, height FROM images WHERE id IN(SELECT vndbid('sf', n::integer) FROM unnest(ARRAY[!l]) x(n))|, shift);
-}
-
# Fetch random VN + screenshots
# if any arguments are given, it will return one random screenshot for each VN
diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm
deleted file mode 100644
index 4c0a4737..00000000
--- a/lib/VNDB/Handler/VNEdit.pm
+++ /dev/null
@@ -1,541 +0,0 @@
-
-package VNDB::Handler::VNEdit;
-
-use strict;
-use warnings;
-use TUWF ':html', ':xml';
-use Image::Magick;
-use VNDB::Func;
-use VNDB::Types;
-
-
-TUWF::register(
- qr{old/v(?:([1-9]\d*)(?:\.([1-9]\d*))?/edit|/new)}
- => \&edit,
- qr{old/v/add} => \&addform,
- qr{xml/vn\.xml} => \&vnxml,
- qr{xml/screenshots\.xml} => \&scrxml,
-);
-
-
-sub addform {
- my $self = shift;
- return $self->htmlDenied if !$self->authCan('edit');
-
- my $frm;
- my $l = [];
- if($self->reqMethod eq 'POST') {
- return if !$self->authCheckCode;
- $frm = $self->formValidate(
- { post => 'title', maxlength => 250 },
- { post => 'original', required => 0, maxlength => 250, default => '' },
- { post => 'alias', required => 0, maxlength => 500, default => '' },
- { post => 'continue_ign',required => 0 },
- );
-
- # look for duplicates
- if(!$frm->{_err} && !$frm->{continue_ign}) {
- $l = $self->dbVNGet(search => $frm->{title}, what => 'changes', results => 50, inc_hidden => 1);
- push @$l, @{$self->dbVNGet(search => $frm->{original}, what => 'changes', results => 50, inc_hidden => 1)} if $frm->{original};
- $_ && push @$l, @{$self->dbVNGet(search => $_, what => 'changes', results => 50, inc_hidden => 1)} for(split /\n/, $frm->{alias});
- my %ids = map +($_->{id}, $_), @$l;
- $l = [ map $ids{$_}, sort { $ids{$a}{title} cmp $ids{$b}{title} } keys %ids ];
- }
-
- return edit($self, undef, undef, 1) if !@$l && !$frm->{_err};
- }
-
- $self->htmlHeader(title => 'Add a new visual novel', noindex => 1);
- if(@$l) {
- div class => 'mainbox';
- h1 'Possible duplicates found';
- div class => 'warning';
- p;
- txt 'The following is a list of visual novels that match the title(s) you gave.'
- .' Please check this list to avoid creating a duplicate visual novel entry.'
- .' Be especially wary of items that have been deleted! To see why an entry has been deleted, click on its title.';
- br; br;
- txt 'To add the visual novel anyway, hit the "Continue and ignore duplicates" button below.';
- end;
- end;
- ul;
- for(@$l) {
- li;
- a href => "/v$_->{id}", title => $_->{original}||$_->{title}, "v$_->{id}: ".shorten($_->{title}, 50);
- b class => 'standout', ' deleted' if $_->{hidden};
- end;
- }
- end;
- end 'div';
- }
-
- $self->htmlForm({ frm => $frm, action => '/old/v/add', continue => @$l ? 2 : 1 },
- vn_add => [ 'Add a new visual novel',
- [ input => short => 'title', name => 'Title (romaji)', width => 450 ],
- [ input => short => 'original', name => 'Original title', width => 450 ],
- [ static => content => 'The original title of this visual novel, leave blank if it already is in the Latin alphabet.' ],
- [ textarea => short => 'alias', name => 'Aliases', rows => 4 ],
- [ static => content => 'List of alternative titles or abbreviations. One line for each alias.' ],
- ]);
- $self->htmlFooter;
-}
-
-
-sub edit {
- my($self, $vid, $rev, $nosubmit) = @_;
-
- my $v = $vid && $self->dbVNGetRev(id => $vid, what => 'extended screenshots relations anime staff seiyuu changes', $rev ? (rev => $rev) : ())->[0];
- return $self->resNotFound if $vid && !$v->{id};
- $rev = undef if !$vid || $v->{lastrev};
-
- return $self->htmlDenied if !$self->authCan('edit')
- || $vid && (($v->{locked} || $v->{hidden}) && !$self->authCan('dbmod'));
-
- my $r = $v ? $self->dbReleaseGet(vid => $v->{id}) : [];
- my $chars = $v ? $self->dbCharGet(vid => $v->{id}, results => 500) : [];
-
- my %b4 = !$vid ? () : (
- (map { $_ => $v->{$_} } qw|title original desc alias length l_renai l_wikidata image img_nsfw ihid ilock|),
- credits => [
- map { my $c = $_; +{ map { $_ => $c->{$_} } qw|aid role note| } }
- sort { $a->{aid} <=> $b->{aid} || $a->{role} cmp $b->{role} } @{$v->{credits}}
- ],
- seiyuu => [
- map { my $c = $_; +{ map { $_ => $c->{$_} } qw|aid cid note| } }
- sort { $a->{aid} <=> $b->{aid} || $a->{cid} <=> $b->{cid} } @{$v->{seiyuu}}
- ],
- anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}),
- vnrelations => join('|||', map $_->{relation}.','.$_->{id}.','.($_->{official}?1:0).','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}),
- screenshots => [
- map +{ id => $_->{id}, nsfw => $_->{nsfw}?1:0, rid => $_->{rid} },
- sort { $a->{id} <=> $b->{id} } @{$v->{screenshots}}
- ]
- );
-
- my $frm;
- if($self->reqMethod eq 'POST') {
- return if !$nosubmit && !$self->authCheckCode;
- $frm = $self->formValidate(
- { post => 'title', maxlength => 250 },
- { post => 'original', required => 0, maxlength => 250, default => '' },
- { post => 'alias', required => 0, maxlength => 500, default => '' },
- { post => 'desc', required => 0, default => '', maxlength => 10240 },
- { post => 'length', required => 0, default => 0, enum => [ keys %VN_LENGTH ] },
- { post => 'l_renai', required => 0, default => '', maxlength => 100 },
- { post => 'l_wikidata', required => 0, template => 'wikidata' },
- { post => 'anime', required => 0, default => '' },
- { post => 'image', required => 0, default => 0, template => 'id' },
- { post => 'img_nsfw', required => 0, default => 0 },
- { post => 'credits', required => 0, template => 'json', json_unique => ['aid','role'], json_sort => ['aid','role'], json_fields => [
- { field => 'aid', required => 1, template => 'id' },
- { field => 'role', required => 1, enum => [ keys %CREDIT_TYPE ] },
- { field => 'note', required => 0, maxlength => 250, default => '' },
- ]},
- { post => 'seiyuu', required => 0, template => 'json', json_unique => ['aid','cid'], json_sort => ['aid','cid'], json_fields => [
- { field => 'aid', required => 1, template => 'id' },
- { field => 'cid', required => 1, template => 'id' },
- { field => 'note', required => 0, maxlength => 250, default => '' },
- ]},
- { post => 'vnrelations', required => 0, default => '', maxlength => 5000 },
- { post => 'screenshots', required => 0, template => 'json', json_maxitems => 10, json_unique => 'id', json_sort => 'id', json_fields => [
- { field => 'id', required => 1, template => 'id' },
- { field => 'rid', required => 1, template => 'id' },
- { field => 'nsfw', required => 1, template => 'uint', enum => [0,1] },
- ]},
- { post => 'editsum', required => !$nosubmit, template => 'editsum' },
- { post => 'ihid', required => 0 },
- { post => 'ilock', required => 0 },
- );
- $frm->{original} = '' if $frm->{original} eq $frm->{title};
-
- # handle image upload
- $frm->{image} = _uploadimage($self, $frm) if !$nosubmit;
-
- if(!$nosubmit && !$frm->{_err}) {
- # normalize aliases
- $frm->{alias} = join "\n", map { s/^ +//g; s/ +$//g; $_?($_):() } split /\n/, $frm->{alias};
- # throw error on duplicate/existing aliases
- my %alias = map +(lc($_),1), $frm->{title}, $frm->{original}, map +($_->{title}, $_->{original}), @$r;
- my @e = map $alias{ lc($_) }++ ? "Duplicate alias '$_', or the alias is already used as a release title" : (), split /\n/, $frm->{alias};
- $frm->{_err} = \@e if @e;
- }
- if(!$nosubmit && !$frm->{_err}) {
- # parse and re-sort fields that have multiple representations of the same information
- my $anime = { map +($_=>1), grep /^[0-9]+$/, split /[ ,]+/, $frm->{anime} };
- my $relations = [ map { /^([a-z]+),([0-9]+),([01]),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3, $4 ] : () } split /\|\|\|/, $frm->{vnrelations} ];
-
- # Ensure submitted alias / character IDs exist within database
- my @alist = map $_->{aid}, @{$frm->{credits}}, @{$frm->{seiyuu}};
- my %staff = @alist ? map +($_->{aid}, 1), @{$self->dbStaffGet(aid => \@alist, results => 200)} : ();
- my %vn_chars = map +($_->{id} => 1), @$chars;
- $frm->{credits} = [ grep $staff{$_->{aid}}, @{$frm->{credits}} ];
- $frm->{seiyuu} = [ grep $staff{$_->{aid}} && $vn_chars{$_->{cid}}, @$chars ? @{$frm->{seiyuu}} : () ];
-
- $frm->{ihid} = $frm->{ihid}?1:0;
- $frm->{ilock} = $frm->{ilock}?1:0;
- $frm->{desc} = $self->bbSubstLinks($frm->{desc});
- $relations = [] if $frm->{ihid};
- $frm->{anime} = join ' ', sort { $a <=> $b } keys %$anime;
- $frm->{vnrelations} = join '|||', map $_->[0].','.$_->[1].','.($_->[2]?1:0).','.$_->[3], sort { $a->[1] <=> $b->[1]} @{$relations};
- $frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0;
- $frm->{screenshots} = [ sort { $a->{id} <=> $b->{id} } @{$frm->{screenshots}} ];
-
- # nothing changed? just redirect
- return $self->resRedirect("/v$vid", 'post') if $vid && !form_compare(\%b4, $frm);
-
- # perform the edit/add
- my $nrev = $self->dbItemEdit(v => $vid ? ($v->{id}, $v->{rev}) : (undef, undef),
- (map { $_ => $frm->{$_} } qw|title original image alias desc length l_renai l_wikidata editsum img_nsfw ihid ilock credits seiyuu screenshots|),
- anime => [ keys %$anime ],
- relations => $relations,
- );
-
- # update reverse relations & relation graph
- if(!$vid && $#$relations >= 0 || $vid && $frm->{vnrelations} ne $b4{vnrelations}) {
- my %old = $vid ? (map +($_->{id} => [ $_->{relation}, $_->{official} ]), @{$v->{relations}}) : ();
- my %new = map +($_->[1] => [ $_->[0], $_->[2] ]), @$relations;
- _updreverse($self, \%old, \%new, $nrev->{itemid}, $nrev->{rev});
- }
-
- return $self->resRedirect("/v$nrev->{itemid}.$nrev->{rev}", 'post');
- }
- }
-
- !exists $frm->{$_} && ($frm->{$_} = $b4{$_}) for (keys %b4);
- $frm->{editsum} = sprintf 'Reverted to revision v%d.%d', $vid, $rev if $rev && !defined $frm->{editsum};
-
- my $title = $vid ? "Edit $v->{title}" : 'Add a new visual novel';
- $self->htmlHeader(title => $title, noindex => 1);
- $self->htmlMainTabs('v', $v, 'edit') if $vid;
- $self->htmlEditMessage('v', $v, $title);
- _form($self, $v, $frm, $r, $chars);
- $self->htmlFooter;
-}
-
-
-sub _uploadimage {
- my($self, $frm) = @_;
-
- if($frm->{_err} || !$self->reqPost('img')) {
- return 0 if !$frm->{image};
- push @{$frm->{_err}}, 'No image with that ID' if !-s imgpath(cv => $frm->{image});
- return $frm->{image};
- }
-
- # perform some elementary checks
- my $imgdata = $self->reqUploadRaw('img');
- $frm->{_err} = [ 'Image must be in JPEG or PNG format' ] if $imgdata !~ /^(\xff\xd8|\x89\x50)/; # JPG or PNG headers
- $frm->{_err} = [ 'Image is too large, only 5MB allowed' ] if length($imgdata) > 5*1024*1024;
- return undef if $frm->{_err};
-
- # resize/compress
- my $im = Image::Magick->new;
- $im->BlobToImage($imgdata);
- $im->Set(magick => 'JPEG');
- my($ow, $oh) = ($im->Get('width'), $im->Get('height'));
- my($nw, $nh) = imgsize($ow, $oh, @{$self->{cv_size}});
- $im->Set(background => '#ffffff');
- $im->Set(alpha => 'Remove');
- if($ow != $nw || $oh != $nh) {
- $im->GaussianBlur(geometry => '0.5x0.5');
- $im->Resize(width => $nw, height => $nh);
- $im->UnsharpMask(radius => 0, sigma => 0.75, amount => 0.75, threshold => 0.008);
- }
- $im->Set(quality => 90);
-
- # Get ID and save
- my $imgid = $self->dbImageAdd(cv => $nw, $nh);
- my $fn = imgpath(cv => $imgid);
- $im->Write($fn);
- chmod 0666, $fn;
-
- return $imgid;
-}
-
-
-sub _form {
- my($self, $v, $frm, $r, $chars) = @_;
- $self->htmlForm({ frm => $frm, action => $v ? "/old/v$v->{id}/edit" : '/old/v/new', editsum => 1, upload => 1 },
- vn_geninfo => [ 'General info',
- [ input => short => 'title', name => 'Title (romaji)', width => 450 ],
- [ input => short => 'original', name => 'Original title', width => 450 ],
- [ static => content => 'The original title of this visual novel, leave blank if it already is in the Latin alphabet.' ],
- [ textarea => short => 'alias', name => 'Aliases', rows => 4 ],
- [ static => content =>
- 'List of alternative titles or abbreviations. One line for each alias.'
- .' Can include both official (japanese/english) titles and unofficial titles used around net.<br />'
- .' Titles that are listed in the releases should not be added here!' ],
- [ textarea => short => 'desc', name => 'Description<br /><b class="standout">English please!</b>', rows => 10 ],
- [ static => content =>
- 'Short description of the main story. Please do not include spoilers, and don\'t forget to list'
- .' the source in case you didn\'t write the description yourself. Formatting codes are allowed.' ],
- [ select => short => 'length', name => 'Length', options =>
- [ map [ $_ => fmtvnlen $_, 1 ], keys %VN_LENGTH ] ],
-
- [ input => short => 'l_wikidata',name => 'Wikidata ID',
- pre => 'https://www.wikidata.org/wiki/',
- value => $frm->{l_wikidata} ? "Q$frm->{l_wikidata}" : '',
- post => qq{ (<a href="$self->{url_static}/f/wikidata.png">How to find this</a>)}
- ],
- [ input => short => 'l_renai', name => 'Renai.us link', pre => 'http://renai.us/game/', post => '.shtml' ],
-
- [ input => short => 'anime', name => 'Anime' ],
- [ static => content =>
- 'Whitespace separated list of <a href="http://anidb.net/">AniDB</a> anime IDs.'
- .' E.g. "1015 3348" will add <a href="http://anidb.net/a1015">Shingetsutan Tsukihime</a>'
- .' and <a href="http://anidb.net/a3348">Fate/stay night</a> as related anime.<br />'
- .' Note: It can take a few minutes for the anime titles to appear on the VN page.' ],
- ],
-
- vn_img => [ 'Image', [ static => nolabel => 1, content => sub {
- div class => 'img';
- p 'No image uploaded yet' if !$frm->{image};
- img src => imgurl(cv => $frm->{image}) if $frm->{image};
- end;
-
- div;
- h2 'Image ID';
- input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}||'';
- p 'Use a VN image that is already on the server. Set to \'0\' to remove the current image.';
- br; br;
-
- h2 'Upload new image';
- input type => 'file', class => 'text', name => 'img', id => 'img';
- p 'Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format'
- .' and at most 5MB. Images larger than 256x400 will automatically be resized.';
- br; br; br;
-
- h2 'NSFW';
- input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw',
- $frm->{img_nsfw} ? (checked => 'checked') : ();
- label class => 'checkbox', for => 'img_nsfw', 'Not Safe For Work';
- p 'Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment.';
- end 'div';
- }]],
-
- vn_staff => [ 'Staff',
- [ json => short => 'credits' ],
- [ static => nolabel => 1, content => sub {
- # propagate staff ids and names to javascript
- my @alist = map $_->{aid}, @{$frm->{credits}}, @{$frm->{seiyuu}};
- script_json staffdata => {
- map +($_->{aid}, {id => $_->{id}, aid => $_->{aid}, name => $_->{name}}),
- @alist ? @{$self->dbStaffGet(aid => \@alist, results => 200)} : ()
- };
- div class => 'warning';
- lit 'Please check the <a href="/d2#3">staff editing guidelines</a>. You can'
- .' <a href="/s/new">create a new staff entry</a> if it is not in the database yet,'
- .' but please <a href="/s/all">check for aliasses first</a>.';
- end;
- br;
- table; tbody id => 'credits_tbl';
- Tr id => 'credits_loading'; td colspan => '4', 'Loading...'; end;
- end; end;
- h2 'Add staff';
- table; Tr;
- td class => 'tc_staff';
- input id => 'credit_input', type => 'text', class => 'text', style => 'width: 300px'; end;
- td colspan => 3, '';
- end; end;
- }]],
-
- # Cast tab is only shown for VNs with some characters listed.
- # There's no way to add voice actors in new VN edits since character list
- # would be empty anyway.
- @{$chars} ? (vn_cast => [ 'Cast',
- [ json => short => 'seiyuu' ],
- [ static => nolabel => 1, content => sub {
- table; tbody id => 'cast_tbl';
- Tr id => 'cast_loading'; td colspan => '4', 'Loading...'; end;
- end; end;
- h2 'Add cast';
- table; Tr;
- td class => 'tc_char';
- Select id =>'cast_chars';
- option value => '', 'Select character';
- for my $i (0..$#$chars) {
- my($name, $id) = @{$chars->[$i]}{qw|name id|};
- # append character IDs to coinciding names
- # (assume dbCharGet sorted characters by name)
- $name .= ' - c'.$id if $name eq ($chars->[$i+1]{name}//'')
- .. $name ne ($chars->[$i+1]{name}//'');
- option value => $id, $name;
- }
- end;
- txt ' voiced by';
- end;
- td class => 'tc_staff';
- input id => 'cast_input', type => 'text', class => 'text', style => 'width: 300px';
- end;
- td colspan => 2, '';
- end; end;
- }]]) : (),
-
- vn_rel => [ 'Relations',
- [ hidden => short => 'vnrelations' ],
- [ static => nolabel => 1, content => sub {
- h2 'Selected relations';
- table;
- tbody id => 'relation_tbl';
- # to be filled using javascript
- end;
- end;
-
- h2 'Add relation';
- table;
- Tr id => 'relation_new';
- td class => 'tc_vn';
- input type => 'text', class => 'text';
- end;
- td class => 'tc_rel';
- txt 'is an ';
- input type => 'checkbox', id => 'official', checked => 'checked';
- label for => 'official', 'official';
- Select;
- option value => $_, $VN_RELATION{$_}{txt}
- for (keys %VN_RELATION);
- end;
- txt ' of';
- end;
- td class => 'tc_title', $v ? $v->{title} : '';
- td class => 'tc_add';
- a href => '#', 'add';
- end;
- end;
- end 'table';
- }],
- ],
-
- vn_scr => [ 'Screenshots', !@$r ? (
- [ static => nolabel => 1, content => 'No releases in the database yet. Screenshots can only be uploaded after a release has been added.' ],
- ) : (
- [ json => short => 'screenshots' ],
- [ static => nolabel => 1, content => sub {
- my @scr = map $_->{id}, @{$frm->{screenshots}};
- my %scr = map +($_->{id}, [ $_->{width}, $_->{height}]), @scr ? @{$self->dbScreenshotGet(\@scr)} : ();
- my @rels = map [ $_->{id}, sprintf '[%s] %s (r%d)', join(',', @{$_->{languages}}), $_->{title}, $_->{id} ], @$r;
- script_json screendata => {
- size => \%scr,
- rel => \@rels,
- staticurl => $self->{url_static},
- };
- div class => 'warning';
- lit 'Please keep the following in mind when uploading screenshots:<br />'
- .'- Screenshots have to be in the native resolution of the game,<br />'
- .'- Remove any window borders and make sure the image is unmarked,<br />'
- .'- Don\'t only upload event CGs.<br />'
- .'Please read the <a href="/d2#6">guidelines</a> for more information.<br />'
- .'Make sure to submit the form after the upload has finished!';
- end;
- br;
- table class => 'stripe';
- tbody id => 'scr_table', '';
- end;
- }],
- )]
-
- );
-}
-
-
-# Update reverse relations and regenerate relation graph
-# Arguments: %old. %new, vid, rev
-# %old,%new -> { vid => [ relation, official ], .. }
-# from the perspective of vid
-# rev is of the related edit
-sub _updreverse {
- my($self, $old, $new, $vid, $rev) = @_;
- my %upd;
-
- # compare %old and %new
- for (keys %$old, keys %$new) {
- if(exists $$old{$_} and !exists $$new{$_}) {
- $upd{$_} = undef;
- } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_}[0] ne $$new{$_}[0] || !$$old{$_}[1] != !$$new{$_}[1])) {
- $upd{$_} = [ $VN_RELATION{ $$new{$_}[0] }{reverse}, $$new{$_}[1] ];
- }
- }
- return if !keys %upd;
-
- # edit all related VNs
- for my $i (keys %upd) {
- my $r = $self->dbVNGetRev(id => $i, what => 'relations')->[0];
- my @newrel = map $_->{id} != $vid ? [ $_->{relation}, $_->{id}, $_->{official} ] : (), @{$r->{relations}};
- push @newrel, [ $upd{$i}[0], $vid, $upd{$i}[1] ] if $upd{$i};
- $self->dbItemEdit(v => $r->{id}, $r->{rev},
- relations => \@newrel,
- editsum => "Reverse relation update caused by revision v$vid.$rev",
- uid => 1, # Multi
- );
- }
-}
-
-
-# peforms a (simple) search and returns the results in XML format
-sub vnxml {
- my $self = shift;
-
- my $q = $self->formValidate({ get => 'q', maxlength => 500 });
- return $self->resNotFound if $q->{_err};
- $q = $q->{q};
-
- my($list, $np) = $self->dbVNGet(
- $q =~ /^v([1-9]\d*)/ ? (id => $1) : (search => $q),
- results => 10,
- page => 1,
- );
-
- $self->resHeader('Content-type' => 'text/xml; charset=UTF-8');
- xml;
- tag 'vns', more => $np ? 'yes' : 'no', query => $q;
- for(@$list) {
- tag 'item', id => $_->{id}, $_->{title};
- }
- end;
-}
-
-
-# handles uploading screenshots and fetching information about them
-sub scrxml {
- my $self = shift;
- return $self->htmlDenied if !$self->authCan('edit') || $self->reqMethod ne 'POST';
-
- # upload new screenshot
- my $id = 0;
- my $imgdata = $self->reqUploadRaw('file');
- $id = -2 if !$imgdata;
- $id = -1 if !$id && $imgdata !~ /^(\xff\xd8|\x89\x50)/; # JPG or PNG headers
-
- # no error? process it
- my($ow, $oh);
- if(!$id) {
- my $im = Image::Magick->new;
- $im->BlobToImage($imgdata);
- $im->Set(background => '#000000');
- $im->Set(alpha => 'Remove');
- $im->Set(magick => 'JPEG');
- $im->Set(quality => 90);
- ($ow, $oh) = ($im->Get('width'), $im->Get('height'));
-
- $id = $self->dbImageAdd(sf => $ow, $oh);
- my $fn = imgpath(sf => $id);
- $im->Write($fn);
- chmod 0666, $fn;
-
- # thumbnail
- my($nw, $nh) = imgsize($ow, $oh, @{$self->{scr_size}});
- $im->Thumbnail(width => $nw, height => $nh);
- $im->Set(quality => 90);
- $fn = imgpath(st => $id);
- $im->Write($fn);
- chmod 0666, $fn;
- }
-
- $self->resHeader('Content-type' => 'text/xml; charset=UTF-8');
- xml;
- tag 'image', id => $id, $id > 0 ? (width => $ow, height => $oh) : (), undef;
-}
-
-
-1;
-
diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm
index f411e3da..89a5fa6f 100644
--- a/lib/VNWeb/HTML.pm
+++ b/lib/VNWeb/HTML.pm
@@ -821,11 +821,6 @@ sub editmsg_ {
li_ 'Fields marked with (*) may cause other fields to become (un)available depending on the selection.' if $type eq 'r';
}
};
- p_ class => 'center', sub {
- txt_ "If you're having trouble using this new form, the ";
- a_ href => '/old'.($obj ? "/v$obj->{id}/edit" : '/v/add'), 'old form';
- txt_ ' is still available.';
- } if $type eq 'v' && tuwf->reqPath() !~ m{^/old/};
}
}