// TODO: could get path constants from DOM in jinja template const FOLDER_CONTENTS_PATH = '/pvdb/file_listing/folder_contents_json/'; const QUERY_PATH = '/pvdb/tmdb/query_media_json'; const CREATE_MAPPING_PATH = '/pvdb/tmdb/create_path_mapping'; const PATH_PATH = '/pvdb/tmdb/query_path_json'; const VIDEO_PREFIX = '/video/'; // NOTE: create links for folder contents function addContents(node, json) { let li = document.createElement('li'); let a = document.createElement('a'); a.href = window.location; a.dataset.base_name = json.base_name; a.dataset.file_extension = json.file_extension; a.dataset.is_dir = json.is_dir; a.dataset.rel_path = json.rel_path; if (json.is_dir) a.classList.add('folder'); else if (json.in_db) a.classList.add('file_stored'); else a.classList.add('file'); a.appendChild(document.createTextNode(json.base_name)); li.appendChild(a); node.appendChild(li); a.addEventListener('click', function(e) { e.preventDefault(); let element = e.target.parentNode; // NOTE: the parent 'li' element let ul_node = element.querySelector('li > ul'); let div_node = element.querySelector('li > .search_result'); if (ul_node != null) { element.removeChild(ul_node); } else if (div_node != null) { element.removeChild(div_node); } else { if (a.dataset.is_dir == 'true') { fetchJSON(FOLDER_CONTENTS_PATH + a.dataset.rel_path, parseResponse, element); } else { if (a.className == 'file_stored') openInfoCard(a.dataset, e.target); else // 'file' openQueryDialog(a.dataset, e.target); } } }); } // NOTE: display an 'info card' for a path that has already been stored function openInfoCard(dataset, element) { query_str = PATH_PATH + '?rel_path=' + dataset.rel_path; fetchJSON(query_str, function(json) { if (json.errors) { for (let e of json.errors) logError(e) } else { blurb = createBlurb(json); // NOTE: don't need the mapping link here let p = blurb.querySelector('.mapping_link').parentNode; p.parentNode.removeChild(p); // NOTE: add play link let a = document.createElement('a'); a.classList.add('play_link'); a.href = VIDEO_PREFIX + dataset.rel_path; a.appendChild(document.createTextNode('play')); let div = blurb.querySelector('.search_result'); div.insertBefore(a, div.firstChild); element.parentNode.appendChild(blurb); } }); } // NOTE: create query results dialog from html templates function openQueryDialog(dataset, element) { query_str = QUERY_PATH + '?query=' + dataset.base_name + '&rel_path=' + dataset.rel_path; fetchJSON(query_str, function(json) { console.log('openQueryDialog(), ' + query_str); console.log(json); if (json.errors) { for (let e of json.errors) logError(e) } else { let tcontainer = document.querySelector('#query_results'); let tclone = document.importNode(tcontainer.content, true); let close = tclone.querySelector('#query_close'); close.addEventListener('click', function(e) { e.preventDefault(); document.querySelector('body').removeChild(e.target.parentNode); }); for (let result of json) { blurb = createBlurb(result); blurb.querySelector('.mapping_link').addEventListener('click', function(e) { submitFileMapping(e, result.detail_id, dataset.rel_path, element); }); tclone.querySelector('#query_result_container').appendChild(blurb); } document.querySelector('body').appendChild(tclone); } }); } function createBlurb(details) { let qt = document.querySelector('#query_result'); let qtclone = document.importNode(qt.content, true); let title_link = qtclone.querySelector('h3 > a'); title_link.href = details.tmdb_link; title_link.appendChild(document.createTextNode(details.title)); let date = qtclone.querySelector('.query_release_date'); date.appendChild(document.createTextNode(details.release_date)); let description = qtclone.querySelector('.query_description'); description.appendChild(document.createTextNode(details.overview)); return qtclone; } async function submitFileMapping(click_event, detail_id, rel_path, element) { click_event.preventDefault(); // NOTE: remove the query box document.querySelector('body').removeChild(document.querySelector('#query_result_container')); query_str = CREATE_MAPPING_PATH; params = new FormData(); params.append('detail_id', detail_id); params.append('rel_path', rel_path); let json = null; const response = await fetch(CREATE_MAPPING_PATH, { body: params, method: 'POST' }); try { json = await response.json(); } catch (e) { logError('error in submitFileMapping(), ' + e); } if (json != null && json.errors.length == 0) { // NOTE: display success dialog let map_temp = document.querySelector('#mapping_success'); let clone = document.importNode(map_temp.content, true); clone.querySelector('div > p').appendChild(document.createTextNode(json.message)); let body = document.querySelector('body'); body.appendChild(clone); window.setTimeout(function() { body.removeChild(document.querySelector('.success_container')); }, 500); // NOTE: update the displayed link class element.className = 'file_stored'; } } function parseResponse(json, node) { if (node == null) { logError('parent node cannot be null'); return; } if (json.errors.length > 0) { for (let err of json.errors) logError(err); } else { let frag = document.createDocumentFragment(); let ul = document.createElement('ul'); frag.appendChild(ul); for (let path of json.paths) addContents(ul, path); node.appendChild(frag); } } window.onload = function() { document.querySelector('#noscript').style.display = 'none'; let error_box = document.querySelector('#js_errors'); error_box.style.display = 'none'; if (!('fetch' in window)) { logError('Unsupported Browser, No fetch API'); return; } if ((!'content' in document.createElement('template'))) { logError('Unsupported Browser, No template support'); return; } fetchJSON(FOLDER_CONTENTS_PATH, parseResponse, document.querySelector('.content')); } function logError(s) { console.log(s); let error_box = document.querySelector('#js_errors'); let p = document.createElement('p'); p.appendChild(document.createTextNode(s)); error_box.appendChild(p); error_box.style.display = 'block'; } function removeAllChildren(node) { while(node.hasChildNodes()) node.removeChild(node.lastChild); } function fetchJSON(url, responseFunc, node=null) { fetch(url) .then(function(response) { if (!response.ok) throw Error(response.statusText); return response.json(); }) .catch(function(error) { logError('fetch error: ' + error); return null; }) .then(function(json) { if (json != null) (node == null) ? responseFunc(json) : responseFunc(json, node); }); }