Put new functionality in to allow choosing existing folder in move code - it goes back and forwards 7 days from the date of this file and finds matching files and uses those dirs, or just dirname matches for those dates and offers them up. Also improved Move code to reject dodgy paths
This commit is contained in:
5
TODO
5
TODO
@@ -4,8 +4,6 @@
|
||||
|
||||
* remember last import dir, so you can just go straight back to it
|
||||
|
||||
* offer similar existing folders (based on date range +/- say 2 days)
|
||||
|
||||
* in Fullscreen mode and next/prev dropped out of FS when calling /viewlist route
|
||||
-- only way to fix this, is for when we POST to viewlist, it returns json, and we never leave /view/X
|
||||
-- then we can stay on-page, and stay in FS and then just call ViewImageOrVide()
|
||||
@@ -18,9 +16,6 @@
|
||||
* why .xcf is seen as a video???
|
||||
- actually only 1 is... I think if type == 'Unknown' then do file display and use ? as the image again
|
||||
|
||||
* maybe strip unnecessary / at end of directory name. i think i have left behind empty folders, e.g. check switzerland and austria
|
||||
- also should allow move to existing folder soon...
|
||||
|
||||
* add an option on the person menu to run_ai_on all photos (or at least import/storage)
|
||||
|
||||
* when hitting back button to a search, it doesnt handle the post, etc.
|
||||
|
||||
42
files.py
42
files.py
@@ -1,6 +1,6 @@
|
||||
from wtforms import SubmitField, StringField, HiddenField, validators, Form
|
||||
from flask_wtf import FlaskForm
|
||||
from flask import request, render_template, redirect, send_from_directory, url_for
|
||||
from flask import request, render_template, redirect, send_from_directory, url_for, jsonify
|
||||
from path import MovePathDetails
|
||||
from main import db, app, ma
|
||||
from sqlalchemy import Sequence
|
||||
@@ -18,6 +18,7 @@ import cv2
|
||||
import time
|
||||
import re
|
||||
import json
|
||||
import datetime
|
||||
from flask_login import login_required, current_user
|
||||
from options import Options
|
||||
|
||||
@@ -615,3 +616,42 @@ def _jinja2_filter_toplevelfolderof(path, cwd):
|
||||
@app.template_filter('ParentPath')
|
||||
def _jinja2_filter_parentpath(path):
|
||||
return os.path.dirname(path)
|
||||
|
||||
###############################################################################
|
||||
# route to allow the Move Dialog Box to pass a date (YYYYMMDD) and returns a
|
||||
# json? list of existing dir names that could be near it in time. Starting
|
||||
# simple, by using YYYYMM-1, YYYYMM, YYYYMM+1 dirs
|
||||
###############################################################################
|
||||
@app.route("/getexistingpaths/<dt>", methods=["POST"])
|
||||
@login_required
|
||||
def GetExistingPathsAsDiv(dt):
|
||||
dir_ft=FileType.query.filter(FileType.name=='Directory').first()
|
||||
dirs_arr=[]
|
||||
for delta in range(-7, 8):
|
||||
new_dtime=datetime.datetime.strptime(dt, "%Y%m%d") + datetime.timedelta(days=delta)
|
||||
new_dt=new_dtime.strftime('%Y%m%d')
|
||||
dirs_arr+=Dir.query.distinct(Dir.rel_path).filter(Dir.rel_path.ilike('%'+new_dt+'%')).all();
|
||||
dirs_arr+=Dir.query.distinct(Dir.rel_path).join(EntryDirLink).join(Entry).filter(Entry.type_id!=dir_ft.id).filter(Entry.name.ilike('%'+new_dt+'%')).all()
|
||||
|
||||
# remove duplicates from array
|
||||
dirs = set(dirs_arr)
|
||||
|
||||
# turn DB output into json and return it to the f/e
|
||||
ret='[ '
|
||||
first_dir=1
|
||||
for dir in dirs:
|
||||
print( f"process dir matching for {new_dt} => {dir}")
|
||||
if not first_dir:
|
||||
ret +=", "
|
||||
bits=dir.rel_path.split('-')
|
||||
|
||||
ret+= '{ '
|
||||
ret+= '"prefix":"' + bits[0] + '", '
|
||||
if len(bits)>1:
|
||||
ret+= '"suffix":"' + bits[1] + '"'
|
||||
else:
|
||||
ret+= '"suffix":"''"'
|
||||
ret+= ' } '
|
||||
first_dir=0
|
||||
ret+= ' ]'
|
||||
return ret
|
||||
|
||||
@@ -37,6 +37,22 @@ function change_rp_sel()
|
||||
$('#move_path_type').val( $('option:selected', '#rp_sel').attr('path_type') )
|
||||
}
|
||||
|
||||
function GetExistingDirsAsDiv( dt, divname )
|
||||
{
|
||||
$.ajax({
|
||||
type: 'POST', data: null, url: '/getexistingpaths/'+dt,
|
||||
success: function(data) {
|
||||
$('#'+divname).html(data)
|
||||
dirs = JSON.parse(data)
|
||||
s=''
|
||||
dirs.forEach( function(item, index) {
|
||||
s+= '<button class="btn btn-outline-primary" type="button" onClick="$(\'#prefix\').val(\''+item.prefix+'\'); $(\'#suffix\').val(\''+item.suffix+'\');return false;">'+item.prefix+'/'+item.suffix+'</button>'
|
||||
} )
|
||||
$('#'+divname).html(s)
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
// show the DBox for a move file, includes all thumbnails of selected files to move
|
||||
// and a pre-populated folder to move them into, with text field to add a suffix
|
||||
function MoveDBox(path_details, db_url)
|
||||
@@ -53,6 +69,8 @@ function MoveDBox(path_details, db_url)
|
||||
div+=GetSelnAsDiv()
|
||||
yr=$('.highlight').first().attr('yr')
|
||||
dt=$('.highlight').first().attr('date')
|
||||
div+='<div class="col-12">Use Existing:</div><div id="existing"></div>'
|
||||
GetExistingDirsAsDiv( dt, "existing" )
|
||||
div+=`
|
||||
<div class="input-group my-3">
|
||||
<alert class="alert alert-primary my-auto py-1">
|
||||
@@ -71,7 +89,7 @@ function MoveDBox(path_details, db_url)
|
||||
div+="value="+yr+'/'+dt+"-"
|
||||
div+=`
|
||||
"></input>
|
||||
<input type="text" name="suffix" class="form-control" placeholder="name"> </input>
|
||||
<input id="suffix" type="text" name="suffix" class="form-control" placeholder="name"> </input>
|
||||
</div>
|
||||
<div class="form-row col-12 mt-2">
|
||||
<button onClick="$('#dbox').modal('hide'); return false;" class="btn btn-outline-secondary offset-1 col-2">Cancel</button>
|
||||
|
||||
@@ -1650,6 +1650,15 @@ def JobMoveFiles(job):
|
||||
JobProgressState( job, "In Progress" )
|
||||
prefix=[jex.value for jex in job.extra if jex.name == "prefix"][0]
|
||||
suffix=[jex.value for jex in job.extra if jex.name == "suffix"][0]
|
||||
# Sanity check, if prefix starts with /, reject it -> no /etc/shadow potentials
|
||||
# Sanity check, if .. in prefix or suffix, reject it -> no ../../etc/shadow potentials
|
||||
# Sanity check, if // in prefix or suffix, reject it -> not sure code wouldnt try to make empty dirs, and I dont want to chase /////// cases, any 2 in a row is enough to reject
|
||||
if '..' in prefix or '..' in suffix or prefix[0] == '/' or '//' in prefix or '//' in suffix:
|
||||
FinishJob( job, f"ERROR: Not processing move as the paths contain illegal chars", "Failed" )
|
||||
return
|
||||
# also remove unecessary slashes, jic
|
||||
prefix=prefix.rstrip('/')
|
||||
suffix=suffix.lstrip('/').rstrip('/')
|
||||
path_type=[jex.value for jex in job.extra if jex.name == "move_path_type"][0]
|
||||
rel_path=[jex.value for jex in job.extra if jex.name == "rel_path"][0]
|
||||
dst_storage_path = session.query(Path).filter(Path.path_prefix=='static/' + path_type + '/'+ rel_path).first()
|
||||
|
||||
Reference in New Issue
Block a user