removed __repr__ from classes in files.py, and added in sqlalchemy class and marshmallow schemas for entry amendments, then load amendments on get_entry_by_id - so any page load (first or next/prev) will see amendments, we then display them into the files list and now add a white circle inside the throbber and overlay that with approrpiate icon/image - all of which is taken from amendment type and eid. tables.sql also updated to create the amendment data, tweaked icons.svg to remove hardcoded-colours for flip_[vh]

This commit is contained in:
2025-10-15 23:06:05 +11:00
parent 9cf47f4582
commit 80ceb7aaed
5 changed files with 175 additions and 88 deletions

View File

@@ -161,13 +161,13 @@
c4.142,0,7.5-3.357,7.5-7.5S339.642,328,335.5,328z"/>
<g style="fill:#00000025;" transform="matrix(16, 0, 0, 16, 120, 115)"><path d="M4.502 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/><path d="M14.002 13a2 2 0 0 1-2 2h-10a2 2 0 0 1-2-2V5A2 2 0 0 1 2 3a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v8a2 2 0 0 1-1.998 2zM14 2H4a1 1 0 0 0-1 1h9.002a2 2 0 0 1 2 2v7A1 1 0 0 0 15 11V3a1 1 0 0 0-1-1zM2.002 4a1 1 0 0 0-1 1v8l2.646-2.354a.5.5 0 0 1 .63-.062l2.66 1.773 3.71-3.71a.5.5 0 0 1 .577-.094l1.777 1.947V5a1 1 0 0 0-1-1h-10z"/></g>
</svg>
<svg id="flip_h" fill="currentColor" viewBox='0 0 512 512'>
<svg id="flip_h" viewBox='0 0 512 512'>
<path fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32' d='M304 48l112 112-112 112M398.87 160H96M208 464L96 352l112-112M114 352h302'/>
</svg>
<svg id="flip_v" fill="currentColor" viewBox='0 0 512 512'>
<svg id="flip_v" viewBox='0 0 512 512'>
<path fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32' d='M464 208L352 96 240 208M352 113.13V416M48 304l112 112 112-112M160 398V96'/>
</svg>
<svg id="fullscreen" fill="currentColor" viewBox="0 0 16 16">
<svg id="fullscreen" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M5.828 10.172a.5.5 0 0 0-.707 0l-4.096 4.096V11.5a.5.5 0 0 0-1 0v3.975a.5.5 0 0 0 .5.5H4.5a.5.5 0 0 0 0-1H1.732l4.096-4.096a.5.5 0 0 0 0-.707zm4.344 0a.5.5 0 0 1 .707 0l4.096 4.096V11.5a.5.5 0 1 1 1 0v3.975a.5.5 0 0 1-.5.5H11.5a.5.5 0 0 1 0-1h2.768l-4.096-4.096a.5.5 0 0 1 0-.707zm0-4.344a.5.5 0 0 0 .707 0l4.096-4.096V4.5a.5.5 0 1 0 1 0V.525a.5.5 0 0 0-.5-.5H11.5a.5.5 0 0 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 0 .707zm-4.344 0a.5.5 0 0 1-.707 0L1.025 1.732V4.5a.5.5 0 0 1-1 0V.525a.5.5 0 0 1 .5-.5H4.5a.5.5 0 0 1 0 1H1.732l4.096 4.096a.5.5 0 0 1 0 .707z"/>
</svg>
<svg id="unknown_ftype" fill="grey" viewBox="0 0 16 16">

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -213,44 +213,82 @@ function DetailsDBox()
}
// DoSel is called when a click event occurs, and sets the selection via adding
// DoSel is called when a click event occurs, and sets the selection via adding
// 'highlight' to the class of the appropriate thumbnails
// e == event (can see if shift/ctrl held down while left-clicking
// el == element the click is on
// this allows single-click to select, ctrl-click to (de)select 1 item, and
// shift-click to add all elements between highlighted area and clicked area,
// whether you click after highlight or before
function DoSel(e, el)
{
if( e.ctrlKey || document.fake_ctrl === 1 )
{
$(el).toggleClass('highlight')
if( document.fake_ctrl === 1 )
document.fake_ctrl=0
return
}
if( e.shiftKey || document.fake_shift === 1 )
{
st=Number($('.highlight').first().attr('ecnt'))
end=Number($('.highlight').last().attr('ecnt'))
clicked=Number($(el).attr('ecnt'))
// if we shift-click first element, then st/end are NaN, so just highlightthe one clicked
if( isNaN(st) )
{
$('.entry').slice( clicked, clicked+1 ).addClass('highlight')
return
}
if( clicked > end )
$('.entry').slice( end, clicked+1 ).addClass('highlight')
else
$('.entry').slice( clicked, st ).addClass('highlight')
// shift-click to add all elements between highlighted area and clicked el,
// whether you click before highlight or after, or inside a gap and then back
// or forward to the closest higlighted entry - also, only works on entry class,
// so it ignores figures that we take entry off while we transform, etc it
function DoSel(e, el) {
const id = $(el).attr('id');
const entries = $('.entry');
if( document.fake_shift === 1 )
document.fake_shift=0
return
// Collect currently highlighted entries
const currentHighlights = $('.highlight');
const highlighted = new Set();
currentHighlights.each(function() {
highlighted.add($(this).attr('id'));
});
// Ctrl+click: toggle highlight for the clicked entry
if (e.ctrlKey || document.fake_ctrl === 1) {
$(el).toggleClass('highlight');
if (highlighted.has(id)) {
highlighted.delete(id);
} else {
highlighted.add(id);
}
if (document.fake_ctrl === 1) {
document.fake_ctrl = 0;
}
return;
}
// Shift+click: select a range
else if (e.shiftKey || document.fake_shift === 1) {
if (currentHighlights.length === 0) {
// If no highlights, just highlight the clicked entry
$(el).addClass('highlight');
highlighted.add(id);
} else {
// Find the nearest highlighted entry
const clickedIndex = entries.index($(el));
let nearestHighlightIndex = -1;
let minDistance = Infinity;
currentHighlights.each(function() {
const highlightIndex = entries.index($(this));
const distance = Math.abs(highlightIndex - clickedIndex);
if (distance < minDistance) {
minDistance = distance;
nearestHighlightIndex = highlightIndex;
}
});
// Highlight the range between the nearest highlighted entry and the clicked entry
const from = Math.min(clickedIndex, nearestHighlightIndex);
const to = Math.max(clickedIndex, nearestHighlightIndex);
for (let i = from; i <= to; i++) {
const entryId = entries.eq(i).attr('id');
highlighted.add(entryId);
entries.eq(i).addClass('highlight');
}
}
if (document.fake_shift === 1) {
document.fake_shift = 0;
}
return;
}
// Single click: clear all highlights and highlight the clicked entry
else {
$('.highlight').removeClass('highlight');
highlighted.clear();
$(el).addClass('highlight');
highlighted.add(id);
}
$('.highlight').removeClass('highlight')
$(el).addClass('highlight')
}
// if a selection exists, enable move & del/restore buttons otherwise disable them
@@ -323,7 +361,7 @@ function NoSel() {
* ecnt - Entry counter (e.g., { val: 0 }).
* returns {string} - Generated HTML string.
*/
function addFigure( obj, last, ecnt)
function addFigure( obj, last, ecnt )
{
let html = "";
@@ -383,6 +421,24 @@ function addFigure( obj, last, ecnt)
}
$('#figures').append( html )
// check if there is a pending amendment for this entry, if so mark it up
// (e.g. its being deleted, rotated, etc) - details in the am obj
for (const am of document.amendments)
{
if( am.eid == obj.id )
{
$('#'+obj.id).find('img.thumb').attr('style', 'filter: grayscale(100%);' )
$('#'+obj.id).removeClass('entry')
html='<img class="position-absolute top-50 start-50 translate-middle" height="60" src="/internal/white-circle.png">'
html+='<img class="position-absolute top-50 start-50 translate-middle" height="64" src="/internal/throbber.gif">'
if( am.type.which == 'icon' )
html+=`<svg class="position-absolute top-50 start-50 translate-middle" height="32" style="color:${am.type.colour}" fill="${am.type.colour}"><use xlink:href="/internal/icons.svg#${am.type.what}"></use></svg>`
else
html+=`<img class="position-absolute top-50 start-50 translate-middle" src="/internal/${am.type.what}?v={{js_vers['r270']}}" height="32">`
$('#'+obj.id).find('a').append(html)
}
}
return
}
@@ -613,7 +669,7 @@ function getPage(pageNumber, successCallback, viewingIdx=0)
type: 'POST', url: '/get_entries_by_ids',
data: JSON.stringify(data), contentType: 'application/json',
dataType: 'json',
success: function(res) { getEntriesByIdSuccessHandler( res, pageNumber, successCallback, viewingIdx ) },
success: function(res) { document.amendments=res.amend; getEntriesByIdSuccessHandler( res.entries, pageNumber, successCallback, viewingIdx ) },
error: function(xhr, status, error) { console.error("Error:", error); } });
return
}