Compare commits

...

4 Commits

6 changed files with 389 additions and 401 deletions

15
TODO
View File

@@ -1,20 +1,15 @@
### ###
# get override data into view # get override data into view
# should start with an empty DB and test - definitely no dirs in storage_sp gives: # should start with an empty DB and test
# dir_id=dir_arr[0] # definitely no dirs in storage_sp I now pass root_eid=0 for this
# IndexError: list index out of range # BUT - need GUI to work - may even be good to put an alert up - its so odd to have not root dir ONLY happens when no data
# TEST this, code in files will work, but now passes root_eid=0 for # empty directories (2017/20171015-test/...) showing "No matches for: 'undefined'" <- should only comes up for search in URL???
# this - so need GUI to work - may even be good to put an alert up - its so odd to hvae not root dir ONLY happens when no data
# empty directories are sometimes showing "No matches for: 'undefined'" <- should only comes up for search in URL???
# think I killed pa_job_manager without passing an eid to a transform job, shouldn't crash # think I killed pa_job_manager without passing an eid to a transform job, shouldn't crash
# SHOULD JUST get AI to help clean-up and write defensive code here... # SHOULD JUST get AI to help clean-up and write defensive code here...
# also all the add ref img/add override, etc are non-functional - FIX the override* stuff first to get table/naming consistency as that is half the problem # also all the add ref img/add override, etc are non-functional - FIX the override* stuff first to get table/naming consistency as that is half the problem
# delete button also uses current? (eid is empty anyway)
# move as much jscript into *_support, as possible (if there are no more {{ - # then move it)
# convert move_paths to a json setup # convert move_paths to a json setup
# ALSO revisit this move_paths to be as safe as possible ultimately, triple-check there are no leading / or .. 's # ALSO revisit this move_paths to be as safe as possible ultimately, triple-check there are no leading / or .. 's
# TEST everything (don't forget keybindings) # TEST everything (don't forget keybindings,e.g. delete)
# transforms -> should consider removing the pull logic to see if a job is finished (have job-mgr push data back? while more rest, not sure b/e EVER sends data to F/E at moment)
### ###
### major fix - go to everywhere I call GetEntries(), and redo the logic totally... ### major fix - go to everywhere I call GetEntries(), and redo the logic totally...

View File

