Browse Source

update file listing interface

master
cinnaboot 7 years ago
parent
commit
5ca2374c5d
  1. 1
      .gitignore
  2. 12
      video_metadata/static/style.css
  3. 29
      video_metadata/templates/file_listing/index.html
  4. 2
      video_metadata/templates/tmdb/query.html
  5. 56
      video_metadata/views/file_listing.py
  6. 6
      video_metadata/views/tmdb.py

1
.gitignore vendored

@ -1,2 +1,3 @@
instance/*
__pycache__/
tags

12
video_metadata/static/style.css

@ -8,22 +8,16 @@ nav h1 { flex: auto; margin: 0; }
nav h1 a { text-decoration: none; padding: 0.25rem 0.5rem; }
nav ul { display: flex; list-style: none; margin: 0; padding: 0; }
nav ul li a, nav ul li span, header .action { display: block; padding: 0.5rem; }
.flash { margin: 1em 0; padding: 1em; background: #cae6f6; border: 1px solid #377ba8; }
.content { padding: 0 1rem 1rem; }
.content > header { border-bottom: 1px solid lightgray; display: flex; align-items: flex-end; }
.content > header h1 { flex: auto; margin: 1rem 0 0.25rem 0; }
.flash { margin: 1em 0; padding: 1em; background: #cae6f6; border: 1px solid #377ba8; }
.post > header { display: flex; align-items: flex-end; font-size: 0.85em; }
.post > header > div:first-of-type { flex: auto; }
.post > header h1 { font-size: 1.5em; margin-bottom: 0; }
.post .about { color: slategray; font-style: italic; }
.post .body { white-space: pre-line; }
.content:last-child { margin-bottom: 0; }
.content form { margin: 1em 0; display: flex; flex-direction: column; }
.content label { font-weight: bold; margin-bottom: 0.5em; }
.content input, .content textarea { margin-bottom: 1em; }
.content textarea { min-height: 12em; resize: vertical; }
input { color: #333; background-color: #eee; }
input.danger { color: #cc2f2e; }
input[type=submit] { align-self: start; min-width: 10em; }
.debug { background: lightgrey; padding: 1em; overflow: auto; border: 1px solid darkgrey }
.search_result { max-width: 400px; padding: 1em; background: aquamarine; }
.arrow_submit { width: 3em; font-weight: bold; }
.content li { list-style: ' - '; }

29
video_metadata/templates/file_listing/index.html

@ -5,9 +5,28 @@
{% endblock %}
{% block content %}
<ul>
{% for file in filenames %}
<li><span>! </span><a href="{{ url_for('tmdb.query_movie') }}?query={{ file|urlencode() }}">{{ file }}</a></li>
{% endfor %}
</ul>
<ul>
{% for path in paths recursive %}
<li>
{% if path.is_dir %}
<span>{{ path.base_name }}</span>
{% else %}
<form action="{{ url_for('tmdb.query_movie') }}" method="post">
<span>{{ path.base_name }}</span>
<input type="hidden" name="base_name" value="{{ path.base_name }}" />
<input type="hidden" name="full_path" value="{{ path.full_path }}" />
<input class="arrow_submit" type="submit" value="->" />
</form>
{% endif %}
{% if path.contents %}
<ul>{{ loop(path.contents) }}</ul>
{% endif %}
</li>
{% endfor %}
</ul>
<div class="debug">
<h3>Debug Info</h3>
<pre>{{ debug_str }}</pre>
</div>
{% endblock %}

2
video_metadata/templates/tmdb/query.html

@ -5,7 +5,7 @@
{% endblock %}
{% block content %}
{% if view_data.raw_query_str == '' %}
{% if view_data|length == 0 %}
<form method="get">
<label for="query">Search for movie</label>
<input name="query" id="query">

56
video_metadata/views/file_listing.py

@ -1,12 +1,64 @@
import os
import yaml
from flask import Blueprint, current_app, render_template
VIDEO_EXTENSIONS = ['.avi', '.m4v', '.mkv', '.mp4', '.mpg']
MAX_RECURSE_DEPTH = 5
bp = Blueprint('file_listing', __name__)
class path_entry:
def __init__(self):
self.base_name = ''
self.full_path = ''
self.file_extension = ''
self.is_dir = False
self.depth = 0
self.contents = []
@bp.route('/file_listing')
def index():
# construct tree of path_entry objects
video_path = current_app.config['MOVIE_DIR']
filenames = os.listdir(video_path)
return render_template('file_listing/index.html', filenames=filenames)
paths = []
for entry in os.scandir(video_path):
p = getPathInfo(entry)
if p:
paths.append(p)
return render_template(
'file_listing/index.html',
paths=paths,
debug_str=yaml.dump(paths)
)
def getPathInfo(entry, depth=0):
if not entry.name.startswith('.') and not entry.is_symlink():
pe = path_entry()
pe.base_name = entry.name
pe.path = entry.path
pe.is_dir = entry.is_dir()
pe.depth = depth
# TODO: add relative path for http server root links as 'full_path'
if entry.is_file():
ext = os.path.splitext(entry)[1]
if ext in VIDEO_EXTENSIONS:
pe.file_extension = ext
else:
return None
elif entry.is_dir() and depth < MAX_RECURSE_DEPTH:
for e in os.scandir(entry):
p = getPathInfo(e, depth + 1)
if p:
pe.contents.append(p)
return pe
return None

6
video_metadata/views/tmdb.py

@ -77,7 +77,7 @@ class view_result(object):
####################
# flask routes
@bp.route('/query_movie')
@bp.route('/query_movie', methods=['GET', 'POST'])
def query_movie():
errors = []
query = query_data()
@ -86,7 +86,9 @@ def query_movie():
query.tmdb_api_key = current_app.config['TMDB_API_KEY']
# NOTE: query string can be submitted from a link or form input
if 'query' in request.form:
if 'base_name' in request.form:
query.raw_query_str = request.form['base_name']
elif 'query' in request.form:
query.raw_query_str = request.form['query']
elif 'query' in request.args:
query.raw_query_str = request.args['query']

Loading…
Cancel
Save