Personal Video Database
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.
 
 
 
 
 

228 lines
6.4 KiB

// 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_movie_json';
const CREATE_MAPPING_PATH = '/pvdb/tmdb/create_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 = a.parentNode
if (element.querySelector('ul')) {
element.removeChild(element.querySelector('ul'));
} 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) {
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.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, movie_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('movie_id', movie_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'));
}, 1000);
// 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);
});
}