Switched from flask-bootstrap to standalone Bootstrap 5 and overhaul of UI
This commit is contained in:
7
app.py
7
app.py
@@ -1,8 +1,7 @@
|
||||
from flask import Flask, current_app, g
|
||||
from flask_bootstrap import Bootstrap
|
||||
from flask_wtf.csrf import CSRFProtect
|
||||
|
||||
from frontend import frontend, nav
|
||||
from frontend import frontend
|
||||
from backend import get_db
|
||||
from os import urandom
|
||||
|
||||
@@ -16,16 +15,12 @@ def init_db():
|
||||
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
Bootstrap(app)
|
||||
|
||||
app.config['BOOTSTRAP_SERVE_LOCAL'] = True
|
||||
app.config['SECRET_KEY'] = urandom(32)
|
||||
app.config['BOOTSTRAP_USE_MINIFIED'] = False
|
||||
CSRFProtect(app)
|
||||
|
||||
app.register_blueprint(frontend)
|
||||
app.app_context().push()
|
||||
nav.init_app(app)
|
||||
|
||||
init_db()
|
||||
|
||||
|
||||
@@ -304,6 +304,7 @@ def yt_download(location, ext='mp3'):
|
||||
|
||||
# if videos are wanted, adjust the options
|
||||
if ext == 'mp4':
|
||||
opts['format'] = 'bestvideo[height<=1080]+bestaudio/best[height<=1080]'
|
||||
opts.pop('format')
|
||||
opts.pop('postprocessors')
|
||||
|
||||
|
||||
@@ -4,6 +4,6 @@ from wtforms.validators import URL, DataRequired, AnyOf
|
||||
|
||||
|
||||
class DownloadForm(FlaskForm):
|
||||
url = URLField('Video, Channel or Playlist', validators=[DataRequired(), URL()], render_kw={'placeholder': 'YouTube Link'})
|
||||
url = URLField('Video, Channel or Playlist', validators=[DataRequired(), URL()], render_kw={'placeholder': 'URL'})
|
||||
ext = SelectField('Type', choices=[('mp3', 'Audio'), ('mp4', 'Video')], validators=[AnyOf(('mp3', 'mp4'))])
|
||||
submit = SubmitField('Go')
|
||||
|
||||
48
frontend.py
48
frontend.py
@@ -1,8 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from flask import Blueprint, request, render_template, flash, send_from_directory
|
||||
from flask_nav3 import Nav
|
||||
from flask_nav3.elements import Navbar, View
|
||||
|
||||
from flask import Blueprint, request, render_template, flash, send_from_directory, send_file
|
||||
|
||||
from forms.download import DownloadForm
|
||||
from backend import zip_folder, downloads_path, enqueue_download
|
||||
@@ -11,20 +10,12 @@ from file_cache import *
|
||||
|
||||
frontend = Blueprint('frontend', __name__)
|
||||
|
||||
nav = Nav()
|
||||
nav.register_element('frontend_top', Navbar(
|
||||
View('ytm-ls', '.index'),
|
||||
View('Downloader', '.downloader'),
|
||||
View('Library', '.library')
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# index has a list of running downloads
|
||||
@frontend.route('/', methods=['GET'])
|
||||
def index():
|
||||
if not running_downloads:
|
||||
flash('Currently, no downloads are running.')
|
||||
flash('Currently, no downloads are running.', 'primary')
|
||||
return render_template('index.html', running_downloads=running_downloads, titles=titles, urls=urls, amount=len(urls))
|
||||
|
||||
|
||||
@@ -52,7 +43,7 @@ def downloader():
|
||||
enqueue_download(url, ext=ext)
|
||||
|
||||
# show download start confirmation
|
||||
flash('Download enqueued and will finish in background.')
|
||||
flash('Download enqueued and will finish in background.', 'primary')
|
||||
return render_template('feedback-simple.html', amount=len(urls))
|
||||
|
||||
|
||||
@@ -84,16 +75,17 @@ def update(url_rowid):
|
||||
enqueue_download(url, update=True)
|
||||
|
||||
# show download start confirmation
|
||||
flash('Update enqueued and will finish in background.')
|
||||
flash('Update enqueued and will finish in background.', 'primary')
|
||||
return render_template('feedback-simple.html', titles=titles, urls=urls, amount=len(urls))
|
||||
|
||||
|
||||
@frontend.route('/library', methods=['GET'])
|
||||
def library():
|
||||
videos = query_db("SELECT name, ext, path FROM video")
|
||||
videos = query_db("SELECT name, ext, path FROM video "
|
||||
"LEFT JOIN collection ON video.id = collection.video WHERE collection.video IS NULL ")
|
||||
playlists = query_db("SELECT name, ROWID FROM playlist")
|
||||
if not playlists and not videos:
|
||||
flash('Library ist currently empty. Try downloading something!')
|
||||
flash('Library ist currently empty. Try downloading something!', 'primary')
|
||||
|
||||
return render_template('library.html', videos=videos, playlists=playlists, amount=len(playlists))
|
||||
|
||||
@@ -106,3 +98,27 @@ def library_playlist():
|
||||
'playlist.ROWID = :playlist',
|
||||
{'playlist': playlist})
|
||||
return render_template('collection.html', videos=videos)
|
||||
|
||||
|
||||
@frontend.route('/player', methods=['GET'])
|
||||
def player():
|
||||
return render_template('video-player.html')
|
||||
|
||||
|
||||
@frontend.route('/serve', methods=['GET'])
|
||||
def serve():
|
||||
file = request.args.get('file', None)
|
||||
if 'audio' in file:
|
||||
file = r'downloads\\CptCatman\\my vital organs all lift together.mp3'
|
||||
return send_file(
|
||||
file,
|
||||
'audio/mpeg',
|
||||
True
|
||||
)
|
||||
else:
|
||||
file = r'downloads\\Rick Astley - Never Gonna Give You Up (Official Music Video).webm'
|
||||
return send_file(
|
||||
file,
|
||||
'video/webm',
|
||||
True
|
||||
)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
flask
|
||||
flask_bootstrap
|
||||
flask_nav3
|
||||
flask_wtf
|
||||
wtforms
|
||||
yt_dlp
|
||||
|
||||
5002
static/bootstrap5/css/bootstrap-grid.css
vendored
Normal file
5002
static/bootstrap5/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap-grid.css.map
Normal file
1
static/bootstrap5/css/bootstrap-grid.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap-grid.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/css/bootstrap-grid.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap-grid.min.css.map
Normal file
File diff suppressed because one or more lines are too long
5001
static/bootstrap5/css/bootstrap-grid.rtl.css
vendored
Normal file
5001
static/bootstrap5/css/bootstrap-grid.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap-grid.rtl.css.map
Normal file
1
static/bootstrap5/css/bootstrap-grid.rtl.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap-grid.rtl.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap-grid.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/css/bootstrap-grid.rtl.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap-grid.rtl.min.css.map
Normal file
File diff suppressed because one or more lines are too long
426
static/bootstrap5/css/bootstrap-reboot.css
vendored
Normal file
426
static/bootstrap5/css/bootstrap-reboot.css
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
background-color: #fff;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
direction: ltr /* rtl:ignore */;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
1
static/bootstrap5/css/bootstrap-reboot.css.map
Normal file
1
static/bootstrap5/css/bootstrap-reboot.css.map
Normal file
File diff suppressed because one or more lines are too long
8
static/bootstrap5/css/bootstrap-reboot.min.css
vendored
Normal file
8
static/bootstrap5/css/bootstrap-reboot.min.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||
1
static/bootstrap5/css/bootstrap-reboot.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap-reboot.min.css.map
Normal file
File diff suppressed because one or more lines are too long
423
static/bootstrap5/css/bootstrap-reboot.rtl.css
vendored
Normal file
423
static/bootstrap5/css/bootstrap-reboot.rtl.css
vendored
Normal file
@@ -0,0 +1,423 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
background-color: #fff;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
direction: ltr ;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
1
static/bootstrap5/css/bootstrap-reboot.rtl.css.map
Normal file
1
static/bootstrap5/css/bootstrap-reboot.rtl.css.map
Normal file
File diff suppressed because one or more lines are too long
8
static/bootstrap5/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
8
static/bootstrap5/css/bootstrap-reboot.rtl.min.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */
|
||||
1
static/bootstrap5/css/bootstrap-reboot.rtl.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap-reboot.rtl.min.css.map
Normal file
File diff suppressed because one or more lines are too long
4752
static/bootstrap5/css/bootstrap-utilities.css
vendored
Normal file
4752
static/bootstrap5/css/bootstrap-utilities.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap-utilities.css.map
Normal file
1
static/bootstrap5/css/bootstrap-utilities.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap-utilities.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap-utilities.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/css/bootstrap-utilities.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap-utilities.min.css.map
Normal file
File diff suppressed because one or more lines are too long
4743
static/bootstrap5/css/bootstrap-utilities.rtl.css
vendored
Normal file
4743
static/bootstrap5/css/bootstrap-utilities.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap-utilities.rtl.css.map
Normal file
1
static/bootstrap5/css/bootstrap-utilities.rtl.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap-utilities.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
10837
static/bootstrap5/css/bootstrap.css
vendored
Normal file
10837
static/bootstrap5/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap.css.map
Normal file
1
static/bootstrap5/css/bootstrap.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/css/bootstrap.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
10813
static/bootstrap5/css/bootstrap.rtl.css
vendored
Normal file
10813
static/bootstrap5/css/bootstrap.rtl.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/css/bootstrap.rtl.css.map
Normal file
1
static/bootstrap5/css/bootstrap.rtl.css.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/css/bootstrap.rtl.min.css
vendored
Normal file
7
static/bootstrap5/css/bootstrap.rtl.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/css/bootstrap.rtl.min.css.map
Normal file
1
static/bootstrap5/css/bootstrap.rtl.min.css.map
Normal file
File diff suppressed because one or more lines are too long
6748
static/bootstrap5/js/bootstrap.bundle.js
vendored
Normal file
6748
static/bootstrap5/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/js/bootstrap.bundle.js.map
Normal file
1
static/bootstrap5/js/bootstrap.bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/js/bootstrap.bundle.min.js
vendored
Normal file
7
static/bootstrap5/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/js/bootstrap.bundle.min.js.map
Normal file
1
static/bootstrap5/js/bootstrap.bundle.min.js.map
Normal file
File diff suppressed because one or more lines are too long
4967
static/bootstrap5/js/bootstrap.esm.js
vendored
Normal file
4967
static/bootstrap5/js/bootstrap.esm.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/js/bootstrap.esm.js.map
Normal file
1
static/bootstrap5/js/bootstrap.esm.js.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/js/bootstrap.esm.min.js
vendored
Normal file
7
static/bootstrap5/js/bootstrap.esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/js/bootstrap.esm.min.js.map
Normal file
1
static/bootstrap5/js/bootstrap.esm.min.js.map
Normal file
File diff suppressed because one or more lines are too long
5016
static/bootstrap5/js/bootstrap.js
vendored
Normal file
5016
static/bootstrap5/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/bootstrap5/js/bootstrap.js.map
Normal file
1
static/bootstrap5/js/bootstrap.js.map
Normal file
File diff suppressed because one or more lines are too long
7
static/bootstrap5/js/bootstrap.min.js
vendored
Normal file
7
static/bootstrap5/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bootstrap5/js/bootstrap.min.js.map
Normal file
1
static/bootstrap5/js/bootstrap.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -1,22 +1,48 @@
|
||||
{%- extends "bootstrap/base.html" %}
|
||||
{% import "bootstrap/utils.html" as utils %}
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
{% block title %}
|
||||
ytm-ls
|
||||
<title>ytm-ls</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block navbar %}
|
||||
{{ nav.frontend_top.render() }}
|
||||
{% block head %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/static/bootstrap5/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script src="/static/bootstrap5/js/bootstrap.min.js"></script>
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% block body %}
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">yt-mls</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/downloader">downloader</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/library">library</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{%- with messages = get_flashed_messages(with_categories=True) %}
|
||||
{%- if messages %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{utils.flashed_messages(messages)}}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="container d-flex justify-content-center" style="width: fit-content; padding: 1%">
|
||||
<div class="alert alert-{{ category }} d-flex align-self-center justify-content-center" style="width: 150%" role="alert">{{ message }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{%- endwith %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
@@ -2,25 +2,32 @@
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid" style="width: fit-content(105%)">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Song</th>
|
||||
<th scope="col" class="text-center">Download</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for video in videos %}
|
||||
<tr>
|
||||
<td class="text-center">{{ video['name'] }}</td>
|
||||
<td class="text-center"><a class="btn" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<form action="/download/{{ videos[0]['path'] }}">
|
||||
<input type="submit" class="btn pull-right" value="Download all"/>
|
||||
</form>
|
||||
<div class="container" style="width: fit-content(100%); padding: 1.5%">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Song</th>
|
||||
<th scope="col" class="text-center"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for video in videos %}
|
||||
<tr>
|
||||
<td class="text-center">{{ video['name'] }}</td>
|
||||
<td class="text-center"><a class="btn btn-link" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Download</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="container" style="padding: 1.5%">
|
||||
<form action="/download/{{ videos[0]['path'] }}">
|
||||
<input type="submit" class="btn btn-primary float-end" value="Download all"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock %}
|
||||
@@ -2,15 +2,29 @@
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid" style="width: fit-content; align-self: flex-start">
|
||||
<div class="table-bordered" style="padding: .5cm">
|
||||
<form method="POST" class="form-group">
|
||||
{{ form.csrf_token }}
|
||||
{{ form.url.label(class_="form-text") }} <br>
|
||||
{{ form.url(class_="form-control") }} <br>
|
||||
{{ form.ext(class_="form-control") }} <br>
|
||||
{{ form.submit(class_="btn primary") }}
|
||||
</form>
|
||||
<div class="container-fluid d-flex justify-content-center" style="width: fit-content(100%); padding: 1.5%">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST" class="form-group">
|
||||
{{ form.csrf_token }}
|
||||
<div class="container-fluid" style="width: fit-content">
|
||||
<div class="row" style="width: fit-content">
|
||||
{{ form.url.label(class_="form-label") }}
|
||||
</div>
|
||||
<div class="row" style="width: fit-content">
|
||||
<div class="col">
|
||||
{{ form.url(class_="form-control") }}
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ form.ext(class_="form-select") }}
|
||||
</div>
|
||||
<div class="col" style="width: fit-content">
|
||||
{{ form.submit(class_="btn btn-primary") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if form.errors %}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
{%- extends "base.html" %}
|
||||
|
||||
{% import "bootstrap/utils.html" as utils %}
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container" style="width: fit-content(105%)">
|
||||
<div class="container" style="width: fit-content(100%); padding: 1.5%">
|
||||
{% if running_downloads %}
|
||||
<div class="card">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Queue</th>
|
||||
<th scope="col" class="text-center">Started at</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entry in running_downloads %}
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-center"><a href="{{ entry[0] }}" target="_blank">{{ entry[0] }}</a></td>
|
||||
<td class="text-center">{{ entry[1] }}</td>
|
||||
<th scope="col" class="text-center">Queue</th>
|
||||
<th scope="col" class="text-center">Started at</th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entry in running_downloads %}
|
||||
<tr>
|
||||
<td class="text-center"><a href="{{ entry[0] }}" target="_blank">{{ entry[0] }}</a></td>
|
||||
<td class="text-center">{{ entry[1] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
|
||||
@@ -2,61 +2,61 @@
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid" style="width: fit-content(105%)">
|
||||
<div class="container" style="width: fit-content(100%); padding: 1.5%">
|
||||
{% if playlists %}
|
||||
<div class="card">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<table id="playlists" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Playlists</th>
|
||||
<th scope="col" class="text-center">Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for playlist in playlists %}
|
||||
<tr>
|
||||
<td class="text-center"><a class="btn" href="/library-playlist?playlist={{ playlist['ROWID'] }}">{{ playlist['name'] }}</a></td>
|
||||
<td class="text-center"><a class="btn" href="/update/{{ playlist[1] }}">Start</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card-body">
|
||||
<table id="playlists" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center align-middle">Playlists</th>
|
||||
<th scope="col" class="text-center align-middle">Update</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for playlist in playlists %}
|
||||
<tr>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/library-playlist?playlist={{ playlist['ROWID'] }}">{{ playlist['name'] }}</a></td>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/update/{{ playlist[1] }}">Start</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<br><br>
|
||||
<br>
|
||||
|
||||
{% if videos %}
|
||||
<div class="card">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<div class="card-body">
|
||||
<table id="videos" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center align-middle">Titles not in any playlist</th>
|
||||
<th scope="col" class="text-center align-middle">Download</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for video in videos %}
|
||||
{% if 'mp3' in video['ext'] %}
|
||||
<tr>
|
||||
<td class="text-center align-middle">{{ video['name'] }}</td>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Download</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if 'mp4' in video['ext'] %}
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Title</th>
|
||||
<th scope="col" class="text-center">Download</th>
|
||||
<td class="text-center align-middle">{{ video['name'] }}</td>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/player?file={{ video['path'] + video['name'] + video['ext'] }}">Watch</a></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for video in videos %}
|
||||
<tr>
|
||||
<td class="text-center">{{ video['name'] }}</td>
|
||||
<td class="text-center"><a class="btn" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endblock %}
|
||||
12
templates/video-player.html
Normal file
12
templates/video-player.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{%- extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid">
|
||||
<div id="trailer" class="section d-flex justify-content-center embed-responsive embed-responsive-16by9">
|
||||
<video class="embed-responsive-item" style="width: 100%; padding: 1.5%; height: auto" controls>
|
||||
<source src="serve?file=video" type="video/webm">
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock %}
|
||||
Reference in New Issue
Block a user