set OPT values in jscript in files.html, added functions to draw figures on a page based on pageList (subset of entryList) & json data, and tweaked just grouping select as well to also use the draw figures func() in jscript. Needed to move out .figure click handler into the draw figures too. This is now semi-functional, images load, pages next/prev works, grouping works -- BUT only for files_ip -- folders wont work, search wont work, files_sp wont work, viewing a file wont work

This commit is contained in:
2025-09-27 00:31:42 +10:00
parent be218c5049
commit 5842bf2ab8
2 changed files with 185 additions and 15 deletions

View File

@@ -1,3 +1,9 @@
// GLOBAL ICON array
ICON={}
ICON["Import"]="import"
ICON["Storage"]="db"
ICON["Bin"]="trash"
// 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
@@ -317,20 +323,176 @@ function NoSel() {
return true return true
} }
function handlePageOfData() /**
* Renders a group header or entry based on the object and options.
* @param {Object} obj - The object containing file/directory details.
* @param {Object} last - Tracks the last printed group (e.g., { printed: null }).
* @param {Object} ecnt - Entry counter (e.g., { val: 0 }).
* @returns {string} - Generated HTML string.
*/
function addFigure( obj, last, ecnt)
{ {
// FIXME: this should get back a json'd array of entries, and I can/should let html = "";
// use this to redraw the figures dynamically on the page
// Grouping logic
if (OPT.grouping === "Day") {
if (last.printed !== obj.file_details.day) {
html += `<div class="row ps-3"><h6>Day: ${obj.file_details.day} of ${obj.file_details.month}/${obj.file_details.year}</h6></div>`;
last.printed = obj.file_details.day;
}
} else if (OPT.grouping === "Week") {
if (last.printed !== obj.file_details.woy) {
html += `<div class="row ps-3"><h6>Week #: ${obj.file_details.woy} of ${obj.file_details.year}</h6></div>`;
last.printed = obj.file_details.woy;
}
} else if (OPT.grouping === "Month") {
if (last.printed !== obj.file_details.month) {
html += `<div class="row ps-3"><h6>Month: ${obj.file_details.month} of ${obj.file_details.year}</h6></div>`;
last.printed = obj.file_details.month;
}
}
// Image/Video/Unknown entry
if (obj.type.name === "Image" || obj.type.name === "Video" || obj.type.name === "Unknown") {
if (!OPT.folders || isTopLevelFolder(obj.in_dir.in_path.path_prefix + '/' + obj.in_dir.rel_path + '/' + obj.name, OPT.cwd)) {
const pathType = obj.in_dir.in_path.type.name;
const size = obj.file_details.size_mb;
const hash = obj.file_details.hash;
const inDir = `${obj.in_dir.in_path.path_prefix}/${obj.in_dir.rel_path}`;
const fname = obj.name;
const yr = obj.file_details.year;
const date = `${yr}${String(obj.file_details.month).padStart(2, '0')}${String(obj.file_details.day).padStart(2, '0')}`;
const prettyDate = `${obj.file_details.day}/${obj.file_details.month}/${obj.file_details.year}`;
const type = obj.type.name;
html += `
<figure id="${obj.id}" ecnt="${ecnt}" class="col col-auto g-0 figure entry m-1"
path_type="${pathType}" size="${size}" hash="${hash}" in_dir="${inDir}"
fname="${fname}" yr="${yr}" date="${date}" pretty_date="${prettyDate}" type="${type}">
${renderMedia(obj)}
</figure>
`;
}
}
// Directory entry
else if (obj.type.name === "Directory" && OPT.folders) {
const dirname = obj.dir_details.rel_path.length
? `${obj.dir_details.in_path.path_prefix}/${obj.dir_details.rel_path}`
: obj.dir_details.in_path.path_prefix;
if (isTopLevelFolder(dirname, OPT.cwd)) {
html += `
<figure class="col col-auto g-0 dir entry m-1" id="${obj.id}" ecnt="${ecnt}" dir="${dirname}" type="Directory">
<svg class="svg" width="${OPT.size - 22}" height="${OPT.size - 22}" fill="currentColor">
<use xlink:href="/static/icons.svg#Directory"></use>
</svg>
<figcaption class="svg_cap figure-caption text-center text-wrap text-break">${obj.name}</figcaption>
</figure>
`;
html += `<script>f=$('#${obj.id}'); w=f.find('svg').width(); f.find('figcaption').width(w);</script>`;
}
}
$('#figures').append( html )
// console.log( html )
return
} }
// Helper function to render media (image/video/unknown)
function renderMedia(obj) {
const isImageOrUnknown = obj.type.name === "Image" || obj.type.name === "Unknown";
const isVideo = obj.type.name === "Video";
const path = `${obj.in_dir.in_path.path_prefix}/${obj.in_dir.rel_path}/${obj.name}`;
const thumb = obj.file_details.thumbnail
? `<a href="${path}"><img alt="${obj.name}" class="thumb" height="${OPT.size}" src="data:image/jpeg;base64,${obj.file_details.thumbnail}"></a>`
: `<a href="${path}"><svg width="${OPT.size}" height="${OPT.size}" fill="white"><use xlink:href="/static/icons.svg#unknown_ftype"/></svg></a>`;
let mediaHtml = `<div style="position:relative; width:100%">${thumb}`;
if (isImageOrUnknown) {
if (OPT.search_term) {
mediaHtml += `
<div style="position:absolute; bottom: 0px; left: 2px;">
<svg width="16" height="16" fill="white"><use xlink:href="/static/icons.svg#${getLocationIcon(obj)}"/></svg>
</div>
`;
}
mediaHtml += `
<div id="s${obj.id}" style="display:none; position:absolute; top: 50%; left:50%; transform:translate(-50%, -50%);">
<img height="64px" src="/static/throbber.gif">
</div>
`;
} else if (isVideo) {
mediaHtml += `
<div style="position:absolute; top: 0px; left: 2px;">
<svg width="16" height="16" fill="white"><use xlink:href="/static/icons.svg#film"/></svg>
</div>
`;
if (OPT.search_term) {
mediaHtml += `
<div style="position:absolute; bottom: 0px; left: 2px;">
<svg width="16" height="16" fill="white"><use xlink:href="/static/icons.svg#${getLocationIcon(obj)}"/></svg>
</div>
`;
}
}
mediaHtml += `</div>`;
return mediaHtml;
}
// Helper: Check if path is a top-level folder of cwd
function isTopLevelFolder(path, cwd) {
// Implement your logic here
return true; // Placeholder
}
// Helper: Get location icon (placeholder)
function getLocationIcon(obj) {
return ICON[obj.in_dir.in_path.type.name]
}
// this function draws all the figures from document.entries - called when we
// change pages, but also when we change say grouping/other OPTs
function drawPageOfFigures()
{
$('#figures').empty()
var last = { printed: null }
var ecnt=0
for (const obj of document.entries) {
addFigure( obj, last, ecnt )
ecnt++
}
$('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; });
}
// 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) function getPage(pageNumber)
{ {
const startIndex = (pageNumber - 1) * howMany; const startIndex = (pageNumber - 1) * OPT.howMany;
const endIndex = startIndex + howMany; const endIndex = startIndex + OPT.howMany;
pageList = entryList.slice(startIndex, endIndex); pageList = entryList.slice(startIndex, endIndex);
// FIXME: should POST here to get the data for new pl
// set up data to send to server to get the entry data for entries in pageList
data={}
data.ids = pageList
data.query = 99999
$.ajax({
type: 'POST',
url: '/get_entries_by_ids',
data: JSON.stringify(data), // Stringify the data
contentType: 'application/json', // Set content type
dataType: 'json', // Expect JSON response
success: function(res) {
document.entries=res
drawPageOfFigures()
},
error: function(xhr, status, error) {
console.error("Error:", error);
}
});
return return
} }
@@ -343,7 +505,7 @@ function isFirstPage(pageNumber)
// Function to check if we are on the last page // Function to check if we are on the last page
function isLastPage(pageNumber) function isLastPage(pageNumber)
{ {
const totalPages = Math.ceil(entryList.length / howMany); const totalPages = Math.ceil(entryList.length / OPT.howMany);
return pageNumber >= totalPages; return pageNumber >= totalPages;
} }
@@ -354,7 +516,7 @@ function getPageNumberForId(id) {
if (idx === -1) { if (idx === -1) {
return -1; // or null, if you prefer return -1; // or null, if you prefer
} }
return Math.floor(idx / howMany) + 1; return Math.floor(idx / OPT.howMany) + 1;
} }
// if we are on first page, disable prev, it not ensure next is enabled // if we are on first page, disable prev, it not ensure next is enabled
@@ -380,7 +542,7 @@ function nextPage()
// should never happen / just return pageList unchanged // should never happen / just return pageList unchanged
if ( currentPage === -1 || isLastPage( currentPage ) ) if ( currentPage === -1 || isLastPage( currentPage ) )
{ {
console.log( "WARNING: seems first on pg=" + firstEntryOnPage + " of how many=" + howMany + " gives currentPage=" + currentPage + " and we cant go next page?" ) console.log( "WARNING: seems first on pg=" + firstEntryOnPage + " of how many=" + OPT.howMany + " gives currentPage=" + currentPage + " and we cant go next page?" )
return return
} }
getPage( currentPage+1 ) getPage( currentPage+1 )
@@ -396,7 +558,7 @@ function prevPage()
// should never happen / just return pageList unchanged // should never happen / just return pageList unchanged
if (currentPage === 1 || currentPage === -1 ) if (currentPage === 1 || currentPage === -1 )
{ {
console.log( "WARNING: seems first on pg=" + firstEntryOnPage + " of how many=" + howMany + " gives currentPage=" + currentPage + " and we cant go prev page?" ) console.log( "WARNING: seems first on pg=" + firstEntryOnPage + " of how many=" + OPT.howMany + " gives currentPage=" + currentPage + " and we cant go prev page?" )
return return
} }
getPage( currentPage-1 ) getPage( currentPage-1 )