@@ -4,6 +4,21 @@ ICON["Import"]="import"
ICON["Storage"]="db" ICON["Storage"]="db"
ICON["Bin"]="trash" ICON["Bin"]="trash"
// function called when we get another page from inside the files view
function getPageFigures(res, viewingIdx)
{
// add all the figures to files_div
drawPageOfFigures()
}
// function called when we get another page from inside the viewer
function getPageViewer(res, viewingIdx)
{
document.viewing=document.entries[viewingIdx]
// update viewing, arrows and image/video too
ViewImageOrVideo()
}
// grab all selected thumbnails and return a <div> containing the thumbnails // grab all selected thumbnails and return a <div> containing the thumbnails
// with extra yr and date attached as attributes so we can set the default // with extra yr and date attached as attributes so we can set the default
// dir name for a move directory - not used in del, but no harm to include them // dir name for a move directory - not used in del, but no harm to include them
@@ -520,10 +535,10 @@ function drawPageOfFigures()
addFigure( obj, last, ecnt ) addFigure( obj, last, ecnt )
ecnt++ ecnt++
} }
if( document.entries.length == 0 && OPT.search_term != '' ) if( document.entries.length == 0 && OPT.search_term )
$('#figures').append( `<span class="alert alert-danger p-2 col-auto"> No matches for: '${OPT.search_term}'</span>` ) $('#figures').append( `<span class="alert alert-danger p-2 col-auto"> No matches for: '${OPT.search_term}'</span>` )
$('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; }); $('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; });
$('.figure').dblclick( function(e) { dblClickToViewEntry( $(this).attr('id') ) } ) $('.figure').dblclick( function(e) { dblClickToViewEntry( $(this).attr('id') ); setDisabledForViewingNextPrevBttons(); addViewerKeyHandler() } )
// for dir, getDirEntries 2nd param is back (or "up" a dir) // for dir, getDirEntries 2nd param is back (or "up" a dir)
$(".dir").click( function(e) { document.back_id=this.id; getDirEntries(this.id,false) } ) $(".dir").click( function(e) { document.back_id=this.id; getDirEntries(this.id,false) } )
$(".back").click( function(e) { getDirEntries(this.id,true) } ) $(".back").click( function(e) { getDirEntries(this.id,true) } )
@@ -553,21 +568,6 @@ function getPageFileList(res, viewingIdx)
$('#file_list_div').append(html) $('#file_list_div').append(html)
} }
// function called when we get another page from inside the files view
function getPageFigures(res, viewingIdx)
{
// add all the figures to files_div
drawPageOfFigures()
}
// function called when we get another page from inside the viewer
function getPageViewer(res, viewingIdx)
{
document.viewing=document.entries[viewingIdx]
// update viewing, arrows and image/video too
ViewImageOrVideo()
}
// Function to get the 'page' of entry ids out of entryList // Function to get the 'page' of entry ids out of entryList
function getPage(pageNumber, successCallback, viewingIdx=0) function getPage(pageNumber, successCallback, viewingIdx=0)
{ {
@@ -587,9 +587,15 @@ function getPage(pageNumber, successCallback, viewingIdx=0)
type: 'POST', url: '/get_entries_by_ids', type: 'POST', url: '/get_entries_by_ids',
data: JSON.stringify(data), contentType: 'application/json', data: JSON.stringify(data), contentType: 'application/json',
dataType: 'json', dataType: 'json',
success: function(res) { document.entries=res; successCallback(res,viewingIdx); }, success: function(res) {
error: function(xhr, status, error) { console.error("Error:", error); } }); document.entries=res;
successCallback(res,viewingIdx);
resetNextPrevButtons() resetNextPrevButtons()
// if search, disable folders
if( OPT.search_term )
$('#folders').prop('disabled', 'disabled').removeClass('border-info').addClass('border-secondary').removeClass('text-info').addClass('text-secondary');
},
error: function(xhr, status, error) { console.error("Error:", error); } });
return return
} }
@@ -620,6 +626,13 @@ function getPageNumberForId(id) {
// if we are on last page, disable next, it not ensure prev is enabled // if we are on last page, disable next, it not ensure prev is enabled
function resetNextPrevButtons() function resetNextPrevButtons()
{ {
// no data, so disabled both
if( getPageNumberForId(pageList[0]) == -1 )
{
$('.prev').prop('disabled', true).addClass('disabled');
$('.next').prop('disabled', true).addClass('disabled');
return
}
if ( isFirstPage( getPageNumberForId(pageList[0]) ) ) if ( isFirstPage( getPageNumberForId(pageList[0]) ) )
$('.prev').prop('disabled', true).addClass('disabled'); $('.prev').prop('disabled', true).addClass('disabled');
else else
@@ -661,12 +674,14 @@ function prevPage(successCallback)
return return
} }
// function to see if we are on a phone or tablet (where we dont have ctrl or shift keys - helps to display fake buttons to allow multiselect on mobiles)
function isMobile() { function isMobile() {
try{ document.createEvent("TouchEvent"); return true; } try{ document.createEvent("TouchEvent"); return true; }
catch(e){ return false; } catch(e){ return false; }
} }
// when we change one of the options (noo, how_many, folders) - then update '{how_many} files' str,
// tweak noo menu for folders/flat view then reset the page contents based on current OPT values
function changeOPT(successCallback) { function changeOPT(successCallback) {
OPT.how_many=$('#how_many').val() OPT.how_many=$('#how_many').val()
new_f=$('#folders').val() new_f=$('#folders').val()
@@ -707,3 +722,119 @@ function changeOPT(successCallback) {
} }
}) })
} }
// function to change the size of thumbnails when user clicks xs/s/m/l/xl buttons
function changeSize()
{
sz=$('input[name="size"]:checked').val();
$('.thumb').prop('height',sz);
}
function getPreviousEntry() {
var currentIndex = entryList.indexOf(document.viewing.id);
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
if (currentIndex > 0) {
currentIndex--;
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex=currentIndex-(pageOffset*OPT.how_many)
// pref page, load it
if( oldPageOffset != pageOffset )
// pref page is pageOffset+1 now
getPage(pageOffset+1,getPageViewer,currentIndex)
else
document.viewing=document.entries[currentIndex]
}
}
function getNextEntry() {
var currentIndex = entryList.indexOf(document.viewing.id);
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
if (currentIndex < entryList.length - 1) {
currentIndex++
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex=currentIndex-(pageOffset*OPT.how_many)
// next page, load it
if( oldPageOffset != pageOffset )
// next page is pageOffset+1 now
getPage(pageOffset+1,getPageViewer,currentIndex)
else
document.viewing=document.entries[currentIndex]
}
}
function entryIsAtStart() {
return document.viewing.id === entryList[0];
}
function entryIsAtEnd() {
return document.viewing.id === entryList[entryList.length - 1];
}
function setEntryById(id) {
var currentIndex = entryList.indexOf(parseInt(id));
// if we are on a different page, adjust as document.entries only has <= how_many
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex = currentIndex-(pageOffset*OPT.how_many)
document.viewing=document.entries[currentIndex]
}
function setDisabledForViewingNextPrevBttons()
{
$('#la').attr('disabled', entryIsAtStart());
$('#ra').attr('disabled', entryIsAtEnd());
}
function addViewerKeyHandler() {
// allow a keypress on the viewer_div
$(document).keydown(function(event) {
// if dbox is visible, dont process this hot-key, we are inputting text
// into inputs instead
if( $("#dbox").is(':visible') )
return
switch (event.key)
{
case "Left": // IE/Edge specific value
case "ArrowLeft":
if( $('#la').prop('disabled') == false )
$('#la').click()
break;
case "Right": // IE/Edge specific value
case "ArrowRight":
if( $('#ra').prop('disabled') == false )
$('#ra').click()
break;
case "d":
$('#distance').click()
break;
case "f":
$('#faces').click()
break;
case "n":
$('#fname_toggle').click()
break;
case "F":
fullscreen=!document.fullscreen
ViewImageOrVideo()
break;
case "l":
JoblogSearch()
break;
case "Delete":
$('#del').click()
default:
return; // Quit when this doesn't handle the key event.
}
});
}
$(document).on('click', function(e) { $('.highlight').removeClass('highlight') ; SetButtonState() });
function dblClickToViewEntry(id) {
$('#files_div').addClass('d-none')
$('#viewer_div').removeClass('d-none')
setEntryById( id )
ViewImageOrVideo()
}

