You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

240 lines
6.7 KiB

/*
* This file is part of video_metadata.
*
* video_metadata is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* video_metadata is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with video_metadata. If not, see <https://www.gnu.org/licenses/>.
*/
const SCAN_URL = 'admin.php?action=scan';
const VERIFY_URL = 'admin.php?action=verify';
function copyJSONtoDOMData(node, path_info)
{
node.dataset.baseName = path_info.base_name;
node.dataset.contentSize = path_info.content_size;
node.dataset.depth = path_info.depth;
node.dataset.fileExtension = path_info.path_extension;
node.dataset.fullPath = path_info.full_path;
node.dataset.mediaType = path_info.media_type;
node.dataset.pathType = path_info.path_type;
}
function updatePathInfoStyle(node)
{
node.classList.remove('unknown', 'movie', 'tv_show');
if (node.dataset.pathType == 'directory') {
node.classList.add('directory');
} else if (node.dataset.pathType == 'file') {
node.classList.add('file');
if (node.dataset.mediaType != '')
node.classList.add(node.dataset.mediaType);
}
if (node.dataset.mediaType == 'unknown')
node.classList.add('unknown');
}
function updateMediaType(node, media_type)
{
node.dataset.mediaType = media_type;
updateRadioButtons(node, media_type)
updatePathInfoStyle(node);
for (let child of node.children) {
if (child.nodeName == 'DIV')
updateMediaType(child, media_type);
}
}
function updateRadioButtons(node, media_type)
{
if (media_type == 'movie') {
node.querySelector('input[value^="tv_show"]').setAttribute('checked', false);
node.querySelector('input[value^="movie"]').setAttribute('checked', true);
} else if (media_type == 'tv_show') {
node.querySelector('input[value^="movie"]').setAttribute('checked', false);
node.querySelector('input[value^="tv_show"]').setAttribute('checked', true);
}
}
// NOTE: recursively build DOM tree with attached data attributes and callbacks
// for editing the data
function buildDirectoryTreeWithData(path_info)
{
const DEPTH_NAMES = ['depth_0', 'depth_1', 'depth_2', 'depth_3', 'depth_4', 'depth_5'];
let t = document.querySelector("#path_info_template");
let clone = document.importNode(t.content, true);
let sub_list = clone.querySelector('div');
sub_list.querySelector('form span').textContent = path_info.base_name;
sub_list.classList.add(DEPTH_NAMES[path_info.depth]);
copyJSONtoDOMData(sub_list, path_info);
updatePathInfoStyle(sub_list);
updateRadioButtons(sub_list, path_info.media_type)
// NOTE: don't display the radio buttons on top level directory
if (path_info.depth == 0) {
let s = sub_list.querySelector('form span');
sub_list.appendChild(s);
sub_list.removeChild(sub_list.querySelector('form'));
} else {
sub_list.querySelector('form').addEventListener('change', function(e){
updateMediaType(sub_list, e.target.value);
});
}
// NOTE: hide nested folders by default and add listener to open/close children
if (path_info.depth > 1)
sub_list.classList.add('hidden');
if (path_info.depth > 0) {
sub_list.addEventListener('click', function(e) {
e.stopPropagation();
if (e.target.nodeName != 'INPUT') {
for (let div of sub_list.querySelectorAll('div'))
div.classList.toggle('hidden');
}
});
}
for (let node of path_info.contents)
sub_list.appendChild(buildDirectoryTreeWithData(node));
return clone;
}
function createJSONFromDOM(node)
{
let json = {};
json.base_name = node.dataset.baseName;
json.content_size = node.dataset.contentSize;
json.depth = node.dataset.depth;
json.path_extension = node.dataset.fileExtension;
json.full_path = node.dataset.fullPath;
json.media_type = node.dataset.mediaType;
json.path_type = node.dataset.pathType;
json.contents = [];
return json;
}
function buildJSONFromNode(node)
{
let json = createJSONFromDOM(node);
if (json.media_type == "unknown" || json.media_type == "") {
throw new Error('unknown media type, ' + json.base_name + ', at depth: ' + json.depth + '.\n');
return null;
}
if (node.childNodes.length > 1) {
for (let child of node.children) {
if (child.nodeName == 'DIV')
json.contents.push(buildJSONFromNode(child));
}
}
return json;
}
function onScanSubmit(e)
{
console.log('onScanSubmit');
let errors = document.querySelector('#errors');
let error_count = 0;
let div = document.querySelector('#main_container div');
let json = createJSONFromDOM(div);
for (let node of div.children) {
if (node.nodeName == 'DIV') {
try {
json.contents.push(buildJSONFromNode(node));
} catch(e) {
console.log(e);
errors.appendChild(document.createTextNode(e.message));
error_count++;
}
}
}
if (error_count == 0) {
console.log('valid json, uploading');
fetchPOSTJSON(VERIFY_URL, {body: json}, function(response) {
let main_container = document.querySelector("#main_container");
resetContainers(main_container);
if (response.errors)
errors.appendChild(document.createTextNode(response.message));
else
main_container.appendChild(document.createTextNode(response.message));
console.log(response);
});
} else {
console.log('failed upload, errors in json');
}
}
function scanFolderResponse(data)
{
let errors = document.querySelector('#errors');
let info_container = document.querySelector('#info pre');
let main_container = document.querySelector('#main_container');
resetContainers(errors, info_container, main_container);
if (data.errors) {
for (let err of data.errors) {
errors.appendChild(document.createTextNode(err));
console.log(err);
}
}
if (data.mem_usage) {
info_container.appendChild(document.createTextNode(
'memory usage: ' + data.mem_usage + ' bytes')
);
}
if (data.path_info) {
let b = document.createElement('button');
b.textContent = 'Upload';
b.addEventListener('click', onScanSubmit);
main_container.appendChild(b);
main_container.appendChild(buildDirectoryTreeWithData(data.path_info));
}
}
window.onload = function () {
if (!('fetch' in window)) {
console.log('no fetch API');
return;
}
let scan_button = document.querySelector('#scan_button');
scan_button.addEventListener('click', function(e) {
let info_container = document.querySelector('#info pre');
resetContainers(info_container);
info_container.appendChild(document.createTextNode('waiting for response...'));
fetchJSON(SCAN_URL, scanFolderResponse);
});
}