From c4590c4789e8e71013b00960e081f75a0e715d58 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Tue, 10 Sep 2019 06:17:31 -0400 Subject: [PATCH] add new endpoints for async file listing --- video_metadata/templates/base.html | 7 ++- .../file_listing/folder_contents.html | 21 +++++++ video_metadata/views/file_listing.py | 62 +++++++++++++++++-- 3 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 video_metadata/templates/file_listing/folder_contents.html diff --git a/video_metadata/templates/base.html b/video_metadata/templates/base.html index 7fa93b1..dce219e 100644 --- a/video_metadata/templates/base.html +++ b/video_metadata/templates/base.html @@ -1,15 +1,16 @@ - {% block title %}{% endblock %} - video_metadata + {% block title %}{% endblock %} - pvdb diff --git a/video_metadata/templates/file_listing/folder_contents.html b/video_metadata/templates/file_listing/folder_contents.html new file mode 100644 index 0000000..7ceae6c --- /dev/null +++ b/video_metadata/templates/file_listing/folder_contents.html @@ -0,0 +1,21 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}File Listing{% endblock %}

+{% endblock %} + +{% block content %} + +{% endblock %} diff --git a/video_metadata/views/file_listing.py b/video_metadata/views/file_listing.py index fe3a427..5eeb23c 100644 --- a/video_metadata/views/file_listing.py +++ b/video_metadata/views/file_listing.py @@ -1,16 +1,18 @@ import os import re -import yaml -from flask import Blueprint, current_app, render_template +from flask import Blueprint, current_app, escape, flash, render_template +from flask import jsonify + +from .. import util VIDEO_EXTENSIONS = ['.avi', '.m4v', '.mkv', '.mp4', '.mpg'] MAX_RECURSE_DEPTH = 5 -bp = Blueprint('file_listing', __name__) +bp = Blueprint('file_listing', __name__, url_prefix='/file_listing') -class path_entry: +class path_entry(object): def __init__(self): self.base_name = '' self.rel_path = '' # NOTE: fs path relative to config['MOVIE_DIR'] @@ -20,7 +22,7 @@ class path_entry: self.contents = [] -@bp.route('/file_listing') +@bp.route('/') def index(): # construct tree of path_entry objects video_path = current_app.config['MOVIE_DIR'] @@ -34,9 +36,57 @@ def index(): return render_template( 'file_listing/index.html', paths=paths, - debug_str=yaml.dump(paths) + debug_str=util.dumpObject(paths) + ) + + +@bp.route('/folder_contents/') +def getBaseFolderContents(): + full_path = current_app.config['MOVIE_DIR'] + paths = [] + + # validate input + if not os.path.exists(full_path): + flash('invalid path') + else: + for entry in os.scandir(full_path): + paths.append(getPathInfo(entry, MAX_RECURSE_DEPTH)) + + return render_template( + 'file_listing/folder_contents.html', + paths=paths, + debug_str=util.dumpObject(paths) ) + +# NOTE: return a listing of files and directories in a sub_directory as JSON +# @param subpath a path relative to config['MOVIE_DIR'] +@bp.route('/folder_contents/') +def getFolderJSON(subpath = ''): + video_path = current_app.config['MOVIE_DIR'] + full_path = os.path.join(video_path, subpath) + paths = [] + + # validate input + if re.search('\.\.', subpath) or not os.path.exists(full_path): + flash('invalid path') + else: + for entry in os.scandir(full_path): + # TODO: remove 'getPathInfo()' when finished with async file listing + # make sure to continue to test for '.' and symlinks + logger.info(entry) + pe = getPathInfo(entry, MAX_RECURSE_DEPTH) + if pe: + paths.append({ + 'base_name': pe.base_name, + 'rel_path': pe.rel_path, + 'file_extension': pe.file_extension, + 'is_dir': pe.is_dir, + }) + + return jsonify(paths) + + def getPathInfo(entry, depth=0): if not entry.name.startswith('.') and not entry.is_symlink(): video_path = current_app.config['MOVIE_DIR']