5
job.py
View File

@@ -3,7 +3,7 @@ from flask_wtf import FlaskForm
from flask import request, render_template, redirect, make_response, jsonify, url_for from flask import request, render_template, redirect, make_response, jsonify, url_for
from settings import Settings from settings import Settings
from main import db, app, ma from main import db, app, ma
from sqlalchemy import Sequence, func from sqlalchemy import Sequence, func, select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pytz import pytz
@@ -280,7 +280,8 @@ def joblog_search():
from sqlalchemy import text from sqlalchemy import text
eid=request.form['eid'] eid=request.form['eid']
ent=Entry.query.get(eid) stmt = select(Entry).where(Entry.id == eid)
ent = db.session.scalars(stmt).one_or_none()
logs=Joblog.query.join(Job).filter(Joblog.log.ilike(text(f"'%%{ent.name}%%'"))).with_entities(Joblog.log, Job.id, Job.name, Job.state, Joblog.log_date).all() logs=Joblog.query.join(Job).filter(Joblog.log.ilike(text(f"'%%{ent.name}%%'"))).with_entities(Joblog.log, Job.id, Job.name, Job.state, Joblog.log_date).all()
# turn DB output into json and return it to the f/e # turn DB output into json and return it to the f/e

View File

@@ -63,6 +63,9 @@ class PathDetail(PA):
# construct icon_url based on type of storage path (icons.svg contains icons for each) # construct icon_url based on type of storage path (icons.svg contains icons for each)
self.icon_url:str=url_for("internal", filename="icons.svg") + "#" + ICON[self.type] self.icon_url:str=url_for("internal", filename="icons.svg") + "#" + ICON[self.type]
def to_dict(self):
return {key: value for key, value in vars(self).items()}
################################################################################ ################################################################################
# helper function to find path details for move destinations - used in html # helper function to find path details for move destinations - used in html
# for move DBox to show potential storage paths to move files into # for move DBox to show potential storage paths to move files into
@@ -83,9 +86,9 @@ def MovePathDetails():
sps=Path.query.join(PathType).filter(PathType.name=="Storage").all() sps=Path.query.join(PathType).filter(PathType.name=="Storage").all()
for p in sps: for p in sps:
obj = PathDetail( ptype="Storage", path=p.path_prefix.replace("static/Storage/","") ) obj = PathDetail( ptype="Storage", path=p.path_prefix.replace("static/Storage/","") )
ret.append( obj ) ret.append( obj.to_dict() )
ips=Path.query.join(PathType).filter(PathType.name=="Import").all() ips=Path.query.join(PathType).filter(PathType.name=="Import").all()
for p in ips: for p in ips:
obj = PathDetail( ptype="Import", path=p.path_prefix.replace("static/Import/","") ) obj = PathDetail( ptype="Import", path=p.path_prefix.replace("static/Import/","") )
ret.append( obj ) ret.append( obj.to_dict() )
return ret return ret

