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:
2022-01-20 17:25:01 +11:00
parent 5461cb4036
commit 78acb9bd66
5 changed files with 132 additions and 76 deletions

4
TODO
View File

@@ -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"])

View File

@@ -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

View File

@@ -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

118
states.py
View File

@@ -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
else:
self.folders=True
self.noo="A to Z"
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
else:
self.folders=True
self.noo="A to Z"
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
else:
self.folders=False
self.noo="Oldest"
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.path_type = 'Import'
self.paths = SettingsIPath()
elif 'files_sp' in url:
if self.path_type == "View":
self.orig_ptype = 'Storage'
else:
self.path_type = 'Storage'
elif 'files_rbp' in url:
if self.path_type == "View":
self.orig_ptype = 'Bin'
else:
self.path_type = 'Bin'
elif 'search' in url:
# 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.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:
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.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"
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,11 +158,16 @@ 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()
# now save pref
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 )
# 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
@@ -148,6 +176,8 @@ class Options(PA):
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()

View File

@@ -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>