diff --git a/files.py b/files.py index 4063fdf..ae00e35 100644 --- a/files.py +++ b/files.py @@ -179,6 +179,7 @@ class FileSchema(ma.SQLAlchemyAutoSchema): class DirSchema(ma.SQLAlchemyAutoSchema): class Meta: model = Dir load_instance = True + eid = ma.auto_field() # Explicitly include eid in_path = ma.Nested(PathSchema) ################################################################################ @@ -404,39 +405,70 @@ def process_ids(): # return entries as json return jsonify(entries_schema.dump(entries)) -### -# query_data = { 'entry_lst': entry_lst, 'query_id': query_id, ... } -### + +################################################################################ +# /get_dir_entries -> show thumbnail view of files from import_path(s) +################################################################################ +@app.route("/get_dir_entries", methods=["POST"]) +@login_required +def get_dir_entries(): + data = request.get_json() # Parse JSON body + dir_id = data.get('dir_id', []) # Extract list of ids + back = data.get('back', False) # Extract back boolean + + # if we are going back, find the parent id and use that instead + if back: + stmt=( select(EntryDirLink.dir_eid).filter(EntryDirLink.entry_id==dir_id) ) + dir_id = db.session.execute(stmt).scalars().all() [0] + + # get content of dir_id + stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) ) + # FIXME: what do we do with ordering anyway??? + #stmt=stmt.order_by(*order_map.get(OPT.noo) ) + ids=db.session.execute(stmt).scalars().all() + entries_schema = EntrySchema(many=True) + entries = Entry.query.filter(Entry.id.in_(ids)).all() + return jsonify(entries_schema.dump(entries)) + +################################################################################ # Call this ONCE on first menu choice of View files, or search box submission +# create the list of entry ids that matcht the required viewing/list +################################################################################ def GetQueryData( OPT ): - query_data = {} + query_data={} query_data['query_id']=None query_data['entry_list']=None - # set up the sql order strings (back in OPT) based on value of noo - # FIXME: remove this for all last/first eid usage AND use order_map - SetOrderStrings( OPT ) - if OPT.path_type == 'Search': print ("NOT YET") return query_data + # always get the top of the (OPT.prefix) Path's eid and keep it for OPT.folders toggling/use + dir_stmt=( select(Entry.id).join(Dir).join(PathDirLink).join(Path).filter(Dir.rel_path == '').filter(Path.path_prefix==OPT.prefix) ) + # this should return the 1 Dir (that we want to see the content of) - and with only 1, no need to worry about order + dir_arr=db.session.execute(dir_stmt).scalars().all() + dir_id=dir_arr[0] + query_data['root_eid']=dir_id + if OPT.folders: - entries, tmp_num_ents = GetEntriesInFolderView( OPT, prefix ) + # start folder view with only the root folder + stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) ) + query_data['entry_list']=db.session.execute(stmt).scalars().all() else: - stmt = ( select(Entry.id).join(File).join(EntryDirLink).join(Dir).join(PathDirLink). - join(Path).filter(Path.path_prefix == OPT.prefix) ) - stmt = stmt.order_by(*order_map.get(OPT.noo) ) + # get every File that is in the OPT.prefix Path + stmt=( select(Entry.id).join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).filter(Path.path_prefix == OPT.prefix) ) + stmt=stmt.order_by(*order_map.get(OPT.noo) ) query_data['entry_list']= db.session.execute(stmt).scalars().all() - # first time we get the data q_offset is 0, current=first one, search never gets here, so search_term='' - # FIXME: Doubt we need cwd -- I only need originals to either invalidate this list, or recreate it... need to think about that a lot more - query = Query( path_type=OPT.path_type, noo=OPT.noo, q_offset=0, folder=OPT.folders, grouping=OPT.grouping, root=OPT.root, cwd=OPT.cwd, search_term='', - entry_list=query_data['entry_list'], current=query_data['entry_list'][0], created=datetime.now(pytz.utc) ) - db.session.add(query) - db.session.commit() - - query_data['query_id']=query.id +# not sure I need this in hindsight - any value at all??? +# # first time we get the data q_offset is 0, current=first one, search never gets here, so search_term='' +# # FIXME: Doubt we need cwd -- I only need originals to either invalidate this list, or recreate it... need to think about that a lot more +# query = Query( path_type=OPT.path_type, noo=OPT.noo, q_offset=0, folder=OPT.folders, grouping=OPT.grouping, root=OPT.root, cwd=OPT.cwd, search_term='', +# entry_list=query_data['entry_list'], current=query_data['entry_list'][0], created=datetime.now(pytz.utc) ) +# db.session.add(query) +# db.session.commit() +# +# query_data['query_id']=query.id return query_data ################################################################################ @@ -519,11 +551,10 @@ def files_ip(): # now we have reset the offset, etc. into the prefs, we can use a GET and this will be back/forward browser button safe if request.method=='POST': redirect("/files_ip") - entries=GetEntries( OPT ) people = Person.query.all() move_paths = MovePathDetails() query_data = GetQueryData( OPT ) - return render_template("files.html", page_title=f"View Files ({OPT.path_type} Path)", entry_data=entries, OPT=OPT, people=people, move_paths=move_paths, query_data=query_data ) + return render_template("files.html", page_title=f"View Files ({OPT.path_type} Path)", OPT=OPT, people=people, move_paths=move_paths, query_data=query_data ) ################################################################################ # /files -> show thumbnail view of files from storage_path @@ -535,10 +566,10 @@ def files_sp(): # now we have reset the offset, etc. into the prefs, we can use a GET and this will be back/forward browser button safe if request.method=='POST': redirect("/files_sp") - entries=GetEntries( OPT ) people = Person.query.all() move_paths = MovePathDetails() - return render_template("files.html", page_title=f"View Files ({OPT.path_type} Path)", entry_data=entries, OPT=OPT, people=people, move_paths=move_paths ) + query_data = GetQueryData( OPT ) + return render_template("files.html", page_title=f"View Files ({OPT.path_type} Path)", OPT=OPT, people=people, move_paths=move_paths, query_data=query_data ) ################################################################################ diff --git a/internal/js/files_support.js b/internal/js/files_support.js index 7881205..e1501c3 100644 --- a/internal/js/files_support.js +++ b/internal/js/files_support.js @@ -351,6 +351,11 @@ function addFigure( obj, last, ecnt) last.printed = obj.file_details.month; } } + /* + {% if not entry_data %} + No matches for: '{{search_term}}' + {% endif %} + */ // Image/Video/Unknown entry if (obj.type.name === "Image" || obj.type.name === "Video" || obj.type.name === "Unknown") { @@ -384,7 +389,7 @@ function addFigure( obj, last, ecnt) html += `
- +
${obj.name}
@@ -394,7 +399,6 @@ function addFigure( obj, last, ecnt) } $('#figures').append( html ) -// console.log( html ) return } @@ -405,7 +409,7 @@ function renderMedia(obj) { const path = `${obj.in_dir.in_path.path_prefix}/${obj.in_dir.rel_path}/${obj.name}`; const thumb = obj.file_details.thumbnail ? `${obj.name}` - : ``; + : ``; let mediaHtml = `
${thumb}`; @@ -413,25 +417,25 @@ function renderMedia(obj) { if (OPT.search_term) { mediaHtml += `
- +
`; } mediaHtml += ` `; } else if (isVideo) { mediaHtml += `
- +
`; if (OPT.search_term) { mediaHtml += `
- +
`; } @@ -452,6 +456,31 @@ function getLocationIcon(obj) { return ICON[obj.in_dir.in_path.type.name] } +// POST to get entry ids, and then getPage for a specified directory +function getDirEntries(dir_id, back) +{ + data={} + data.dir_id=dir_id + data.back=back + + $.ajax({ + type: 'POST', + url: '/get_dir_entries', + data: JSON.stringify(data), // Stringify the data + contentType: 'application/json', // Set content type + dataType: 'json', // Expect JSON response + success: function(res) { + document.entries=res + if( back ) + document.back_id = res[0].in_dir.eid + drawPageOfFigures() + }, + error: function(xhr, status, error) { + console.error("Error:", error); + } + }); +} + // 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() @@ -459,11 +488,44 @@ function drawPageOfFigures() $('#figures').empty() var last = { printed: null } var ecnt=0 + + if( OPT.folders ) + { + if( document.entries.length && document.entries[0].in_dir.rel_path == '' ) + { + gray="_gray" + back="" + cl="" + } + else + { + gray="" + back="Back" + cl="back" + } + // back button, if gray/back decide if we see grayed out folder and/or the name of the folder we go back to + html=`
+
+ + + +
${back}
+
+
` + /* + + */ + $('#figures').append(html) + } for (const obj of document.entries) { addFigure( obj, last, ecnt ) ecnt++ } $('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; }); + $('.figure').dblclick( CallViewRouteWrapper ) + // for dir, getDirEntries 2nd param is back (or "up" a dir) + $(".dir").click( function(e) { document.back_id=this.id; getDirEntries(this.id,false) } ) + $(".back").click( function(e) { getDirEntries(this.id,true) } ) } // Function to get the 'page' of entry ids out of entryList diff --git a/templates/files.html b/templates/files.html index 480bf70..a674349 100644 --- a/templates/files.html +++ b/templates/files.html @@ -24,6 +24,7 @@ var OPT={} OPT.grouping='{{OPT.grouping}}' OPT.cwd='{{OPT.cwd}}' + OPT.root_eid={{query_data.root_eid}} OPT.search_term='{{OPT.orig_search_term}}' OPT.folders="{{OPT.folders}}" === "True" OPT.howMany={{OPT.how_many}} @@ -143,12 +144,7 @@
{% set eids=namespace( str="" ) %} {# gather all the file eids and collect them in case we go gallery mode #} - {% for obj in entry_data %} - {% if obj.type.name != "Directory" %} - {% set eids.str = eids.str + obj.id|string +"," %} - {% endif %} - {% endfor %} - + {% set ecnt=namespace( val=0 ) %}
@@ -320,8 +316,6 @@ function CallViewRoute(id) $(s).appendTo('body').submit(); } -$('.figure').dblclick( CallViewRouteWrapper ) - // different context menu on files $.contextMenu({ selector: '.entry',