View File

@@ -17,15 +17,24 @@
{% endfor %} {% endfor %}
// GLOBALS // GLOBALS
// how many on this page, we can change this and redraw the page to suit (also used heavily in pagination code related to entry and page list) // OPTions set via GUI, will change if we alter drop-downs, etc. in GUI
var howMany = {{OPT.how_many}} // TODO: reference these from GUI, so we can finally ditch the form to submit/change them.
// BUT -- must handle noo changing with a form/post as it requires a new ordering
var OPT={}
OPT.grouping='{{OPT.grouping}}'
OPT.cwd='{{OPT.cwd}}'
OPT.search_term='{{OPT.orig_search_term}}'
OPT.folders="{{OPT.folders}}" === "True"
OPT.howMany={{OPT.how_many}}
OPT.size={{OPT.size}}
// this is the list of entry ids for the images for ALL matches for this query // this is the list of entry ids for the images for ALL matches for this query
var entryList={{query_data.entry_list}} var entryList={{query_data.entry_list}}
// pageList is just those entries shown on this page from the full entryList // pageList is just those entries shown on this page from the full entryList
var pageList=[] var pageList=[]
// force pageList to the first page // force pageList to set pageList for & render the first page
getPage(1) getPage(1)
</script> </script>
@@ -61,7 +70,7 @@
{% else %} {% else %}
{{CreateFoldersSelect( OPT.folders )|safe }} {{CreateFoldersSelect( OPT.folders )|safe }}
<span class="sm-txt my-auto btn btn-outline-info disabled border-top border-bottom">grouped by:</span> <span class="sm-txt my-auto btn btn-outline-info disabled border-top border-bottom">grouped by:</span>
{{CreateSelect( "grouping", OPT.grouping, ["None", "Day", "Week", "Month"], "", "rounded-end")|safe }} {{CreateSelect( "grouping", OPT.grouping, ["None", "Day", "Week", "Month"], "OPT.grouping=$('#grouping').val();drawPageOfFigures();return false", "rounded-end")|safe }}
{% endif %} {% endif %}
</div class="input-group"> </div class="input-group">
</div class="col"> </div class="col">
@@ -287,7 +296,6 @@
<script> <script>
$('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; });
$(document).on('click', function(e) { $('.highlight').removeClass('highlight') ; SetButtonState() }); $(document).on('click', function(e) { $('.highlight').removeClass('highlight') ; SetButtonState() });
function CallViewRouteWrapper() function CallViewRouteWrapper()