big clean up of Options -> States, total rework, now actually handles pa_user_state -> States as Import/Storage/Bin/Search or View. If Search has orig_search_term saved. If view, has orig_ptype (and orig_search_term if orig_ptype is Search) -- removed OPT.paths -> these are now worked out when we GetEntries based on pa_user_state. This now allows us to GET all URLs for image viewing allowing me to use the back-button without issues in PROD - well we will see once I commit :)
This commit is contained in:
4
TODO
4
TODO
@@ -1,14 +1,12 @@
|
||||
## GENERAL
|
||||
* for below.. make Options( request )
|
||||
- know that a view is a "path", dont rely on orig_url
|
||||
- remove all "Options()" that are not set by a user-choice in the F/E and just make sure new "Options" sets all defaults as needed
|
||||
-- viewlist can work out new view_eids server side, and pass them back as json data
|
||||
- can consider an optim-- new_view page makes calls to viewlist to ADD json data only, so only trigger a new "viewlist" if we dont have data for that part of the eids
|
||||
|
||||
* going forward into search page (and probably all POSTs) does not work
|
||||
don't render_template instead do a redirect to a GET of the new, or list? for del...
|
||||
files.py:@app.route("/view/<id>", methods=["POST"])
|
||||
- first pass -- fails on storage in prod (view_eids was NONE, but prefs had content, odd... ALSO in dev, it did have a list but the img we were viewing was not in the list!
|
||||
[DONE] files.py:@app.route("/view/<id>", methods=["POST"])
|
||||
files.py:@app.route("/viewlist", methods=["POST"])
|
||||
-- this will need a total rewrite for viewer to handle fullscreen across offset/size boundaries so fix that instead
|
||||
job.py:@app.route("/jobs", methods=["GET", "POST"])
|
||||
|
||||
51
files.py
51
files.py
@@ -20,7 +20,7 @@ import re
|
||||
import json
|
||||
import datetime
|
||||
from flask_login import login_required, current_user
|
||||
from states import Options
|
||||
from states import States
|
||||
|
||||
################################################################################
|
||||
# Local Class imports
|
||||
@@ -28,7 +28,7 @@ from states import Options
|
||||
from job import Job, JobExtra, Joblog, NewJob
|
||||
from path import PathType, Path
|
||||
from person import Refimg, Person, PersonRefimgLink
|
||||
from settings import Settings
|
||||
from settings import Settings, SettingsIPath, SettingsSPath, SettingsRBPath
|
||||
from shared import SymlinkName
|
||||
from dups import Duplicates
|
||||
from face import Face, FaceFileLink, FaceRefimgLink
|
||||
@@ -238,8 +238,8 @@ def GetEntriesInFolderView( OPT, prefix ):
|
||||
################################################################################
|
||||
def GetEntries( OPT ):
|
||||
entries=[]
|
||||
if OPT.path_type == 'Search':
|
||||
search_term=OPT.search_term
|
||||
if OPT.path_type == 'Search' or (OPT.path_type == 'View' and OPT.orig_ptype=='Search'):
|
||||
search_term=OPT.orig_search_term
|
||||
if 'AI:' in search_term:
|
||||
search_term = search_term.replace('AI:','')
|
||||
all_entries = Entry.query.join(File).join(FaceFileLink).join(Face).join(FaceRefimgLink).join(Refimg).join(PersonRefimgLink).join(Person).filter(Person.tag.ilike(f"%{search_term}%")).order_by(File.year.desc(),File.month.desc(),File.day.desc(),Entry.name).offset(OPT.offset).limit(OPT.how_many).all()
|
||||
@@ -269,7 +269,25 @@ def GetEntries( OPT ):
|
||||
all_entries.append(a)
|
||||
return all_entries
|
||||
|
||||
for path in OPT.paths:
|
||||
# if we are a view, then it will be of something else, e.g. a list of
|
||||
# import, storage, or bin images, reset OPT.path_type so that the paths array below works
|
||||
if 'View' in OPT.path_type:
|
||||
eid = OPT.url[6:]
|
||||
print( f"we have a view, eid={eid}" )
|
||||
#e=Entry.query.get(eid)
|
||||
#OPT.path_type=e.in_dir.in_path.type.name
|
||||
print( f"pt={OPT.orig_ptype}, st={OPT.orig_search_term}" )
|
||||
OPT.path_type= OPT.orig_ptype
|
||||
|
||||
paths = []
|
||||
if OPT.path_type == 'Storage':
|
||||
paths = SettingsSPath()
|
||||
elif OPT.path_type == 'Import':
|
||||
paths = SettingsIPath()
|
||||
elif OPT.path_type == 'Bin':
|
||||
paths.append(SettingsRBPath())
|
||||
|
||||
for path in paths:
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
prefix = SymlinkName(OPT.path_type,path,path+'/')
|
||||
@@ -295,7 +313,7 @@ def clear_jm_msg(id):
|
||||
@app.route("/file_list_ip", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def file_list_ip():
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
# 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("/file_list_ip")
|
||||
@@ -308,7 +326,7 @@ def file_list_ip():
|
||||
@app.route("/files_ip", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def files_ip():
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
# 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")
|
||||
@@ -323,7 +341,7 @@ def files_ip():
|
||||
@app.route("/files_sp", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def files_sp():
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
# 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")
|
||||
@@ -339,7 +357,7 @@ def files_sp():
|
||||
@app.route("/files_rbp", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def files_rbp():
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
# 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_rbp")
|
||||
@@ -356,7 +374,7 @@ def files_rbp():
|
||||
@app.route("/search/<search_term>", methods=["GET"])
|
||||
@login_required
|
||||
def search(search_term):
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
OPT.search_term = search_term
|
||||
# always show flat results for search to start with
|
||||
OPT.folders=False
|
||||
@@ -510,7 +528,7 @@ def move_files():
|
||||
@app.route("/viewlist", methods=["POST"])
|
||||
@login_required
|
||||
def viewlist():
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
# Get next/prev set of data - e.g. if next set, then it will use orig_url
|
||||
# to go forward how_many from offset and then use viewer.html to show that
|
||||
# first obj of the new list of entries
|
||||
@@ -551,22 +569,19 @@ def viewlist():
|
||||
@login_required
|
||||
@app.route("/view/<id>", methods=["GET"])
|
||||
def view(id):
|
||||
OPT=Options( request )
|
||||
OPT=States( request )
|
||||
objs = {}
|
||||
print( OPT )
|
||||
entries=GetEntries( OPT )
|
||||
eids=""
|
||||
for e in entries:
|
||||
print( f"in loop deal with: {e.id}")
|
||||
objs[e.id]=e
|
||||
eids += f"{e.id},"
|
||||
# if this is a dir, we wont view it with a click anyway, so move on...
|
||||
if not e.file_details:
|
||||
print( f"seems {e.name} is not a file? -- {e.type}" )
|
||||
continue
|
||||
# put locn data back into array format
|
||||
for face in e.file_details.faces:
|
||||
face.locn = json.loads(face.locn)
|
||||
print("now render the viewer" )
|
||||
eids=eids.rstrip(",")
|
||||
return render_template("viewer.html", current=int(id), eids=eids, objs=objs, OPT=OPT )
|
||||
|
||||
@@ -576,7 +591,9 @@ def view(id):
|
||||
@app.route("/view/<id>", methods=["POST"])
|
||||
@login_required
|
||||
def view_img_post(id):
|
||||
OPT=Options( request )
|
||||
# set pa_user_states...
|
||||
OPT=States( request )
|
||||
# then use back-button friendly URL (and use pa_user_states to view the right image in the right list
|
||||
return redirect( "/view/" + id );
|
||||
|
||||
# route called from front/end - if multiple images are being transformed, each transorm == a separate call
|
||||
|
||||
2
main.py
2
main.py
@@ -54,8 +54,8 @@ Compress(app)
|
||||
|
||||
################################# Now, import separated class files ###################################
|
||||
from ai import aistats
|
||||
from settings import Settings
|
||||
from files import Entry, GetJM_Message, ClearJM_Message
|
||||
from settings import Settings
|
||||
from person import Person
|
||||
from job import Job, GetNumActiveJobs
|
||||
from user import PAUser
|
||||
|
||||
138
states.py
138
states.py
@@ -23,79 +23,102 @@ class PA_UserState(db.Model):
|
||||
fullscreen = db.Column(db.Boolean, unique=False, nullable=False )
|
||||
root = db.Column(db.String, unique=False, nullable=False )
|
||||
cwd = db.Column(db.String, unique=False, nullable=False )
|
||||
## for now being lazy and not doing a separate table until I settle on needed fields and when
|
||||
# only used if ptype == View
|
||||
view_eid = db.Column(db.Integer, unique=False, nullable=False )
|
||||
orig_ptype = db.Column(db.String, unique=False, nullable=False )
|
||||
# only used if view and orig_ptype was search
|
||||
orig_search_term = db.Column(db.String, unique=False, nullable=False )
|
||||
|
||||
def __repr__(self):
|
||||
return f"<pa_user_dn: {self.pa_user_dn}, path_type: {self.path_type}, noo: {self.noo}, grouping: {self.grouping}, how_many: {self.how_many}, st_offset: {self.st_offset}, size: {self.size}, folders: {self.folders}, root: {self.root}, cwd: {self.cwd}>"
|
||||
return f"<pa_user_dn: {self.pa_user_dn}, path_type: {self.path_type}, noo: {self.noo}, grouping: {self.grouping}, how_many: {self.how_many}, st_offset: {self.st_offset}, size: {self.size}, folders: {self.folders}, root: {self.root}, cwd: {self.cwd}, view_eid: {self.view_eid}, orig_ptype: {self.orig_ptype}, orig_search_term: {self.orig_search_term}>"
|
||||
|
||||
|
||||
################################################################################
|
||||
# Options: class to store set of default values for viewing (order/size, etc.)
|
||||
# States: class to store 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, paths, fullscreen, search, etc.
|
||||
################################################################################
|
||||
class Options(PA):
|
||||
class States(PA):
|
||||
def __init__(self, request):
|
||||
self.path_type=''
|
||||
self.url = request.path
|
||||
|
||||
# this occurs ONLY when a POST to /view/<id> occurs (at this stage orig_url will be from an import, storage, bin or search)
|
||||
if 'orig_url' in request.form:
|
||||
self.path_type='View'
|
||||
# use orig url to define defaults/look up states for 'last' import/storage/bin/search
|
||||
url = request.form['orig_url']
|
||||
# get the eid out of the url /view/<id>
|
||||
self.view_eid = request.path[6:]
|
||||
else:
|
||||
url = request.path
|
||||
self.orig_url=url
|
||||
if 'files_sp' in url:
|
||||
self.path_type = 'Storage'
|
||||
self.paths = SettingsSPath()
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).first()
|
||||
if pref:
|
||||
self.folders=pref.folders
|
||||
self.noo=pref.noo
|
||||
self.view_eid = None
|
||||
|
||||
if 'files_ip' in url or 'file_list_ip' in url:
|
||||
if self.path_type == "View":
|
||||
self.orig_ptype = 'Import'
|
||||
else:
|
||||
self.folders=True
|
||||
self.noo="A to Z"
|
||||
self.path_type = 'Import'
|
||||
elif 'files_sp' in url:
|
||||
if self.path_type == "View":
|
||||
self.orig_ptype = 'Storage'
|
||||
else:
|
||||
self.path_type = 'Storage'
|
||||
elif 'files_rbp' in url:
|
||||
self.path_type = 'Bin'
|
||||
self.paths = []
|
||||
self.paths.append(SettingsRBPath())
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).first()
|
||||
if pref:
|
||||
self.folders=pref.folders
|
||||
self.noo=pref.noo
|
||||
if self.path_type == "View":
|
||||
self.orig_ptype = 'Bin'
|
||||
else:
|
||||
self.folders=True
|
||||
self.noo="A to Z"
|
||||
self.path_type = 'Bin'
|
||||
elif 'search' in url:
|
||||
self.path_type = 'Search'
|
||||
self.paths = None
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).first()
|
||||
if pref:
|
||||
self.folders=pref.folders
|
||||
self.noo=pref.noo
|
||||
# okay if we are a search, but came from a view then get last_search_state form prefs and use it
|
||||
if self.path_type == "View":
|
||||
last_search_state = PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type=='Search').first()
|
||||
self.orig_search_term = last_search_state.orig_search_term
|
||||
self.orig_ptype = 'Search'
|
||||
else:
|
||||
self.folders=False
|
||||
self.noo="Oldest"
|
||||
self.orig_search_term = url[8:]
|
||||
self.path_type = 'Search'
|
||||
elif 'view' in url:
|
||||
# use url to get eid of viewed entry
|
||||
self.view_eid = self.url[6:]
|
||||
self.path_type="View"
|
||||
else:
|
||||
print( f"ERROR: DDP messed up, failed to match URL {url} for settings this will fail, redirecting to home" )
|
||||
return
|
||||
|
||||
if self.path_type == 'View':
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type,PA_UserState.view_eid==self.view_eid).first()
|
||||
else:
|
||||
self.path_type = 'Import'
|
||||
self.paths = SettingsIPath()
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).first()
|
||||
if pref:
|
||||
self.folders=pref.folders
|
||||
self.noo=pref.noo
|
||||
else:
|
||||
self.folders=False
|
||||
self.noo="Oldest"
|
||||
|
||||
if pref:
|
||||
self.folders=pref.folders
|
||||
self.noo=pref.noo
|
||||
self.grouping=pref.grouping
|
||||
self.how_many=pref.how_many
|
||||
self.offset=pref.st_offset
|
||||
self.size=pref.size
|
||||
self.root=pref.root
|
||||
self.cwd=pref.cwd
|
||||
self.orig_ptype=pref.orig_ptype
|
||||
self.orig_search_term=pref.orig_search_term
|
||||
else:
|
||||
self.folders=False
|
||||
self.noo="Oldest"
|
||||
self.grouping="None"
|
||||
self.how_many="50"
|
||||
self.offset="0"
|
||||
self.size="128"
|
||||
self.root='static/' + self.path_type
|
||||
if self.path_type == "View":
|
||||
self.root='static/' + self.orig_ptype
|
||||
else:
|
||||
self.root='static/' + self.path_type
|
||||
self.cwd=self.root
|
||||
if not hasattr(self, 'orig_ptype'):
|
||||
self.orig_ptype=None
|
||||
if not hasattr(self, 'orig_search_term'):
|
||||
self.orig_search_term=None
|
||||
|
||||
|
||||
# the above are defaults, if we are here, then we have current values, use them instead if they are set -- AI: searches dont set them so then we use those in the DB first
|
||||
@@ -135,22 +158,29 @@ class Options(PA):
|
||||
if 'next' in request.form:
|
||||
self.offset += int(self.how_many)
|
||||
|
||||
pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).first()
|
||||
if not pref:
|
||||
pref=PA_UserState( pa_user_dn=current_user.dn, path_type=self.path_type, noo=self.noo, grouping=self.grouping, how_many=self.how_many,
|
||||
st_offset=self.offset, size=self.size, folders=self.folders, root=self.root, cwd=self.cwd )
|
||||
else:
|
||||
pref.noo=self.noo
|
||||
pref.grouping=self.grouping
|
||||
pref.how_many=self.how_many
|
||||
pref.st_offset=self.offset
|
||||
pref.size=self.size
|
||||
pref.folders=self.folders
|
||||
pref.root = self.root
|
||||
pref.cwd = self.cwd
|
||||
# now save pref
|
||||
if not pref:
|
||||
# if there is an PA_UserState( pa_user_dn=current_user.dn, # path_type=self.path_type ), then its for a different view_eid and we are viewing, delete it before we insert the new
|
||||
old_pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type).delete()
|
||||
pref=PA_UserState( pa_user_dn=current_user.dn, path_type=self.path_type, view_eid=self.view_eid, noo=self.noo, grouping=self.grouping, how_many=self.how_many,
|
||||
st_offset=self.offset, size=self.size, folders=self.folders, root=self.root, cwd=self.cwd, orig_ptype=self.orig_ptype, orig_search_term=self.orig_search_term )
|
||||
else:
|
||||
pref.pa_user_dn=current_user.dn
|
||||
pref.path_type=self.path_type
|
||||
pref.view_eid=self.view_eid
|
||||
pref.noo=self.noo
|
||||
pref.grouping=self.grouping
|
||||
pref.how_many=self.how_many
|
||||
pref.st_offset=self.offset
|
||||
pref.size=self.size
|
||||
pref.folders=self.folders
|
||||
pref.root = self.root
|
||||
pref.cwd = self.cwd
|
||||
pref.orig_ptype = self.orig_ptype
|
||||
pref.orig_search_term = self.orig_search_term
|
||||
|
||||
db.session.add(pref)
|
||||
db.session.commit()
|
||||
db.session.add(pref)
|
||||
db.session.commit()
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -15,7 +15,18 @@
|
||||
<tbody>
|
||||
{% for st in states %}
|
||||
<tr>
|
||||
<td>{{st.path_type}}</td>
|
||||
<td>{{st.path_type}}
|
||||
{% if st.path_type == 'Search' %}
|
||||
"{{st.orig_search_term}}"
|
||||
{% endif %}
|
||||
{% if st.path_type == 'View' %}
|
||||
(orig: id={{st.view_eid}} in {{st.orig_ptype}})
|
||||
{% if st.orig_ptype == 'Search' %}
|
||||
"{{st.orig_search_term}}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
<td>{{st.noo}}</td>
|
||||
<td>{{st.how_many}}</td>
|
||||
<td>{{st.folders}}</td>
|
||||
|
||||
Reference in New Issue
Block a user