Initial commit
This commit is contained in:
23
app/__init__.py
Normal file
23
app/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from quart import Quart
|
||||
|
||||
from app.extensions import imp, db
|
||||
|
||||
|
||||
def create_app():
|
||||
app = Quart(__name__, static_url_path="/")
|
||||
|
||||
imp.init_app(app)
|
||||
imp.import_app_resources(
|
||||
files_to_import=["*"],
|
||||
folders_to_import=["*"]
|
||||
)
|
||||
imp.import_blueprints("blueprints")
|
||||
imp.import_models("models")
|
||||
|
||||
db.init_app(app)
|
||||
|
||||
@app.before_serving
|
||||
async def create_tables():
|
||||
db.create_all()
|
||||
|
||||
return app
|
||||
10
app/blueprints/www/__init__.py
Normal file
10
app/blueprints/www/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from quart_imp import Blueprint
|
||||
|
||||
bp = Blueprint(__name__)
|
||||
|
||||
bp.import_resources("routes")
|
||||
|
||||
|
||||
@bp.before_app_request
|
||||
async def before_app_request():
|
||||
bp.init_session()
|
||||
25
app/blueprints/www/config.toml
Normal file
25
app/blueprints/www/config.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
ENABLED = "yes"
|
||||
|
||||
[SETTINGS]
|
||||
URL_PREFIX = "/"
|
||||
#SUBDOMAIN = ""
|
||||
#URL_DEFAULTS = {}
|
||||
STATIC_FOLDER = "static"
|
||||
TEMPLATE_FOLDER = "templates"
|
||||
STATIC_URL_PATH = "/static"
|
||||
#ROOT_PATH = ""
|
||||
#CLI_GROUP = ""
|
||||
|
||||
[SESSION]
|
||||
#www_session = "yes"
|
||||
|
||||
# Set ENABLED to true to allow the blueprint
|
||||
# to create a database bind, change settings accordingly.
|
||||
[DATABASE_BIND]
|
||||
ENABLED = false
|
||||
DIALECT = "sqlite"
|
||||
DATABASE_NAME = "www"
|
||||
LOCATION = ""
|
||||
PORT = ""
|
||||
USERNAME = ""
|
||||
PASSWORD = ""
|
||||
8
app/blueprints/www/routes/index.py
Normal file
8
app/blueprints/www/routes/index.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from quart import render_template
|
||||
|
||||
from .. import bp
|
||||
|
||||
|
||||
@bp.route("/", methods=["GET"])
|
||||
async def index():
|
||||
return await render_template(bp.tmpl("index.html"))
|
||||
880
app/blueprints/www/static/css/water.css
Normal file
880
app/blueprints/www/static/css/water.css
Normal file
@@ -0,0 +1,880 @@
|
||||
/**
|
||||
* Forced dark theme version
|
||||
*/
|
||||
|
||||
:root {
|
||||
--background-body: #202b38;
|
||||
--background: #161f27;
|
||||
--background-alt: #1a242f;
|
||||
--selection: #1c76c5;
|
||||
--text-main: #dbdbdb;
|
||||
--text-bright: #fff;
|
||||
--text-muted: #a9b1ba;
|
||||
--links: #41adff;
|
||||
--focus: #0096bfab;
|
||||
--border: #526980;
|
||||
--code: #ffbe85;
|
||||
--animation-duration: 0.1s;
|
||||
--button-base: #0c151c;
|
||||
--button-hover: #040a0f;
|
||||
--scrollbar-thumb: var(--button-hover);
|
||||
--scrollbar-thumb-hover: rgb(0, 0, 0);
|
||||
--form-placeholder: #a9a9a9;
|
||||
--form-text: #fff;
|
||||
--variable: #d941e2;
|
||||
--highlight: #efdb43;
|
||||
--select-arrow: url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3 .org/1999/xlink' height='62.5' width='116.9' fill='%23efef ef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6, 7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115. 3,1.6Z'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
html {
|
||||
scrollbar-color: #040a0f #202b38;
|
||||
scrollbar-color: var(--scrollbar-thumb) var(--background-body);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif;
|
||||
line-height: 1.4;
|
||||
max-width: 800px;
|
||||
margin: 20px auto;
|
||||
padding: 0 10px;
|
||||
word-wrap: break-word;
|
||||
color: #dbdbdb;
|
||||
color: var(--text-main);
|
||||
background: #202b38;
|
||||
background: var(--background-body);
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
button {
|
||||
transition: background-color 0.1s linear,
|
||||
border-color 0.1s linear,
|
||||
color 0.1s linear,
|
||||
box-shadow 0.1s linear,
|
||||
transform 0.1s ease;
|
||||
transition: background-color var(--animation-duration) linear,
|
||||
border-color var(--animation-duration) linear,
|
||||
color var(--animation-duration) linear,
|
||||
box-shadow var(--animation-duration) linear,
|
||||
transform var(--animation-duration) ease;
|
||||
}
|
||||
|
||||
input {
|
||||
transition: background-color 0.1s linear,
|
||||
border-color 0.1s linear,
|
||||
color 0.1s linear,
|
||||
box-shadow 0.1s linear,
|
||||
transform 0.1s ease;
|
||||
transition: background-color var(--animation-duration) linear,
|
||||
border-color var(--animation-duration) linear,
|
||||
color var(--animation-duration) linear,
|
||||
box-shadow var(--animation-duration) linear,
|
||||
transform var(--animation-duration) ease;
|
||||
}
|
||||
|
||||
textarea {
|
||||
transition: background-color 0.1s linear,
|
||||
border-color 0.1s linear,
|
||||
color 0.1s linear,
|
||||
box-shadow 0.1s linear,
|
||||
transform 0.1s ease;
|
||||
transition: background-color var(--animation-duration) linear,
|
||||
border-color var(--animation-duration) linear,
|
||||
color var(--animation-duration) linear,
|
||||
box-shadow var(--animation-duration) linear,
|
||||
transform var(--animation-duration) ease;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.2em;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-bottom: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h4 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h5 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h6 {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
b,
|
||||
strong,
|
||||
th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
q::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
q::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 4px solid #0096bfab;
|
||||
border-left: 4px solid var(--focus);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
q {
|
||||
border-left: 4px solid #0096bfab;
|
||||
border-left: 4px solid var(--focus);
|
||||
margin: 1.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
blockquote > footer {
|
||||
font-style: normal;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
blockquote cite {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
address {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
a[href^='mailto\:']::before {
|
||||
content: '📧 ';
|
||||
}
|
||||
|
||||
a[href^='tel\:']::before {
|
||||
content: '📞 ';
|
||||
}
|
||||
|
||||
a[href^='sms\:']::before {
|
||||
content: '💬 ';
|
||||
}
|
||||
|
||||
mark {
|
||||
background-color: #efdb43;
|
||||
background-color: var(--highlight);
|
||||
border-radius: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a > code,
|
||||
a > strong {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select,
|
||||
input[type='submit'],
|
||||
input[type='reset'],
|
||||
input[type='button'],
|
||||
input[type='checkbox'],
|
||||
input[type='range'],
|
||||
input[type='radio'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[type='checkbox'],
|
||||
[type='radio'] {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
input {
|
||||
color: #fff;
|
||||
color: var(--form-text);
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #fff;
|
||||
color: var(--form-text);
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
color: #fff;
|
||||
color: var(--form-text);
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select {
|
||||
color: #fff;
|
||||
color: var(--form-text);
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #0c151c;
|
||||
background-color: var(--button-base);
|
||||
padding-right: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
input[type='submit'] {
|
||||
background-color: #0c151c;
|
||||
background-color: var(--button-base);
|
||||
padding-right: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
input[type='reset'] {
|
||||
background-color: #0c151c;
|
||||
background-color: var(--button-base);
|
||||
padding-right: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
input[type='button'] {
|
||||
background-color: #0c151c;
|
||||
background-color: var(--button-base);
|
||||
padding-right: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #040a0f;
|
||||
background: var(--button-hover);
|
||||
}
|
||||
|
||||
input[type='submit']:hover {
|
||||
background: #040a0f;
|
||||
background: var(--button-hover);
|
||||
}
|
||||
|
||||
input[type='reset']:hover {
|
||||
background: #040a0f;
|
||||
background: var(--button-hover);
|
||||
}
|
||||
|
||||
input[type='button']:hover {
|
||||
background: #040a0f;
|
||||
background: var(--button-hover);
|
||||
}
|
||||
|
||||
input[type='color'] {
|
||||
min-height: 2rem;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type='checkbox'],
|
||||
input[type='radio'] {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
input[type='radio'] {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
label {
|
||||
vertical-align: middle;
|
||||
margin-bottom: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input:not([type='checkbox']):not([type='radio']),
|
||||
input[type='range'],
|
||||
select,
|
||||
button,
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
display: block;
|
||||
margin-right: 0;
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
textarea:not([cols]) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea:not([rows]) {
|
||||
min-height: 40px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
select {
|
||||
background: #161f27 url("data:image/svg+xml;charset=utf-8,% 3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version= '1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w 3.org/1999/xlink' height='62.5' width='116.9' fill='%23efef ef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L5 8.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7. 4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60 .5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3, 1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;
|
||||
background: var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat;
|
||||
padding-right: 35px;
|
||||
}
|
||||
|
||||
select::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
select[multiple] {
|
||||
padding-right: 10px;
|
||||
background-image: none;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
box-shadow: 0 0 0 2px #0096bfab;
|
||||
box-shadow: 0 0 0 2px var(--focus);
|
||||
}
|
||||
|
||||
select:focus {
|
||||
box-shadow: 0 0 0 2px #0096bfab;
|
||||
box-shadow: 0 0 0 2px var(--focus);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
box-shadow: 0 0 0 2px #0096bfab;
|
||||
box-shadow: 0 0 0 2px var(--focus);
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
box-shadow: 0 0 0 2px #0096bfab;
|
||||
box-shadow: 0 0 0 2px var(--focus);
|
||||
}
|
||||
|
||||
input[type='checkbox']:active,
|
||||
input[type='radio']:active,
|
||||
input[type='submit']:active,
|
||||
input[type='reset']:active,
|
||||
input[type='button']:active,
|
||||
input[type='range']:active,
|
||||
button:active {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
input:disabled,
|
||||
select:disabled,
|
||||
button:disabled,
|
||||
textarea:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
::-moz-placeholder {
|
||||
color: #a9a9a9;
|
||||
color: var(--form-placeholder);
|
||||
}
|
||||
|
||||
:-ms-input-placeholder {
|
||||
color: #a9a9a9;
|
||||
color: var(--form-placeholder);
|
||||
}
|
||||
|
||||
::-ms-input-placeholder {
|
||||
color: #a9a9a9;
|
||||
color: var(--form-placeholder);
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: #a9a9a9;
|
||||
color: var(--form-placeholder);
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 1px #0096bfab solid;
|
||||
border: 1px var(--focus) solid;
|
||||
border-radius: 6px;
|
||||
margin: 0;
|
||||
margin-bottom: 12px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
legend {
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type='range'] {
|
||||
margin: 10px 0;
|
||||
padding: 10px 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
input[type='range']:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type='range']::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 9.5px;
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
input[type='range']::-webkit-slider-thumb {
|
||||
box-shadow: 0 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 50%;
|
||||
background: #526980;
|
||||
background: var(--border);
|
||||
-webkit-appearance: none;
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
input[type='range']:focus::-webkit-slider-runnable-track {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
input[type='range']::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 9.5px;
|
||||
-moz-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
input[type='range']::-moz-range-thumb {
|
||||
box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 50%;
|
||||
background: #526980;
|
||||
background: var(--border);
|
||||
}
|
||||
|
||||
input[type='range']::-ms-track {
|
||||
width: 100%;
|
||||
height: 9.5px;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
border-width: 16px 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
input[type='range']::-ms-fill-lower {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border: 0.2px solid #010101;
|
||||
border-radius: 3px;
|
||||
box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
}
|
||||
|
||||
input[type='range']::-ms-fill-upper {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border: 0.2px solid #010101;
|
||||
border-radius: 3px;
|
||||
box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
}
|
||||
|
||||
input[type='range']::-ms-thumb {
|
||||
box-shadow: 1px 1px 1px #000, 0 0 1px #0d0d0d;
|
||||
border: 1px solid #000;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 50%;
|
||||
background: #526980;
|
||||
background: var(--border);
|
||||
}
|
||||
|
||||
input[type='range']:focus::-ms-fill-lower {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
input[type='range']:focus::-ms-fill-upper {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #41adff;
|
||||
color: var(--links);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
color: #ffbe85;
|
||||
color: var(--code);
|
||||
padding: 2.5px 5px;
|
||||
border-radius: 6px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
samp {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
color: #ffbe85;
|
||||
color: var(--code);
|
||||
padding: 2.5px 5px;
|
||||
border-radius: 6px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
time {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
color: #ffbe85;
|
||||
color: var(--code);
|
||||
padding: 2.5px 5px;
|
||||
border-radius: 6px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
padding: 10px;
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
var {
|
||||
color: #d941e2;
|
||||
color: var(--variable);
|
||||
font-style: normal;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border: 1px solid #526980;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 2px;
|
||||
color: #dbdbdb;
|
||||
color: var(--text-main);
|
||||
padding: 2px 4px 2px 4px;
|
||||
}
|
||||
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid #526980;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
table caption {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
thead {
|
||||
border-bottom: 1px solid #526980;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
tfoot {
|
||||
border-top: 1px solid #526980;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) {
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) button {
|
||||
background-color: #1a242f;
|
||||
background-color: var(--background-alt);
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) button:hover {
|
||||
background-color: #202b38;
|
||||
background-color: var(--background-body);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #161f27;
|
||||
background: var(--background);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #040a0f;
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgb(0, 0, 0);
|
||||
background: var(--scrollbar-thumb-hover);
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background-color: #1c76c5;
|
||||
background-color: var(--selection);
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: #1c76c5;
|
||||
background-color: var(--selection);
|
||||
color: #fff;
|
||||
color: var(--text-bright);
|
||||
}
|
||||
|
||||
details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
background-color: #1a242f;
|
||||
background-color: var(--background-alt);
|
||||
padding: 10px 10px 0;
|
||||
margin: 1em 0;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
details[open] {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
details > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
details[open] summary {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
padding: 10px;
|
||||
margin: -10px -10px 0;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
summary:hover,
|
||||
summary:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
details > :not(summary) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
summary::-webkit-details-marker {
|
||||
color: #dbdbdb;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
dialog {
|
||||
background-color: #1a242f;
|
||||
background-color: var(--background-alt);
|
||||
color: #dbdbdb;
|
||||
color: var(--text-main);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
border-color: #526980;
|
||||
border-color: var(--border);
|
||||
padding: 10px 30px;
|
||||
}
|
||||
|
||||
dialog > header:first-child {
|
||||
background-color: #161f27;
|
||||
background-color: var(--background);
|
||||
border-radius: 6px 6px 0 0;
|
||||
margin: -10px -30px 10px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
dialog::-webkit-backdrop {
|
||||
background: #0000009c;
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
dialog::backdrop {
|
||||
background: #0000009c;
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
footer {
|
||||
border-top: 1px solid #526980;
|
||||
border-top: 1px solid var(--border);
|
||||
padding-top: 10px;
|
||||
color: #a9b1ba;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
body > footer {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body,
|
||||
pre,
|
||||
code,
|
||||
summary,
|
||||
details,
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
body,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
pre,
|
||||
code,
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
footer,
|
||||
summary,
|
||||
strong {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
summary::marker {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
summary::-webkit-details-marker {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00f;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
BIN
app/blueprints/www/static/img/quart-imp-logo.png
Normal file
BIN
app/blueprints/www/static/img/quart-imp-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
1
app/blueprints/www/static/js/main.js
Normal file
1
app/blueprints/www/static/js/main.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log('This log is from the file /home/david/PycharmProjects/quart-imp/app/blueprints/www/static/main.js')
|
||||
24
app/blueprints/www/templates/www/extends/main.html
Normal file
24
app/blueprints/www/templates/www/extends/main.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="'width=device-width, initial-scale=1.0'">
|
||||
<title>Quart-Imp</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" sizes="16x16 32x32" type="image/x-icon">
|
||||
<link rel="stylesheet" href="{{ url_for('www.static', filename='css/water.css') }}">
|
||||
<script defer src="{{ url_for('www.static', filename='js/main.js') }}"></script>
|
||||
|
||||
<script>
|
||||
// inline script
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% include 'www/includes/header.html' %}
|
||||
{% block content %}{% endblock %}
|
||||
{% include 'www/includes/footer.html' %}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
6
app/blueprints/www/templates/www/includes/footer.html
Normal file
6
app/blueprints/www/templates/www/includes/footer.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<div style="display: flex; flex-direction: row; align-items: center; gap: 2rem; margin-bottom: 2rem;">
|
||||
<div>
|
||||
<p>This is the footer, located here: <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/includes/footer.html</code></p>
|
||||
<p>It's being imported in the <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/extends/main.html</code> template.</p>
|
||||
</div>
|
||||
</div>
|
||||
10
app/blueprints/www/templates/www/includes/header.html
Normal file
10
app/blueprints/www/templates/www/includes/header.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div style="display: flex; flex-direction: row; align-items: center;
|
||||
justify-content: start; gap: 2rem; margin-bottom: 2rem;">
|
||||
<img style="border-radius: 50%"
|
||||
src="{{ url_for('www.static', filename='img/quart-imp-logo.png') }}" alt="quart-imp logo">
|
||||
<h1 style="font-size: 4rem;">Quart-Imp</h1>
|
||||
</div>
|
||||
<div style="margin-bottom: 2rem;">
|
||||
<p>This is the header, located here: <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/includes/header.html</code></p>
|
||||
<p>It's being imported in the <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/extends/main.html</code> template.</p>
|
||||
</div>
|
||||
17
app/blueprints/www/templates/www/index.html
Normal file
17
app/blueprints/www/templates/www/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends 'www/extends/main.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div style="display: flex; flex-direction: row; align-items: center; gap: 2rem; margin-bottom: 2rem;">
|
||||
<div>
|
||||
<h2 style="margin: 0;">Blueprint: www</h2>
|
||||
<h3>This is the index route of the included example blueprint.</h3>
|
||||
<p style="margin-bottom: 0;">
|
||||
This template page is located in <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/index.html</code><br/>
|
||||
it extends from <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/templates/www/extends/main.html</code><br/>
|
||||
with its route defined in <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/routes/index.py</code><br/><br/>
|
||||
It's being imported by <code>bp.import_resources("routes")</code>
|
||||
in the <code>/home/david/PycharmProjects/quart-imp/app/blueprints/www/__init__.py</code> file.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
81
app/default.config.toml
Normal file
81
app/default.config.toml
Normal file
@@ -0,0 +1,81 @@
|
||||
# Quart-Imp Config File
|
||||
# ------------------------
|
||||
# Updates the Quart app config with the variables below.
|
||||
# If any variable below does not exist in the standard Quart env
|
||||
# vars it is created and will be accessible using
|
||||
# app.config. All key names defined below will be
|
||||
# capitalised when imported.
|
||||
[FLASK]
|
||||
DEBUG = false
|
||||
#PROPAGATE_EXCEPTIONS = true
|
||||
TRAP_HTTP_EXCEPTIONS = false
|
||||
#TRAP_BAD_REQUEST_ERRORS = true
|
||||
SECRET_KEY = "86685ef98889e7db7da6df2dd7184f866f4ef34244fe2c52"
|
||||
SESSION_COOKIE_NAME = "session"
|
||||
#SESSION_COOKIE_DOMAIN = "domain-here.com"
|
||||
#SESSION_COOKIE_PATH = "/"
|
||||
SESSION_COOKIE_HTTPONLY = true
|
||||
SESSION_COOKIE_SECURE = false
|
||||
SESSION_COOKIE_SAMESITE = "Lax"
|
||||
PERMANENT_SESSION_LIFETIME = 3600 # 1 hour
|
||||
SESSION_REFRESH_EACH_REQUEST = true
|
||||
USE_X_SENDFILE = false
|
||||
#SEND_FILE_MAX_AGE_DEFAULT = 43200
|
||||
ERROR_404_HELP = true
|
||||
#SERVER_NAME = "localhost:5000"
|
||||
APPLICATION_ROOT = "/"
|
||||
PREFERRED_URL_SCHEME = "http"
|
||||
#MAX_CONTENT_LENGTH = 0
|
||||
#TEMPLATES_AUTO_RELOAD = true
|
||||
EXPLAIN_TEMPLATE_LOADING = false
|
||||
MAX_COOKIE_SIZE = 4093
|
||||
|
||||
# This will set the default session variables for the app.
|
||||
# Anything here will be accessible using session["your_var_name"]
|
||||
# or session.get("your_var_name")
|
||||
[SESSION]
|
||||
logged_in = false
|
||||
|
||||
# These settings are specific to the Flask-SQLAlchemy extension.
|
||||
# Anything here will be accessible using app.config
|
||||
[SQLALCHEMY]
|
||||
SQLALCHEMY_ECHO = false
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = false
|
||||
SQLALCHEMY_RECORD_QUERIES = false
|
||||
# Below are extra settings that Quart-Imp uses but relates to Flask-SQLAlchemy.
|
||||
# This sets the file extension for SQLite databases, and where to create the folder
|
||||
# that the database will be stored in. true will create the folder on the same level as your
|
||||
# app, false will create the folder in the app root.
|
||||
SQLITE_DB_EXTENSION = ".sqlite"
|
||||
SQLITE_STORE_IN_PARENT = false
|
||||
|
||||
# [DATABASE.MAIN] is loaded as SQLALCHEMY_DATABASE_URI
|
||||
# Dialets = mysql / postgresql / sqlite / oracle / mssql
|
||||
# Uncomment below to generate the SQLALCHEMY_DATABASE_URI.
|
||||
[DATABASE.MAIN]
|
||||
ENABLED = true
|
||||
DIALECT = "sqlite"
|
||||
DATABASE_NAME = "database"
|
||||
LOCATION = ""
|
||||
PORT = ""
|
||||
USERNAME = ""
|
||||
PASSWORD = ""
|
||||
|
||||
# Adding another database is as simple as adding a new section.
|
||||
# [DATABASE.ANOTHER] will then be accessible using SQLALCHEMY_BINDS
|
||||
# The bind key will be stored as a lowercase value, so "ANOTHER" will
|
||||
# be accessible as "another"
|
||||
# You can then use the bind key in the model as follows:
|
||||
# class MyModel(db.Model):
|
||||
# __bind_key__ = "another"
|
||||
# ...
|
||||
|
||||
# Uncomment below to generate and add to SQLALCHEMY_BINDS.
|
||||
#[DATABASE.ANOTHER]
|
||||
#ENABLED = true
|
||||
#DIALECT = "sqlite"
|
||||
#DATABASE_NAME = "another"
|
||||
#LOCATION = ""
|
||||
#PORT = ""
|
||||
#USERNAME = ""
|
||||
#PASSWORD = ""
|
||||
9
app/extensions/__init__.py
Normal file
9
app/extensions/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import quart_flask_patch
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
from quart_imp import Imp
|
||||
|
||||
_ = quart_flask_patch
|
||||
|
||||
imp = Imp()
|
||||
db = SQLAlchemy()
|
||||
12
app/models/__init__.py
Normal file
12
app/models/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from sqlalchemy import select, update, delete, insert
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.extensions import db
|
||||
|
||||
__all__ = [
|
||||
"db",
|
||||
"select",
|
||||
"update",
|
||||
"delete",
|
||||
"insert",
|
||||
]
|
||||
72
app/models/example_user_table.py
Normal file
72
app/models/example_user_table.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from quart_imp.auth import authenticate_password
|
||||
from quart_imp.auth import encrypt_password
|
||||
from quart_imp.auth import generate_private_key
|
||||
from quart_imp.auth import generate_salt
|
||||
from . import *
|
||||
|
||||
|
||||
class ExampleUserTable(db.Model):
|
||||
user_id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(256), nullable=False)
|
||||
password = db.Column(db.String(512), nullable=False)
|
||||
salt = db.Column(db.String(4), nullable=False)
|
||||
private_key = db.Column(db.String(256), nullable=False)
|
||||
disabled = db.Column(db.Boolean)
|
||||
|
||||
@classmethod
|
||||
def login(cls, username, password: str) -> bool:
|
||||
user = cls.get_by_username(username)
|
||||
if user is None:
|
||||
return False
|
||||
return authenticate_password(password, user.password, user.salt)
|
||||
|
||||
@classmethod
|
||||
def get_by_id(cls, user_id: int):
|
||||
return db.session.execute(
|
||||
select(cls).filter_by(user_id=user_id).limit(1)
|
||||
).scalar_one_or_none()
|
||||
|
||||
@classmethod
|
||||
def get_by_username(cls, username: str):
|
||||
return db.session.execute(
|
||||
select(cls).filter_by(username=username).limit(1)
|
||||
).scalar_one_or_none()
|
||||
|
||||
@classmethod
|
||||
def create(cls, username, password, disabled):
|
||||
salt = generate_salt()
|
||||
salt_pepper_password = encrypt_password(password, salt)
|
||||
private_key = generate_private_key(username)
|
||||
|
||||
db.session.execute(
|
||||
insert(cls).values(
|
||||
username=username,
|
||||
password=salt_pepper_password,
|
||||
salt=salt,
|
||||
private_key=private_key,
|
||||
disabled=disabled,
|
||||
)
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def update(cls, user_id: int, username, private_key, disabled):
|
||||
db.session.execute(
|
||||
update(cls).where(
|
||||
cls.user_id == user_id
|
||||
).values(
|
||||
username=username,
|
||||
private_key=private_key,
|
||||
disabled=disabled,
|
||||
)
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, user_id: int):
|
||||
db.session.execute(
|
||||
delete(cls).where(
|
||||
cls.user_id == user_id
|
||||
)
|
||||
)
|
||||
db.session.commit()
|
||||
57
app/resources/cli/cli.py
Normal file
57
app/resources/cli/cli.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from quart import current_app as app
|
||||
from app.extensions import db
|
||||
from app.models.example_user_table import ExampleUserTable
|
||||
|
||||
|
||||
@app.cli.command("config")
|
||||
async def create_tables():
|
||||
print(app.config)
|
||||
|
||||
|
||||
@app.cli.command("create-tables")
|
||||
async def create_tables():
|
||||
db.create_all()
|
||||
|
||||
|
||||
@app.cli.command("get-example-user")
|
||||
async def get_example_user():
|
||||
result = ExampleUserTable.get_by_id(1)
|
||||
if not result:
|
||||
print("User not found.")
|
||||
return
|
||||
print(
|
||||
f"""
|
||||
user_id: {result.user_id}
|
||||
username: {result.username}
|
||||
salt: {result.salt}
|
||||
password: {result.password}
|
||||
private_key: {result.private_key}
|
||||
disabled: {result.disabled}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
@app.cli.command("create-example-user")
|
||||
async def add_example_user():
|
||||
ExampleUserTable.create(
|
||||
username="admin",
|
||||
password="password",
|
||||
disabled=False,
|
||||
)
|
||||
|
||||
|
||||
@app.cli.command("update-example-user")
|
||||
async def update_example_user():
|
||||
ExampleUserTable.update(
|
||||
user_id=1,
|
||||
username="admin-updated",
|
||||
private_key="private_key",
|
||||
disabled=False,
|
||||
)
|
||||
|
||||
|
||||
@app.cli.command("delete-example-user")
|
||||
async def delete_example_user():
|
||||
ExampleUserTable.delete(
|
||||
user_id=1,
|
||||
)
|
||||
14
app/resources/context_processors/context_processors.py
Normal file
14
app/resources/context_processors/context_processors.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from quart import current_app as app
|
||||
|
||||
|
||||
@app.context_processor
|
||||
async def example__utility_processor():
|
||||
"""
|
||||
Usage:
|
||||
{{ format_price(100.33) }} -> $100.33
|
||||
"""
|
||||
|
||||
async def example__format_price(amount, currency='$'):
|
||||
return '{1}{0:.2f}'.format(amount, currency)
|
||||
|
||||
return dict(format_price=example__format_price)
|
||||
44
app/resources/error_handlers/error_handlers.py
Normal file
44
app/resources/error_handlers/error_handlers.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from quart import current_app as app
|
||||
from quart import render_template
|
||||
|
||||
|
||||
@app.errorhandler(400)
|
||||
async def error_400(error):
|
||||
return await render_template(
|
||||
"errors/400.html",
|
||||
), 400
|
||||
|
||||
|
||||
@app.errorhandler(401)
|
||||
async def error_401(error):
|
||||
return await render_template(
|
||||
"errors/401.html",
|
||||
), 401
|
||||
|
||||
|
||||
@app.errorhandler(403)
|
||||
async def error_403(error):
|
||||
return await render_template(
|
||||
"errors/403.html",
|
||||
), 403
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
async def error_404(error):
|
||||
return await render_template(
|
||||
"errors/404.html",
|
||||
), 404
|
||||
|
||||
|
||||
@app.errorhandler(405)
|
||||
async def error_405(error):
|
||||
return await render_template(
|
||||
"errors/405.html",
|
||||
), 405
|
||||
|
||||
|
||||
@app.errorhandler(500)
|
||||
async def error_500(error):
|
||||
return await render_template(
|
||||
"errors/500.html",
|
||||
), 500
|
||||
30
app/resources/filters/filters.py
Normal file
30
app/resources/filters/filters.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from quart import current_app as app
|
||||
|
||||
|
||||
@app.template_filter('example__num_to_month')
|
||||
async def example__num_to_month(num: str) -> str:
|
||||
"""
|
||||
Usage:
|
||||
{{ 1 | example__num_to_month }} -> January
|
||||
"""
|
||||
if isinstance(num, int):
|
||||
num = str(num)
|
||||
|
||||
months = {
|
||||
"1": "January",
|
||||
"2": "February",
|
||||
"3": "March",
|
||||
"4": "April",
|
||||
"5": "May",
|
||||
"6": "June",
|
||||
"7": "July",
|
||||
"8": "August",
|
||||
"9": "September",
|
||||
"10": "October",
|
||||
"11": "November",
|
||||
"12": "December",
|
||||
}
|
||||
|
||||
if num in months:
|
||||
return months[num]
|
||||
return "Month not found"
|
||||
7
app/resources/routes/routes.py
Normal file
7
app/resources/routes/routes.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from quart import current_app as app
|
||||
from quart import render_template
|
||||
|
||||
|
||||
@app.route("/resources")
|
||||
async def index():
|
||||
return await render_template("index.html")
|
||||
BIN
app/resources/static/favicon.ico
Normal file
BIN
app/resources/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
11
app/resources/templates/errors/400.html
Normal file
11
app/resources/templates/errors/400.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>400 Bad Request</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>It's not us, it's you.</p>
|
||||
</body>
|
||||
</html>
|
||||
11
app/resources/templates/errors/401.html
Normal file
11
app/resources/templates/errors/401.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>401 Unauthorized</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>You lack valid authentication credentials for the requested resource</p>
|
||||
</body>
|
||||
</html>
|
||||
11
app/resources/templates/errors/403.html
Normal file
11
app/resources/templates/errors/403.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>403 Forbidden</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Access forbidden!</p>
|
||||
</body>
|
||||
</html>
|
||||
11
app/resources/templates/errors/404.html
Normal file
11
app/resources/templates/errors/404.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>404 Page Not Found</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>No route associated with the URL</p>
|
||||
</body>
|
||||
</html>
|
||||
11
app/resources/templates/errors/405.html
Normal file
11
app/resources/templates/errors/405.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>405 Method Not Allowed</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Should of GET when you POST, or POST when you GET</p>
|
||||
</body>
|
||||
</html>
|
||||
11
app/resources/templates/errors/500.html
Normal file
11
app/resources/templates/errors/500.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>500 Server Error!</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>There has been a server error!</p>
|
||||
</body>
|
||||
</html>
|
||||
12
app/resources/templates/index.html
Normal file
12
app/resources/templates/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="'width=device-width, initial-scale=1.0'">
|
||||
<title>Quart-Imp Global Template</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" sizes="16x16 32x32" type="image/x-icon">
|
||||
</head>
|
||||
<body>
|
||||
<p>This is the example resources template file located in <code>resources/templates/index.html</code></p>
|
||||
</body>
|
||||
Reference in New Issue
Block a user