View File

@@ -136,7 +136,7 @@
{% if not InDBox %} {% if not InDBox %}
{%block script_content %}{% endblock script_content %} {%block script_content %}{% endblock script_content %}
<div id="status_container" class="position-fixed top-0 end-0 p-0 my-5" "z-index: 11"> </div> <div id="status_container" class="position-fixed top-0 end-0 p-0 my-5" style="z-index: 9999"> </div>
<!-- CheckForJobs(), will see if there are any messages/jobs and keep doing this until there are 0 more and then stop --> <!-- CheckForJobs(), will see if there are any messages/jobs and keep doing this until there are 0 more and then stop -->
<script> <script>
$(document).ready(function() { CheckForJobs() } ) $(document).ready(function() { CheckForJobs() } )

View File

@@ -1,49 +1,24 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block main_content %} {% block main_content %}
<style>
.norm-txt { font-size: 1.0rem }
.form-check-input:checked {
background-color: #39C0ED;
border-color: #CFF4FC;
}
.form-switch .form-check-input {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2339C0ED'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:focus {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23CFF4FC'/%3e%3c/svg%3e");
}
#tst90:hover,#tst90:focus { filter: invert(73%) sepia(27%) saturate(3970%) hue-rotate(146deg) brightness(94%) contrast(100%); }
</style>
<script src="{{ url_for( 'internal', filename='js/files_transform.js')}}"></script> <script src="{{ url_for( 'internal', filename='js/files_transform.js')}}"></script>
<script src="{{ url_for( 'internal', filename='js/files_support.js')}}"></script> <script src="{{ url_for( 'internal', filename='js/files_support.js')}}"></script>
<script src="{{ url_for( 'internal', filename='js/view_support.js')}}"></script> <script src="{{ url_for( 'internal', filename='js/view_support.js')}}"></script>
<script>
// FIXME: why is this script block at the top? and not at the bottom
document.fake_shift=0
document.fake_ctrl=0
// FIXME: used by viewer code - should probably get rid of this?
var fullscreen=false;
// FIXME: doco / and convert to json
var move_paths=[]
{% for p in move_paths %}
p = new Object()
p.type = '{{p.type}}'
p.path = '{{p.path}}'
p.icon_url = '{{p.icon_url}}'
move_paths.push(p)
{% endfor %}
// GLOBALS
// this is the current entry (object) we are viewing - an image/video (used when we dbl-click to view & then in next/prev in view)
document.viewing=null;
var OPT = {{ OPT.to_dict()|tojson }};
OPT.root_eid = {{ query_data.root_eid }};
// this is the list of entry ids for the images for ALL matches for this query
var entryList={{query_data.entry_list}}
// pageList is just those entries shown on this page from the full entryList
var pageList=[]
// force pageList to set pageList for & render the first page
getPage(1,getPageFigures)
// FIXME: MOVE to file_support.js
function changeSize()
{
sz=$('input[name="size"]:checked').val();
$('.thumb').prop('height',sz);
}
</script>
<div id="files_div"> <div id="files_div">
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex row mb-2"> <div class="d-flex row mb-2">
@@ -80,10 +55,6 @@
<div class="col col-auto my-auto"> <div class="col col-auto my-auto">
<span class="alert alert-primary p-2">Searched for: '{{search_term}}'</span> <span class="alert alert-primary p-2">Searched for: '{{search_term}}'</span>
</div class="col my-auto"> </div class="col my-auto">
<script>
// FIXME: need to move this into getPage (or similar), so its picked up always not just on first load
$('#folders').prop('disabled', 'disabled').removeClass('border-info').addClass('border-secondary').removeClass('text-info').addClass('text-secondary');
</script>
{% endif %} {% endif %}
<div class="col flex-grow-1 my-auto d-flex justify-content-center w-100"> <div class="col flex-grow-1 my-auto d-flex justify-content-center w-100">
<button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage(getPageFigures)" disabled> <button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage(getPageFigures)" disabled>
@@ -144,117 +115,6 @@
</div class="container-fluid"> </div class="container-fluid">
</div id="files_div"> </div id="files_div">
<div id="viewer_div" class="d-none"> <div id="viewer_div" class="d-none">
<style>
.norm-txt { font-size: 1.0rem }
.form-check-input:checked {
background-color: #39C0ED;
border-color: #CFF4FC;
}
.form-switch .form-check-input {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2339C0ED'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:focus {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23CFF4FC'/%3e%3c/svg%3e");
}
#tst90:hover,#tst90:focus { filter: invert(73%) sepia(27%) saturate(3970%) hue-rotate(146deg) brightness(94%) contrast(100%); }
</style>
<script>
// FIXME: doco, but also gather all globals together, many make them all document. to be obviously global (and add fullscreen)
var gap=0.8
var grayscale=0
var throbber=0
var objs=[]
var NMO=[]
var imp_path="static/Import/{{imp_path}}"
var st_path="static/Storage/{{st_path}}"
var bin_path="static/Bin/{{bin_path}}"
// FIXME: MOVE these functions to file_support.js
function PrettyFname(fname)
{
s='<span class="alert alert-secondary py-2">'
if( fname.indexOf( "static/Import" ) == 0 )
{
s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#import"/></svg>'
tmp_path=fname.replace(imp_path,"" )
}
if( fname.indexOf( "static/Storage" ) == 0 )
{
s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#db"/></svg>'
tmp_path=fname.replace("static/Storage","" )
}
if( fname.indexOf( "static/Bin" ) == 0 )
{
s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#trash-fill"/></svg>'
tmp_path=fname.replace("static/Bin","" )
}
s+=tmp_path+'</span>'
return s
}
function getPreviousEntry() {
var currentIndex = entryList.indexOf(document.viewing.id);
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
if (currentIndex > 0) {
currentIndex--;
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex=currentIndex-(pageOffset*OPT.how_many)
// pref page, load it
if( oldPageOffset != pageOffset )
// pref page is pageOffset+1 now
getPage(pageOffset+1,getPageViewer,currentIndex)
else
document.viewing=document.entries[currentIndex]
}
}
function getNextEntry() {
var currentIndex = entryList.indexOf(document.viewing.id);
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
if (currentIndex < entryList.length - 1) {
currentIndex++
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex=currentIndex-(pageOffset*OPT.how_many)
// next page, load it
if( oldPageOffset != pageOffset )
// next page is pageOffset+1 now
getPage(pageOffset+1,getPageViewer,currentIndex)
else
document.viewing=document.entries[currentIndex]
}
}
function entryIsAtStart() {
return document.viewing.id === entryList[0];
}
function entryIsAtEnd() {
return document.viewing.id === entryList[entryList.length - 1];
}
function setEntryById(id) {
var currentIndex = entryList.indexOf(parseInt(id));
// if we are on a different page, adjust as document.entries only has <= how_many
pageOffset=Math.floor(currentIndex / OPT.how_many)
currentIndex = currentIndex-(pageOffset*OPT.how_many)
document.viewing=document.entries[currentIndex]
}
function setDisabledForViewingNextPrevBttons()
{
$('#la').attr('disabled', entryIsAtStart());
$('#ra').attr('disabled', entryIsAtEnd());
}
</script>
<div id="viewer" class="container-fluid"> <div id="viewer" class="container-fluid">
<div class="row"> <div class="row">
<button title="Show previous image" class="col-auto btn btn-outline-info px-2" <button title="Show previous image" class="col-auto btn btn-outline-info px-2"
@@ -286,11 +146,6 @@
<figcaption id="vid-cap" class="figure-caption text-center text-wrap text-break"> <figcaption id="vid-cap" class="figure-caption text-center text-wrap text-break">
<span id="fname_v"></span></figcaption> <span id="fname_v"></span></figcaption>
</div> </div>
<script>
window.addEventListener('resize', DrawImg, false);
window.addEventListener('resize', ResizeVideo, false);
</script>
<button title="Show next image" class="col-auto btn btn-outline-info px-2" style="padding: 10%" id="ra" <button title="Show next image" class="col-auto btn btn-outline-info px-2" style="padding: 10%" id="ra"
onClick=" onClick="
getNextEntry() getNextEntry()
@@ -301,7 +156,6 @@
<use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg> <use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg>
</button> </button>
</div class="row"> </div class="row">
{# use this for color of toggles: https://www.codeply.com/p/4sL9uhevwJ #}
<div class="row"> <div class="row">
{# this whole div, just takes up the same space as the left button and is hidden for alignment only #} {# this whole div, just takes up the same space as the left button and is hidden for alignment only #}
<div class="col-auto px-0"> <div class="col-auto px-0">
@@ -362,63 +216,66 @@
</div> </div>
</div class="row"> </div class="row">
</div id="viewer"> </div id="viewer">
</div id="viewer_div"> </div id="viewer_div">
{% endblock main_content %} {% endblock main_content %}
{% block script_content %} {% block script_content %}
<script> <script>
// FIXME: MOVE the majorty of below to files_support/view_support. MIGHT help to have urls go into a global too, and then can ignore many of the above items needing url_for document.fake_shift=0
$( document ).keydown(function(event) { document.fake_ctrl=0
// if dbox is visible, dont process this hot-key, we are inputting text // FIXME: used by viewer code - should probably get rid of this?
// into inputs instead var fullscreen=false;
if( $("#dbox").is(':visible') ) var move_paths = {{ move_paths|tojson }};
return
switch (event.key) // GLOBALS
// this is the current entry (object) we are viewing - an image/video (used when we dbl-click to view & then in next/prev in view)
document.viewing=null;
var OPT = {{ OPT.to_dict()|tojson }};
OPT.root_eid = {{ query_data.root_eid }};
// this is the list of entry ids for the images for ALL matches for this query
var entryList={{query_data.entry_list}}
// pageList is just those entries shown on this page from the full entryList
var pageList=[]
// force pageList to set pageList for & render the first page
getPage(1,getPageFigures)
// FIXME: doco, but also gather all globals together, many make them all document. to be obviously global (and add fullscreen)
var gap=0.8
var grayscale=0
var throbber=0
var NMO=[]
var imp_path="static/Import/{{imp_path}}"
var st_path="static/Storage/{{st_path}}"
var bin_path="static/Bin/{{bin_path}}"
function PrettyFname(fname)
{ {
case "Left": // IE/Edge specific value s='<span class="alert alert-secondary py-2">'
case "ArrowLeft": if( fname.indexOf( "static/Import" ) == 0 )
if( $('#la').prop('disabled') == false ) {
$('#la').click() s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#import"/></svg>'
break; tmp_path=fname.replace(imp_path,"" )
case "Right": // IE/Edge specific value }
case "ArrowRight": if( fname.indexOf( "static/Storage" ) == 0 )
if( $('#ra').prop('disabled') == false ) {
$('#ra').click() s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#db"/></svg>'
break; tmp_path=fname.replace("static/Storage","" )
case "d": }
$('#distance').click() if( fname.indexOf( "static/Bin" ) == 0 )
break; {
case "f": s+='<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#trash-fill"/></svg>'
$('#faces').click() tmp_path=fname.replace("static/Bin","" )
break; }
case "n": s+=tmp_path+'</span>'
$('#fname_toggle').click() return s
break;
case "F":
fullscreen=!document.fullscreen
ViewImageOrVideo()
break;
case "l":
JoblogSearch()
break;
case "Delete":
$('#del').click()
default:
return; // Quit when this doesn't handle the key event.
} }
});
$(document).on('click', function(e) { $('.highlight').removeClass('highlight') ; SetButtonState() }); // different context menu on files
$.contextMenu({
function dblClickToViewEntry(id) {
$('#files_div').addClass('d-none')
$('#viewer_div').removeClass('d-none')
setEntryById( id )
ViewImageOrVideo()
}
// different context menu on files
$.contextMenu({
selector: '.entry', selector: '.entry',
itemClickEvent: "click", itemClickEvent: "click",
build: function($triggerElement, e) { build: function($triggerElement, e) {
@@ -496,11 +353,9 @@ $.contextMenu({
items: item_list items: item_list
}; };
} }
}); });
$( document ).keydown(function(event) { switch (event.key)
$( document ).keydown(function(event) {
switch (event.key)
{ {
case "Delete": case "Delete":
{% if "files_rbp" in request.url %} {% if "files_rbp" in request.url %}
@@ -511,13 +366,16 @@ $( document ).keydown(function(event) {
break; break;
} }) } })
if( isMobile() ) if( isMobile() )
{ {
$('#shift-key').css('visibility', 'visible'); $('#shift-key').css('visibility', 'visible');
$('#ctrl-key').css('visibility', 'visible'); $('#ctrl-key').css('visibility', 'visible');
} }
// check the size radiobutton // check the size radiobutton
$(`input[name="size"][value="${OPT.size}"]`).prop('checked', true) $(`input[name="size"][value="${OPT.size}"]`).prop('checked', true)
window.addEventListener('resize', DrawImg, false);
window.addEventListener('resize', ResizeVideo, false);
</script> </script>
{% endblock script_content %} {% endblock script_content %}