diff --git a/files.py b/files.py index 009a0b2..6340401 100644 --- a/files.py +++ b/files.py @@ -33,8 +33,8 @@ from face import Face, FaceFileLink, FaceRefimgLink # pylint: disable=no-member ################################################################################ -# Class describing File in the database, and via sqlalchemy, connected to the DB as well -# This has to match one-for-one the DB table +# Class describing PathDirLink and in the DB (via sqlalchemy) +# connects the entry (dir) with a path ################################################################################ class PathDirLink(db.Model): __tablename__ = "path_dir_link" @@ -44,6 +44,10 @@ class PathDirLink(db.Model): def __repr__(self): return f"" +################################################################################ +# Class describing EntryDirLInk and in the DB (via sqlalchemy) +# connects (many) entry contained in a directory (which is also an entry) +################################################################################ class EntryDirLink(db.Model): __tablename__ = "entry_dir_link" entry_id = db.Column(db.Integer, db.ForeignKey("entry.id"), primary_key=True ) @@ -52,6 +56,12 @@ class EntryDirLink(db.Model): def __repr__(self): return f"" +################################################################################ +# Class describing Dir and in the DB (via sqlalchemy) +# rel_path: rest of dir after path, e.g. if path = /..../storage, then +# rel_path could be 2021/20210101-new-years-day-pics +# in_path: only in this structure, not DB, quick ref to the path this dir is in +################################################################################ class Dir(db.Model): __tablename__ = "dir" eid = db.Column(db.Integer, db.ForeignKey("entry.id"), primary_key=True ) @@ -61,6 +71,14 @@ class Dir(db.Model): def __repr__(self): return f"" +################################################################################ +# Class describing Entry and in the DB (via sqlalchemy) +# an entry is the common bits between files and dirs +# type is a convenience var only in this class, not in DB +# {dir|file}_etails are convenience data for the relevant details from the Dir +# or File class - not in DB +# in_dir - is the Dir that this entry is located in (convenience for class only) +################################################################################ class Entry(db.Model): __tablename__ = "entry" id = db.Column(db.Integer, db.Sequence('file_id_seq'), primary_key=True ) @@ -74,6 +92,14 @@ class Entry(db.Model): def __repr__(self): return f"" +################################################################################ +# Class describing FileType and in the DB (via sqlalchemy) +# pre-defined list of file types (image, dir, etc.) +################################################################################ class FileType(db.Model): __tablename__ = "file_type" id = db.Column(db.Integer, db.Sequence('file_type_id_seq'), primary_key=True ) @@ -97,6 +127,12 @@ class FileType(db.Model): def __repr__(self): return "".format(self.id, self.name ) +################################################################################ +# Class describing PA_JobManager_Message and in the DB (via sqlalchemy) +# the job manager can send a message back to the front end (this code) via the +# DB. has to be about a specific job_id and is success/danger, etc. (alert) +# and a message +################################################################################ class PA_JobManager_Message(db.Model): __tablename__ = "pa_job_manager_fe_message" id = db.Column(db.Integer, db.Sequence('pa_job_manager_fe_message_id_seq'), primary_key=True ) @@ -108,18 +144,25 @@ class PA_JobManager_Message(db.Model): ################################################################################ -# Local utility functions +# GetJM_Message: used in html to display any message for this front-end ################################################################################ - def GetJM_Message(): msg=PA_JobManager_Message.query.first() return msg +################################################################################ +# ClearJM_Message: used in html to clear any message just displayed +################################################################################ def ClearJM_Message(id): PA_JobManager_Message.query.filter(PA_JobManager_Message.id==id).delete() db.session.commit() return +################################################################################ +# ViewingOptions: defines set of default values for viewing (order/size, etc.) +# and if a request object (from a POST) is passed in, it returns those instead +# it also handles the cwd appropriately +################################################################################ def ViewingOptions( request ): noo="Oldest" grouping="None" @@ -165,6 +208,9 @@ def ViewingOptions( request ): return noo, grouping, how_many, offset, size, folders, cwd, root +################################################################################ +# GetEntriesInFlatView: func. to retrieve DB entries appropriate for flat view +################################################################################ def GetEntriesInFlatView( cwd, prefix, noo, offset, how_many ): entries=[] @@ -178,6 +224,10 @@ def GetEntriesInFlatView( cwd, prefix, noo, offset, how_many ): entries+=Entry.query.join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).filter(Path.path_prefix==prefix).order_by(Entry.name).offset(offset).limit(how_many).all() return entries +################################################################################ +# GetEntriesInFolderView: func. to retrieve DB entries appropriate for folder view +# read inline comments to deal with variations / ordering... +################################################################################ def GetEntriesInFolderView( cwd, prefix, noo, offset, how_many ): entries=[] # okay the root cwd is fake, so treat it specially - its Dir can be found by path with dir.rel_path='' @@ -365,6 +415,11 @@ def scan_sp(): return render_template("base.html") +################################################################################ +# /fix_dups -> use sql to find duplicates based on same hash, different +# filenames, or directories. Pass this straight through to the job manager +# as job extras to a new job. +################################################################################ @app.route("/fix_dups", methods=["POST"]) @login_required def fix_dups(): @@ -391,6 +446,10 @@ def fix_dups(): return render_template("dups.html", DD=DD, pagesize=pagesize ) +################################################################################ +# /rm_dups -> f/e that shows actual duplicates so that we can delete some dups +# this code creates a new job with extras that have hashes/ids to allow removal +################################################################################ @app.route("/rm_dups", methods=["POST"]) @login_required def rm_dups(): @@ -416,6 +475,9 @@ def rm_dups(): return render_template("base.html") +################################################################################ +# /restore_files -> create a job to restore files for the b/e to process +################################################################################ @app.route("/restore_files", methods=["POST"]) @login_required def restore_files(): @@ -428,6 +490,9 @@ def restore_files(): st.SetMessage( f"Created Job #{job.id} to restore selected file(s)") return render_template("base.html") +################################################################################ +# /delete_files -> create a job to delete files for the b/e to process +################################################################################ @app.route("/delete_files", methods=["POST"]) @login_required def delete_files(): @@ -440,6 +505,9 @@ def delete_files(): st.SetMessage( f"Created Job #{job.id} to delete selected file(s)") return render_template("base.html") +################################################################################ +# /move_files -> create a job to move files for the b/e to process +################################################################################ @app.route("/move_files", methods=["POST"]) @login_required def move_files(): @@ -451,6 +519,9 @@ def move_files(): st.SetMessage( f"Created Job #{job.id} to move selected file(s)") return render_template("base.html") +################################################################################ +# /viewnext -> moves to the next entry and grabs data from DB and views it +################################################################################ @app.route("/viewnext", methods=["GET","POST"]) @login_required def viewnext(): @@ -472,6 +543,9 @@ def viewnext(): face.locn = json.loads(face.locn) return render_template("viewer.html", obj=obj, eids=eids, sels=sels ) +################################################################################ +# /viewprev -> moves to the prev entry and grabs data from DB and views it +################################################################################ @app.route("/viewprev", methods=["GET","POST"]) @login_required def viewprev(): @@ -493,6 +567,9 @@ def viewprev(): face.locn = json.loads(face.locn) return render_template("viewer.html", obj=obj, eids=eids, sels=sels ) +################################################################################ +# /view/id -> grabs data from DB and views it +################################################################################ @app.route("/view/", methods=["GET","POST"]) @login_required def view_img(id): @@ -534,6 +611,12 @@ def rotate(): # TODO: make this return data with the job number, then the f/e can poll checkrotatejob return resp +################################################################################ +# /checkrotatejob -> URL that is called repeatedly by front-end waiting for the +# b/e to finish the rotate job. Once done, the new / now +# rotated image's thumbnail is returned so the f/e can +# update with it +################################################################################ @app.route("/checkrotatejob", methods=["POST"]) @login_required def checkrotatejob():