/* * 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 . */ 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); }); }