Converted to python flask #1
|
@ -2,11 +2,10 @@
|
|||
import os, json, secrets
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
# Lib imports
|
||||
from flask import Flask
|
||||
from flask_oidc import OpenIDConnect
|
||||
from flask_login import current_user, login_user, logout_user, LoginManager
|
||||
from flask_bcrypt import Bcrypt
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
@ -41,10 +40,7 @@ app.config.update({
|
|||
'OIDC_TOKEN_TYPE_HINT': 'access_token'
|
||||
})
|
||||
|
||||
|
||||
login_manager = LoginManager(app)
|
||||
bcrypt = Bcrypt(app)
|
||||
oidc = OpenIDConnect(app)
|
||||
oidc = OpenIDConnect(app)
|
||||
def oidc_loggedin():
|
||||
return oidc.user_loggedin
|
||||
app.jinja_env.globals['oidc_loggedin'] = oidc_loggedin
|
||||
|
@ -66,9 +62,7 @@ def retrieveSettings():
|
|||
config = retrieveSettings()
|
||||
|
||||
|
||||
from .forms import LoginForm, RegisterForm
|
||||
from .models import db, Favorites, Settings, User
|
||||
|
||||
from .models import db, Favorites, Settings
|
||||
db.init_app(app)
|
||||
with app.app_context(): db.create_all()
|
||||
from webfm import routes
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, PasswordField, SubmitField
|
||||
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
|
||||
from .models import User
|
||||
|
||||
|
||||
|
||||
|
@ -14,12 +13,4 @@ class RegisterForm(FlaskForm):
|
|||
submit = SubmitField("Sign Up")
|
||||
|
||||
def validate_username(self, username):
|
||||
user = User.query.filter_by(username=username.data).first()
|
||||
if user:
|
||||
raise ValidationError("User exists already! Please use a different name!")
|
||||
|
||||
|
||||
class LoginForm(FlaskForm):
|
||||
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=24)])
|
||||
password = PasswordField('Password', validators=[DataRequired(), Length(min=8, max=32)])
|
||||
submit = SubmitField("Login")
|
||||
pass
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
# System imports
|
||||
|
||||
# Lib imports
|
||||
from flask_login.mixins import UserMixin
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
# App imports
|
||||
from . import app, login_manager
|
||||
from . import app
|
||||
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
return User.query.get(int(user_id))
|
||||
|
||||
|
||||
class Favorites(db.Model):
|
||||
link = db.Column(db.String, nullable=False, unique=True)
|
||||
|
@ -22,19 +17,10 @@ class Favorites(db.Model):
|
|||
def __repr__(self):
|
||||
return f"['{self.link}', '{self.id}']"
|
||||
|
||||
class Settings(db.Model, UserMixin):
|
||||
class Settings(db.Model):
|
||||
key = db.Column(db.String, nullable=False)
|
||||
value = db.Column(db.String, nullable=False)
|
||||
id = db.Column(db.Integer, nullable=False, primary_key=True, unique=True, autoincrement=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"['{self.key}', '{self.value}', '{self.id}']"
|
||||
|
||||
|
||||
class User(db.Model, UserMixin):
|
||||
username = db.Column(db.String, unique=True, nullable=False)
|
||||
password = db.Column(db.String, nullable=False)
|
||||
id = db.Column(db.Integer, primary_key=True, unique=True, autoincrement=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"['{self.username}', '{self.email}', '{self.password}', '{self.id}']"
|
||||
|
|
|
@ -22,20 +22,20 @@
|
|||
|
||||
#file-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(14em, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(22em, 1fr));
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 1em;
|
||||
margin: 2em auto;
|
||||
width: 85%;
|
||||
overflow-y: auto;
|
||||
max-height: 25em;
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
#path { max-width: inherit; }
|
||||
#faves-list > li { width: 100%; }
|
||||
|
||||
#video-container {
|
||||
width: 30em;
|
||||
width: inherit;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,16 @@
|
|||
}
|
||||
|
||||
|
||||
#volumeIcon {
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
#volumeIcon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* CLASSES */
|
||||
.scroller {
|
||||
|
@ -63,6 +73,13 @@
|
|||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.volume-control-positioner {
|
||||
position: absolute;
|
||||
bottom: 2em;
|
||||
right: 50%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.dir-style, .video-style, .file-style {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
@ -84,6 +101,7 @@
|
|||
|
||||
.image-style,
|
||||
.video-style {
|
||||
position: relative;
|
||||
min-height: 6.5em;
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
|
@ -151,7 +169,10 @@
|
|||
}
|
||||
|
||||
.video-title {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0em;
|
||||
bottom: 1em;
|
||||
margin-top: 5.5em;
|
||||
background-color: rgba(0, 0, 0, 0.64);
|
||||
color: rgb(255, 255, 255);
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
/* Vertical slider */
|
||||
input[type=range][orient=vertical] {
|
||||
writing-mode: bt-lr; /* IE */
|
||||
-webkit-appearance: slider-vertical; /* WebKit */
|
||||
width: 8px;
|
||||
height: 175px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#video-container::-webkit-media-controls {
|
||||
display:none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#video-container::-webkit-media-controls-enclosure {
|
||||
display:none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,13 @@ const doAjax = (actionPath, data, action) => {
|
|||
// xhttp.open("POST", formatURL(actionPath), true);
|
||||
xhttp.open("POST", actionPath, true);
|
||||
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
|
||||
if (action === "list-files") {
|
||||
xhttp.setRequestHeader("Cache-Control", "no-cache, no-store");
|
||||
xhttp.setRequestHeader("Pragma", "no-cache");
|
||||
xhttp.setRequestHeader("Expires", "0");
|
||||
}
|
||||
|
||||
// Force return to be JSON NOTE: Use application/xml to force XML
|
||||
xhttp.overrideMimeType('application/json');
|
||||
xhttp.send(data);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
let fullScreenState = 0;
|
||||
let shouldPlay = null;
|
||||
let clicktapwait = 200;
|
||||
let shouldPlay = null;
|
||||
let controlsTimeout = null;
|
||||
let canHideControls = true;
|
||||
|
||||
|
||||
document.body.onload = (eve) => {
|
||||
|
@ -21,102 +23,6 @@ document.body.onload = (eve) => {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function togglePlay(video) {
|
||||
shouldPlay = setTimeout(function () {
|
||||
shouldPlay = null;
|
||||
if (video.paused) {
|
||||
video.play();
|
||||
} else {
|
||||
video.pause();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function toggleFullscreen(video) {
|
||||
containerElm = document.getElementById("video-container");
|
||||
parentElm = video.parentElement;
|
||||
|
||||
|
||||
if (video.requestFullscreen) {
|
||||
parentElm.requestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.webkitRequestFullscreen) { /* Safari */
|
||||
parentElm.webkitRequestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.msRequestFullscreen) { /* IE11 */
|
||||
parentElm.msRequestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
}
|
||||
|
||||
if (fullScreenState == 2) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.webkitExitFullscreen) { /* Safari */
|
||||
document.webkitExitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.msExitFullscreen) { /* IE11 */
|
||||
document.msExitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
}
|
||||
|
||||
fullScreenState = 0;
|
||||
}
|
||||
|
||||
fullScreenState += 1;
|
||||
}
|
||||
|
||||
$("#video-viewer").on("click", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$("#video-viewer").on("touchend", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$( "#video-viewer" ).bind( "timeupdate", async function(eve) {
|
||||
const video = eve.target;
|
||||
const seekto = document.getElementById("seek-slider");
|
||||
const vt = video.currentTime * (100 / video.duration);
|
||||
seekto.value = vt;
|
||||
});
|
||||
|
||||
$( "#seek-slider" ).bind( "change", async function(eve) {
|
||||
const slider = eve.target;
|
||||
let video = document.getElementById("video-viewer");
|
||||
let seekto = video.duration * (slider.value / 100);
|
||||
video.currentTime = seekto;
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$( "#search-files-field" ).bind( "keyup", async function(eve) {
|
||||
searchPage();
|
||||
});
|
||||
|
|
|
@ -72,7 +72,8 @@ const updateHTMLDirList = async (data) => {
|
|||
|
||||
// Setup background if there is a 000.* in selection
|
||||
if (background_image.match(/000\.(jpg|png|gif)\b/) != null) {
|
||||
background_image = formatURL("files/" + images[i][1]);
|
||||
// Due to same hash for 000 we add date to make link unique for each run to bypass cache issues...
|
||||
background_image = formatURL("files/" + images[i][1] + '?d=' + Date.now());
|
||||
updateBackground(background_image, false);
|
||||
} else {
|
||||
background_image = formatURL("static/imgs/backgrounds/particles.mp4");
|
||||
|
@ -119,7 +120,7 @@ const updateHTMLDirList = async (data) => {
|
|||
hash = images[i][1];
|
||||
|
||||
if (thumbnail.match(/000\.(jpg|png|gif)\b/) == null &&
|
||||
!thumbnail.includes("favicon.png")) {
|
||||
!thumbnail.includes("favicon.png") && !thumbnail.includes("000")) {
|
||||
const clone = imgClone.cloneNode(true);
|
||||
createElmBlock(insertArea, clone, thumbnail, title, hash);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,11 @@ const scrollFilesToTop = () => {
|
|||
|
||||
|
||||
const showMedia = async (hash, extension, type) => {
|
||||
document.getElementById("image-viewer").style.display = "none";
|
||||
document.getElementById("text-viewer").style.display = "none";
|
||||
document.getElementById("video-viewer").style.display = "none";
|
||||
document.getElementById("pdf-viewer").style.display = "none";
|
||||
document.getElementById("image-viewer").style.display = "none";
|
||||
document.getElementById("text-viewer").style.display = "none";
|
||||
document.getElementById("pdf-viewer").style.display = "none";
|
||||
document.getElementById("video-viewer").style.display = "none";
|
||||
document.getElementById("video-controls").style.display = "none";
|
||||
|
||||
if (type === "video") {
|
||||
setupVideo(hash, extension);
|
||||
|
@ -34,9 +35,10 @@ const showMedia = async (hash, extension, type) => {
|
|||
|
||||
const setupVideo = async (hash, extension) => {
|
||||
let video = document.getElementById("video-viewer");
|
||||
let controls = document.getElementById("video-controls");
|
||||
video.poster = "static/imgs/icons/loading.gif";
|
||||
video.autoplay = true;
|
||||
video.style.display = "";
|
||||
video.src = "#"
|
||||
video_path = "files/" + hash;
|
||||
|
||||
try {
|
||||
|
@ -46,7 +48,7 @@ const setupVideo = async (hash, extension) => {
|
|||
if ( data.hasOwnProperty('path') ) {
|
||||
video_path = data.path;
|
||||
} else {
|
||||
displayMessage(data.message.text, data.message.type)
|
||||
displayMessage(data.message.text, data.message.type);
|
||||
return ;
|
||||
}
|
||||
} else if ((/\.(flv|mov|m4v|mpg|mpeg)$/i).test(extension)) {
|
||||
|
@ -56,19 +58,20 @@ const setupVideo = async (hash, extension) => {
|
|||
}
|
||||
}
|
||||
|
||||
if ((/\.(flv|f4v)$/i).test(extension)) {
|
||||
$('#file-view-modal').modal({"focus": true, "show": true});
|
||||
video.src = video_path;
|
||||
} else {
|
||||
// This is questionable in usage since it loads the full video before
|
||||
// showing; but, seeking doesn't work otherwise...
|
||||
$('#file-view-modal').modal({"focus": true, "show": true});
|
||||
let response = await fetch(formatURL(video_path));
|
||||
let vid_src = URL.createObjectURL(await response.blob()); // IE10+
|
||||
video.src = vid_src;
|
||||
}
|
||||
$('#file-view-modal').modal({"focus": true, "show": true});
|
||||
controls.style.display = "none";
|
||||
video.src = video_path;
|
||||
// if ((/\.(flv|f4v)$/i).test(extension)) {
|
||||
// video.src = video_path;
|
||||
// } else {
|
||||
// // This is questionable in usage since it loads the full video before
|
||||
// showing; but, seeking doesn't work otherwise...
|
||||
// let response = await fetch(formatURL(video_path));
|
||||
// let vid_src = URL.createObjectURL(await response.blob()); // IE10+
|
||||
// video.src = vid_src;
|
||||
// video.src = video_path;
|
||||
// }
|
||||
} catch (e) {
|
||||
video.src = "#";
|
||||
video.style.display = "none";
|
||||
console.log(e);
|
||||
}
|
||||
|
@ -103,9 +106,8 @@ const setupFile = async (hash, extension) => {
|
|||
}
|
||||
|
||||
if (type == "text") {
|
||||
console.log(hash);
|
||||
let response = await fetch(formatURL("files/" + hash));
|
||||
let textData = await response.text(); // IE10+
|
||||
let response = await fetch(formatURL("files/" + hash));
|
||||
let textData = await response.text(); // IE10+
|
||||
viewer.innerText = textData;
|
||||
}
|
||||
|
||||
|
@ -177,14 +179,16 @@ const disableEdit = (elm) => {
|
|||
|
||||
const updateBackground = (srcLink, isvideo = true) => {
|
||||
try {
|
||||
let elm = document.getElementById("bg");
|
||||
|
||||
console.log(srcLink);
|
||||
if (isvideo) {
|
||||
let elm = document.getElementById("bg");
|
||||
if (elm.getAttribute('src') === "") {
|
||||
elm.src = srcLink;
|
||||
}
|
||||
} else {
|
||||
document.getElementById("bg").src = "";
|
||||
document.getElementById("bg").setAttribute("poster", srcLink);
|
||||
elm.src = "";
|
||||
elm.setAttribute("poster", srcLink);
|
||||
}
|
||||
} catch (e) { }
|
||||
}
|
||||
|
@ -223,3 +227,34 @@ const clearChildNodes = (parent) => {
|
|||
parent.removeChild(parent.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
//Cache Buster
|
||||
const clearCache = () => {
|
||||
var rep = /.*\?.*/,
|
||||
links = document.getElementsByTagName('link'),
|
||||
scripts = document.getElementsByTagName('script'),
|
||||
links = document.getElementsByTagName('video'),
|
||||
process_scripts = false;
|
||||
|
||||
for (var i=0; i<links.length; i++) {
|
||||
var link = links[i],
|
||||
href = link.href;
|
||||
if(rep.test(href)) {
|
||||
link.href = href+'&'+Date.now();
|
||||
} else {
|
||||
link.href = href+'?'+Date.now();
|
||||
}
|
||||
|
||||
}
|
||||
if(process_scripts) {
|
||||
for (var i=0; i<scripts.length; i++) {
|
||||
var script = scripts[i],
|
||||
src = script.src;
|
||||
if(rep.test(src)) {
|
||||
script.src = src+'&'+Date.now();
|
||||
} else {
|
||||
script.src = src+'?'+Date.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
const getTimeFormatted = (duration = null) => {
|
||||
if (duration == null) { return "00:00"; }
|
||||
|
||||
let hours = (duration / 3600).toFixed(2).split(".")[0];
|
||||
let minutes = (duration / 60).toFixed(2).split(".")[0];
|
||||
let time = (duration / 60).toFixed(2)
|
||||
let seconds = Math.floor( (time - Math.floor(time) ) * 60);
|
||||
|
||||
return hours + ":" + minutes + ":" + seconds;
|
||||
}
|
||||
|
||||
const pauseVideo = () => {
|
||||
const video = document.getElementById("video-viewer");
|
||||
video.style.cursor = '';
|
||||
video.pause();
|
||||
}
|
||||
|
||||
const togglePlay = (video) => {
|
||||
shouldPlay = setTimeout(function () {
|
||||
let controls = document.getElementById("video-controls");
|
||||
shouldPlay = null;
|
||||
if (video.paused) {
|
||||
video.style.cursor = 'none';
|
||||
controls.style.display = "none";
|
||||
video.play();
|
||||
} else {
|
||||
video.style.cursor = '';
|
||||
controls.style.display = "";
|
||||
video.pause();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
const toggleFullscreen = (video) => {
|
||||
containerElm = document.getElementById("video-container");
|
||||
parentElm = video.parentElement;
|
||||
|
||||
if (video.requestFullscreen) {
|
||||
parentElm.requestFullscreen();
|
||||
video.style.cursor = 'none';
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.webkitRequestFullscreen) { /* Safari */
|
||||
parentElm.webkitRequestFullscreen();
|
||||
video.style.cursor = 'none';
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.msRequestFullscreen) { /* IE11 */
|
||||
parentElm.msRequestFullscreen();
|
||||
video.style.cursor = 'none';
|
||||
containerElm.style.display = "block";
|
||||
}
|
||||
|
||||
if (fullScreenState == 2) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
video.style.cursor = '';
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.webkitExitFullscreen) { /* Safari */
|
||||
document.webkitExitFullscreen();
|
||||
video.style.cursor = '';
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.msExitFullscreen) { /* IE11 */
|
||||
document.msExitFullscreen();
|
||||
video.style.cursor = '';
|
||||
containerElm.style.display = "contents";
|
||||
}
|
||||
|
||||
fullScreenState = 0;
|
||||
}
|
||||
|
||||
fullScreenState += 1;
|
||||
}
|
||||
|
||||
const toggleVolumeControl = () => {
|
||||
const volume = document.getElementById("volume-slider");
|
||||
if (volume.style.display === "none") {
|
||||
volume.style.display = "";
|
||||
} else {
|
||||
volume.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
const showControls = () => {
|
||||
const video = document.getElementById("video-viewer");
|
||||
const controls = document.getElementById("video-controls");
|
||||
|
||||
video.style.cursor = '';
|
||||
controls.style.display = "";
|
||||
if (controlsTimeout) {
|
||||
clearTimeout(controlsTimeout);
|
||||
}
|
||||
|
||||
controlsTimeout = setTimeout(function () {
|
||||
if (!video.paused) {
|
||||
if (canHideControls) {
|
||||
video.style.cursor = 'none';
|
||||
controls.style.display = "none";
|
||||
controlsTimeout = null;
|
||||
} else {
|
||||
showControls();
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
||||
$("#video-viewer").on("loadedmetadata", function(eve){
|
||||
let video = eve.target;
|
||||
let videoDuration = document.getElementById("videoDuration");
|
||||
videoDuration.innerText = getTimeFormatted(video.duration);
|
||||
});
|
||||
|
||||
$("#video-viewer").on("click", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$("#video-viewer").on("touchend", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$( "#video-viewer" ).bind( "timeupdate", async function(eve) {
|
||||
let videoDuration = document.getElementById("videoCurrentTime");
|
||||
const video = eve.target;
|
||||
const seekto = document.getElementById("seek-slider");
|
||||
const vt = video.currentTime * (100 / video.duration);
|
||||
|
||||
seekto.value = vt;
|
||||
videoDuration.innerText = getTimeFormatted(video.currentTime);
|
||||
});
|
||||
|
||||
$( "#seek-slider" ).bind( "change", async function(eve) {
|
||||
const slider = eve.target;
|
||||
let video = document.getElementById("video-viewer");
|
||||
let seekto = video.duration * (slider.value / 100);
|
||||
video.currentTime = seekto;
|
||||
});
|
||||
|
||||
$( "#volume-slider" ).bind( "change", async function(eve) {
|
||||
const slider = eve.target;
|
||||
let video = document.getElementById("video-viewer");
|
||||
let volumeto = slider.value;
|
||||
video.volume = volumeto;
|
||||
|
||||
});
|
||||
|
||||
$( "#video-controls" ).bind( "mouseenter", async function(eve) { canHideControls = false; });
|
||||
$( "#video-controls" ).bind( "mouseleave", async function(eve) { canHideControls = true; });
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
{% block body_header_additional %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/base.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css')}}">
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap-table.min.css')}}">
|
||||
|
@ -36,7 +37,7 @@
|
|||
|
||||
<button title="File viewer..." class="btn btn-secondary btn-sm"
|
||||
data-toggle="modal" data-target="#file-view-modal">🖼</button>
|
||||
{% if current_user.is_authenticated or oidc_loggedin() %}
|
||||
{% if oidc_loggedin() %}
|
||||
<a href="/logout">
|
||||
<button title="Logout..." class="btn btn-danger btn-sm">
|
||||
Logout
|
||||
|
@ -110,31 +111,48 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>File Viewer:</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<button type="button" onclick="pauseVideo()" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body text-center justify-content-center">
|
||||
<div class="row">
|
||||
<div class="col scroller" style="max-height: 30em; overflow: auto;">
|
||||
<div class="col scroller" style="max-height: 70vh; overflow: auto;">
|
||||
<!-- For video -->
|
||||
<div id="video-container" style="display: contents;">
|
||||
<div id="video-container">
|
||||
<video id="video-viewer"
|
||||
loop
|
||||
src=""
|
||||
autoplay=""
|
||||
loop
|
||||
poster="{{ url_for('static', filename='imgs/icons/loading.gif')}}">
|
||||
volume="0.75"
|
||||
poster="{{ url_for('static', filename='imgs/icons/loading.gif')}}"
|
||||
onmousemove="showControls()">
|
||||
</video>
|
||||
<div id="video-controls">
|
||||
<input id="seek-slider" type="range" min="0" max="100" step="1">
|
||||
</div>
|
||||
|
||||
<div id="video-controls">
|
||||
<div class="row pl-5 pr-5">
|
||||
<div class="col-md-8">
|
||||
<input id="seek-slider" class="form-control-range" type="range" min="0" value="0" max="100" step="1"/>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<span id="videoCurrentTime"></span>
|
||||
/
|
||||
<span id="videoDuration"></span>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<span id="volumeIcon" onclick="toggleVolumeControl()">🔈</span>
|
||||
<input id="volume-slider" class="form-control-range volume-control-positioner" style="display: none;"
|
||||
type="range" orient="vertical" min="0.0" max="1.0" value="0.75" step="0.05" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- For image -->
|
||||
<img id="image-viewer"
|
||||
style="width: 40em; height: auto; display: none;"
|
||||
style="width: inherit; height: auto; display: none;"
|
||||
src="" alt="" />
|
||||
|
||||
<!-- For pdf -->
|
||||
|
@ -152,14 +170,14 @@
|
|||
|
||||
<!-- For text -->
|
||||
<pre id="text-viewer"
|
||||
style="width: 45em; height: auto; display: none;">
|
||||
style="width: inherit; height: auto; display: none;">
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" data-dismiss="modal" class="btn btn-danger btn-sm">Close</button>
|
||||
<button onclick="pauseVideo()" type="button" data-dismiss="modal" class="btn btn-danger btn-sm">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -263,4 +281,5 @@
|
|||
<script src="{{ url_for('static', filename='js/ajax.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/ui-logic.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/events.js')}}"></script>
|
||||
<script src="{{ url_for('static', filename='js/video-events.js')}}"></script>
|
||||
{% endblock body_scripts_additional %}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap.min.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap-datepicker.css')}}">
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css')}}">
|
||||
{% block header_css_additional %}
|
||||
{% endblock header_css_additional %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -126,7 +126,6 @@ class FileManager:
|
|||
|
||||
def returnPathPartFromHash(self, partHash):
|
||||
hashes = [self.dotHash, self.dotdotHash]
|
||||
print(self.pathParts)
|
||||
path = "/".join(self.pathParts)
|
||||
pathPart = None
|
||||
for f in listdir(path):
|
||||
|
|
Loading…
Reference in New Issue