added viewing recycle bin via folders, added comments, cleaned up TODO to note this is done
This commit is contained in:
20
TODO
20
TODO
@@ -1,20 +1,13 @@
|
||||
## GENERAL
|
||||
* on start up, should validate the import/storage/recycle bin paths exist and spit an error if they dont
|
||||
* dont process duplicates from Bin
|
||||
* never process duplicates from Bin (allow them to be created on startup so they can be viewed?)
|
||||
|
||||
* issue where someone could call IP .../Imp/photos and SP .../Sto/photos and then static/photos is ambiguous:
|
||||
-- DONE: make path prefix by static/<ptype.name>/ so that files are in: static/<ptype.name>/in_path.pp/dir.rel_path/
|
||||
-- then deleting below would just path_prefix from static/storage to .pa_bin/storage, etc.
|
||||
-- need to create the subdir if it does not exist in recycle_bin_path
|
||||
*** THINK: should bin be a normal path/dir name, and in static too -- I think it will be easier in hindsight -- so need to change dst_dir when os.replace is used
|
||||
-- need to be able to view recycle bin (should be simple when we have path_types) &&& should able to consolidate the files_ip/files_sp/files_rb? route handling functions
|
||||
-- could also allow undelete per file / show content as another Files->View and more like storage (i.e. show folders)
|
||||
* storage_path viewing needs to be by folder / not a big grab bag of files (by default - DONE)
|
||||
-- BUG: issue with view by Day, etc. we print out day even if the Entry is not in the cwd
|
||||
-- TODO: Need to toggle the view if I want, and when viewing storage area, change single-click to be view file again, and right-click to be my context menu
|
||||
* * import_path can be folder view and is DONE but needs toggle as above
|
||||
* need a way for search results to show we found something in import_path or storage_path:
|
||||
- now we can use the in_path, then have a series of icons, e.g. disk for storage, ? for import, and bin for recycling (before the blue path)--maybe even show different colours, e.g. info for import, primary for storage and danger for bin?
|
||||
- now we can use the in_path, then have a series of icons, e.g. disk for storage, ? for import, and bin for recycling
|
||||
-- only show these on the thumbs *IF* we search (where it may not be obvious where it came from)
|
||||
* handle thumbs:
|
||||
- need to ignore *thumb* -- but consider how we do this and don't screw up 'dir/job counts'
|
||||
and potentially other stuff like .pa_bin if its in storage/import folder?
|
||||
@@ -22,6 +15,9 @@
|
||||
* comment your code
|
||||
* more OO goodness :)
|
||||
|
||||
## MAYBE?
|
||||
* can we consolidate the files_ip/files_sp/files_rbp route handling functions???
|
||||
* could also allow undelete per file / show content as another Files->View and more like storage (i.e. show folders)
|
||||
|
||||
## DB
|
||||
Need to think about...
|
||||
@@ -64,9 +60,6 @@
|
||||
need to copy into here the jquery/fa files so we don't need internet to function
|
||||
- for that matter run lightspeed against all this
|
||||
|
||||
file view should have show folders / flat as a choosable somehow
|
||||
|
||||
|
||||
sorter...
|
||||
need some way to multiselect images [DONE]
|
||||
and then get them into a new "folder"
|
||||
@@ -89,4 +82,3 @@
|
||||
* exif processing?
|
||||
* location stuff - test a new photo from my camera out
|
||||
-- image is in dir, need to look at exifread output
|
||||
|
||||
|
||||
31
files.py
31
files.py
@@ -134,8 +134,10 @@ def ViewingOptions( request ):
|
||||
size=128
|
||||
if 'files_sp' in request.path:
|
||||
folders=True
|
||||
# this is the default as 'Storage' is the path_type in the DB
|
||||
cwd='static/Storage'
|
||||
elif 'files_rbp' in request.path:
|
||||
folders=True
|
||||
cwd='static/Bin'
|
||||
else:
|
||||
folders=False
|
||||
cwd=None
|
||||
@@ -220,6 +222,33 @@ def files_sp():
|
||||
entries+=Entry.query.join(Dir).join(EntryDirLink).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(Entry.name).offset(offset).limit(how_many).all()
|
||||
return render_template("files.html", page_title='View Files (Storage Path)', entry_data=entries, noo=noo, grouping=grouping, how_many=how_many, offset=offset, size=size, folders=folders, cwd=cwd, root=root )
|
||||
|
||||
|
||||
################################################################################
|
||||
# /files -> show thumbnail view of files from storage_path
|
||||
################################################################################
|
||||
@app.route("/files_rbp", methods=["GET", "POST"])
|
||||
def files_rbp():
|
||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||
entries=[]
|
||||
|
||||
print( f"cwd={cwd}" )
|
||||
|
||||
# per recyle bin path, add entries to view
|
||||
settings=Settings.query.first()
|
||||
paths = settings.recycle_bin_path.split("#")
|
||||
for path in paths:
|
||||
prefix = SymlinkName("Bin",path,path+'/')
|
||||
|
||||
if noo == "Oldest":
|
||||
entries+=Entry.query.join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(File.year,File.month,File.day,Entry.name).offset(offset).limit(how_many).all()
|
||||
else:
|
||||
entries+=Entry.query.join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(File.year.desc(),File.month.desc(),File.day.desc(),Entry.name).offset(offset).limit(how_many).all()
|
||||
|
||||
entries+=Entry.query.join(Dir).join(EntryDirLink).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(Entry.name).offset(offset).limit(how_many).all()
|
||||
print( f"dirs={Entry.query.join(Dir).join(EntryDirLink).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(Entry.name).offset(offset).limit(how_many).all()}" )
|
||||
return render_template("files.html", page_title='View Files (Bin Path)', entry_data=entries, noo=noo, grouping=grouping, how_many=how_many, offset=offset, size=size, folders=folders, cwd=cwd, root=root )
|
||||
|
||||
|
||||
################################################################################
|
||||
# /search -> show thumbnail view of files from import_path(s)
|
||||
################################################################################
|
||||
|
||||
@@ -495,6 +495,19 @@ def CreateSymlink(job,ptype,path):
|
||||
os.symlink(path, symlink)
|
||||
return symlink
|
||||
|
||||
################################################################################################################################################################
|
||||
#
|
||||
# Key function that runs as part of (usually) an import job. The name of the directory (dirname) is checked to see
|
||||
# if it already is in the database (inside of in_dir in in_path). If it is,
|
||||
# just return the db entry. If not, then we create a new row in Dir, that has name of dirname, has a parent directory
|
||||
# of in_dir (DB object), has the rel_path set to the relative fs path from the actual fs path to this entry (including the dirname)
|
||||
# and the in_path set to the overarching path (one of an Import, Storage or Recycle_bin path in the DB)
|
||||
#
|
||||
# e.g. path on FS: /home/ddp/src/photoassistant/images_to_process/ ... ends in DB as path_prefix="static/Import/images_to_process"
|
||||
# and we have a dir in /home/ddp/src/photoassistant/images_to_process/0000/subtest, then we call:
|
||||
# AddDir( job, dirname='subtest', in_dir=Dir object for '0000', rel_path='0000/subtest', in_path=Path object for 'static/Import/images_to_process' )
|
||||
#
|
||||
################################################################################################################################################################
|
||||
def AddDir(job, dirname, in_dir, rel_path, in_path ):
|
||||
dir=session.query(Dir).join(PathDirLink).join(Path).filter(Path.id==in_path.id).filter(Dir.rel_path==rel_path).first()
|
||||
if dir:
|
||||
@@ -573,16 +586,28 @@ def MoveFileToRecycleBin(job,del_me):
|
||||
os.replace( src, dst )
|
||||
except Exception as e:
|
||||
print( f"Failed to remove file from filesystem - which={src}, err: {e}")
|
||||
bin=session.query(Path).join(PathType).filter(PathType.name=='Bin').first()
|
||||
print("bin={bin}")
|
||||
print("del_me={del_me}")
|
||||
bin_path=session.query(Path).join(PathType).filter(PathType.name=='Bin').first()
|
||||
print( f"bin={bin}")
|
||||
print( f"del_me={del_me}")
|
||||
new_rel_path=del_me.in_dir.in_path.path_prefix.replace('static/','')
|
||||
|
||||
# if there is a relative path on this dir, add it to the new_rel_path as there is only ever 1 Bin path
|
||||
if len(del_me.in_dir.rel_path):
|
||||
new_rel_path += '/' + del_me.in_dir.rel_path
|
||||
print("new_rel_path={new_rel_path}")
|
||||
new_dir = AddDir(job, new_rel_path, None, new_rel_path, bin )
|
||||
print( "new_dir={new_dir}" )
|
||||
|
||||
print( f"new_rel_path={new_rel_path}" )
|
||||
|
||||
parent_dir=session.query(Dir).join(PathDirLink).filter(PathDirLink.path_id==bin_path.id).first()
|
||||
print( f"parent_dir for path={parent_dir}" )
|
||||
part_rel_path=""
|
||||
for dirname in new_rel_path.split("/"):
|
||||
part_rel_path += f"{dirname}"
|
||||
print( f"AddDir( {dirname} in {parent_dir} with {part_rel_path} as pfx ) ")
|
||||
new_dir=AddDir( job, dirname, parent_dir, part_rel_path, bin_path )
|
||||
parent_dir=new_dir
|
||||
part_rel_path += "/"
|
||||
|
||||
print( f"new_dir={new_dir}" )
|
||||
del_me.in_dir = new_dir
|
||||
return
|
||||
|
||||
@@ -688,8 +713,8 @@ def JobImportDir(job):
|
||||
# already create root above to work out num_files for whole os.walk
|
||||
if root != path:
|
||||
pp=SymlinkName( path_obj.type.name, path, root )+'/'+os.path.basename(root)
|
||||
print( F"pp={pp}, root={root}, symlink={symlink}" )
|
||||
rel_path=pp.replace(symlink+'/','')
|
||||
print( f"pp={pp}, root={root}, symlink={symlink}, rel_path={rel_path}" )
|
||||
dir=AddDir(job, os.path.basename(root), parent_dir, rel_path, path_obj)
|
||||
for basename in files:
|
||||
# commit every 100 files to see progress being made but not hammer the database
|
||||
@@ -1005,8 +1030,8 @@ def RemoveDups(job):
|
||||
del_me_lst = []
|
||||
for f in files:
|
||||
if os.path.isfile( f.FullPathOnFS() ) == False:
|
||||
AddLogForJob( job, f"ERROR: (per file del) file (DB id: {f.eid} - {f.FullPathOnFS()}) does not exist? ignorning file")
|
||||
elif f.file_details.eid == int(keeping):
|
||||
AddLogForJob( job, f"ERROR: (per file del) file (DB id: {f.id} - {f.FullPathOnFS()}) does not exist? ignorning file")
|
||||
elif f.id == int(keeping):
|
||||
found = f
|
||||
else:
|
||||
del_me_lst.append(f)
|
||||
@@ -1032,7 +1057,7 @@ def RemoveDups(job):
|
||||
del_me=None
|
||||
for f in files:
|
||||
if os.path.isfile(f.FullPathOnFS()) == False:
|
||||
AddLogForJob( job, f"ERROR: (per path del) file (DB id: {f.eid} - {f.FullPathOnFS()}) does not exist? ignorning file")
|
||||
AddLogForJob( job, f"ERROR: (per path del) file (DB id: {f.id} - {f.FullPathOnFS()}) does not exist? ignorning file")
|
||||
if f.in_dir.eid == int(keeping):
|
||||
found=f
|
||||
else:
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<a class="dropdown-item" href="{{url_for('files_ip')}}">View Photos to Import</a>
|
||||
<a class="dropdown-item" href="{{url_for('file_list_ip')}}">View Details of Photos to Import</a>
|
||||
<a class="dropdown-item" href="{{url_for('files_sp')}}">View Stored Photos</a>
|
||||
<a class="dropdown-item" href="{{url_for('files_rbp')}}">View Recycle Bin</a>
|
||||
</div>
|
||||
</div class="nav-item dropdown">
|
||||
<div class="nav-item dropdown">
|
||||
|
||||
Reference in New Issue
Block a user