mirror of
https://github.com/NovaOSS/nova-web.git
synced 2024-11-25 16:33:57 +01:00
Added user dashboard
Co-authored-by: Leander <henceiusegentoo@users.noreply.github.com>
This commit is contained in:
parent
0019ee9821
commit
569d40161b
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -18,7 +18,8 @@
|
|||
"web/static/css/footer.css": true,
|
||||
"web/static/css/home.css": true,
|
||||
"web/static/css/input.css": true,
|
||||
"web/static/css/navbar.css": true
|
||||
"web/static/css/navbar.css": true,
|
||||
"web/static/css/profile.css": true
|
||||
},
|
||||
"hide-files.files": [
|
||||
"static/css/base.css",
|
||||
|
@ -30,6 +31,7 @@
|
|||
"web/static/css/footer.css",
|
||||
"web/static/css/home.css",
|
||||
"web/static/css/input.css",
|
||||
"web/static/css/navbar.css"
|
||||
"web/static/css/navbar.css",
|
||||
"web/static/css/profile.css"
|
||||
]
|
||||
}
|
0
web/__main__.py
Normal file → Executable file
0
web/__main__.py
Normal file → Executable file
39
web/account.py
Normal file → Executable file
39
web/account.py
Normal file → Executable file
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import flask
|
||||
import requests
|
||||
import functools
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from requests_oauthlib import OAuth2Session
|
||||
|
@ -12,20 +13,23 @@ os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '0' # change this to '1' if you're r
|
|||
API_URL = 'https://discordapp.com/api'
|
||||
CLIENT_ID = str(os.environ['DISCORD_CLIENT_ID'])
|
||||
CLIENT_SECRET = os.environ['DISCORD_CLIENT_SECRET']
|
||||
# REDIRECT_URI = 'https://nova-oss.com/callback/discord'
|
||||
REDIRECT_URI = 'http://localhost:2211/callback/discord'
|
||||
REDIRECT_URI = 'https://nova-oss.com/callback/discord'
|
||||
# REDIRECT_URI = 'http://localhost:2211/callback/discord'
|
||||
SCOPES = ['identify']
|
||||
|
||||
@functools.lru_cache(maxsize=128)
|
||||
def get_user(discord_id: int) -> dict:
|
||||
return requests.get(
|
||||
res = requests.get(
|
||||
url=f'http://localhost:2333/users?discord_id={discord_id}',
|
||||
timeout=3,
|
||||
headers={
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': os.getenv('CORE_API_KEY')
|
||||
'Authorization': os.environ['CORE_API_KEY']
|
||||
}
|
||||
).json()
|
||||
|
||||
return res
|
||||
|
||||
def register(app):
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
|
@ -34,28 +38,32 @@ def register(app):
|
|||
|
||||
@app.route('/account')
|
||||
def account_view():
|
||||
discord_id = flask.session.get('discord_id')
|
||||
|
||||
if not discord_id:
|
||||
try:
|
||||
discord_id = flask.session['discord_id']
|
||||
except KeyError:
|
||||
return flask.redirect('/login')
|
||||
|
||||
discord_account = OAuth2Session(CLIENT_ID, token=flask.session['discord_token'])
|
||||
profile = discord_account.get(f'{API_URL}/users/@me').json()
|
||||
discord_user = discord_account.get(f'{API_URL}/users/@me').json()
|
||||
|
||||
db_user = get_user(discord_id)
|
||||
|
||||
user = {
|
||||
'name': profile['username'],
|
||||
'avatar': profile['avatar'],
|
||||
'role': db_user['role'],
|
||||
'credits': db_user['credits'],
|
||||
'api_key': db_user['api_key']
|
||||
'username': discord_user.get('username'),
|
||||
'display_name': discord_user.get('global_name'),
|
||||
'avatar': f'https://cdn.discordapp.com/avatars/{discord_user.get("id")}/{discord_user.get("avatar")}.png',
|
||||
'role': db_user.get('role'),
|
||||
'credits': db_user.get('credits'),
|
||||
'api_key': db_user.get('api_key')
|
||||
}
|
||||
|
||||
return flask.render_template('account.html', user=user)
|
||||
|
||||
@app.route('/login')
|
||||
def login_view():
|
||||
if flask.session.get('discord_token'):
|
||||
return flask.redirect('/account')
|
||||
|
||||
return flask.render_template('login.html')
|
||||
|
||||
@app.route('/auth/discord', methods=['POST', 'GET'])
|
||||
|
@ -78,9 +86,10 @@ def register(app):
|
|||
client_secret=CLIENT_SECRET,
|
||||
authorization_response=flask.request.url,
|
||||
)
|
||||
flask.session['discord_token'] = token
|
||||
|
||||
print('Token:', token)
|
||||
flask.session.permanent = True
|
||||
flask.session['discord_token'] = token
|
||||
flask.session['discord_id'] = discord_account.get(f'{API_URL}/users/@me').json()['id']
|
||||
|
||||
return flask.redirect('/account')
|
||||
|
||||
|
|
2
web/app.py
Normal file → Executable file
2
web/app.py
Normal file → Executable file
|
@ -14,7 +14,7 @@ log.disabled = True
|
|||
def create_app() -> flask.Flask:
|
||||
app = flask.Flask(__name__)
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
|
||||
app.secret_key = secrets.token_hex(16)
|
||||
app.secret_key = os.environ['FLASK_SECRET_KEY']
|
||||
app.jinja_env.trim_blocks = True
|
||||
app.jinja_env.lstrip_blocks = True
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ $secondary-dark: #0e0e0e
|
|||
$border: #161d2bb0
|
||||
$soft: #fcf7f824
|
||||
|
||||
$primary: #b53d61
|
||||
$primary-light: #f45a88
|
||||
$primary-glow: #f45a8861
|
||||
$primary-soft: #f79ab624
|
||||
$primary: #5f44b9
|
||||
$primary-light: #b88df0
|
||||
$primary-glow: #683a9638
|
||||
$primary-soft: #cc9af724
|
||||
$accent: #28aaf0
|
||||
|
||||
$error: #ef3628
|
||||
|
|
|
@ -38,14 +38,14 @@ h3, h3 * {
|
|||
|
||||
main a {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #b53d61;
|
||||
text-decoration-color: #5f44b9;
|
||||
text-underline-offset: 2px;
|
||||
text-decoration-thickness: 5px;
|
||||
transition: 0.2s;
|
||||
}
|
||||
main a:hover {
|
||||
text-decoration-thickness: 0;
|
||||
background: rgba(244, 90, 136, 0.3803921569);
|
||||
background: rgba(104, 58, 150, 0.2196078431);
|
||||
}
|
||||
|
||||
main p {
|
||||
|
@ -59,7 +59,7 @@ img {
|
|||
|
||||
mark {
|
||||
color: #f3f3f3;
|
||||
background: #b53d61;
|
||||
background: #5f44b9;
|
||||
padding: 5px 7px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
@ -118,11 +118,18 @@ h6 {
|
|||
}
|
||||
|
||||
.special-gradient {
|
||||
background: linear-gradient(83deg, rgb(244, 90, 136) 7%, rgb(40, 170, 240) 100%);
|
||||
background: linear-gradient(45deg, #be89ec 7%, #2867f0 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.box {
|
||||
background: rgba(204, 154, 247, 0.1411764706);
|
||||
border: 2px solid rgba(204, 154, 247, 0.1411764706);
|
||||
border-radius: 5px;
|
||||
padding: 1rem 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
body {
|
||||
margin: 0 2rem;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -105,10 +105,16 @@ h6
|
|||
outline: none
|
||||
|
||||
.special-gradient
|
||||
background: linear-gradient(83deg, rgba(244,90,136,1) 7%, rgba(40,170,240,1) 100%)
|
||||
background: linear-gradient(45deg, #be89ec 7%, #2867f0 100%)
|
||||
-webkit-background-clip: text
|
||||
-webkit-text-fill-color: transparent
|
||||
|
||||
.box
|
||||
background: $primary-soft
|
||||
border: 2px solid $primary-soft
|
||||
border-radius: $edge
|
||||
padding: 1rem 2rem
|
||||
|
||||
@media (max-width: 900px)
|
||||
body
|
||||
margin: 0 2rem
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["footer.sass","_vars.sass","footer.css"],"names":[],"mappings":"AAEA;EACI,iBAAA;EACA,iBAAA;EACA,gBCcS;ACfb;AFGI;EACI,iBCYK;ACbb;AFGI;EACI,aAAA;EACA,sBAAA;EAEA,mBAAA;AEFR;AFIQ;EACI,oBAAA;EACA,qBAAA;AEFZ;AFIY;EACI,eAAA;EACA,gBAAA;AEFhB;AFIY;EACI,UAAA;EACA,eAAA;EACA,gBAAA;EACA,cAAA;EACA,mBAAA;AEFhB;AFIY;EACI,uBAAA;EAAA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,cAAA;EACA,qBAAA;EACA,mBAAA;AEFhB;AFIgB;EACI,YAAA;AEFpB;AFII;EACI,YAAA;AEFR;;AFIA;EAEQ;IACI,mBAAA;IACA,qCAAA;EEFV;EFIU;IACI,mBAAA;EEFd;AACF;AFGA;EAEQ;IACI,0BAAA;EEFV;AACF","file":"footer.css","sourcesContent":["@import '_vars'\n\nfooter\n padding-top: 4rem\n margin: 4rem auto\n max-width: $main-width\n\n &.wide\n max-width: $more-width\n\n div.rows\n display: grid\n grid-auto-flow: column\n // justify-content: space-between\n margin-bottom: 2rem\n\n div.row\n margin-right: 1.5rem\n margin-bottom: 0.5rem\n\n &:last-child\n margin-right: 0\n margin-bottom: 0\n\n h2\n opacity: 1\n font-size: 1rem\n font-weight: 500\n margin: 1rem 0\n line-height: normal\n\n a\n width: fit-content\n font-size: 14px\n opacity: 0.6\n display: block\n text-decoration: none\n margin-bottom: 1rem\n\n &:hover\n opacity: 0.8\n\n p\n opacity: 0.7\n\n@media (max-width: 1000px)\n footer\n div.rows\n grid-auto-flow: row\n grid-template-columns: repeat(2, 1fr)\n\n div.row\n margin-bottom: 1rem\n\n@media (max-width: 600px)\n footer\n div.rows\n grid-template-columns: 1fr\n","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #b53d61\n$primary-light: #f45a88\n$primary-glow: #f45a8861\n$primary-soft: #f79ab624\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n","footer {\n padding-top: 4rem;\n margin: 4rem auto;\n max-width: 800px;\n}\nfooter.wide {\n max-width: 1000px;\n}\nfooter div.rows {\n display: grid;\n grid-auto-flow: column;\n margin-bottom: 2rem;\n}\nfooter div.rows div.row {\n margin-right: 1.5rem;\n margin-bottom: 0.5rem;\n}\nfooter div.rows div.row:last-child {\n margin-right: 0;\n margin-bottom: 0;\n}\nfooter div.rows div.row h2 {\n opacity: 1;\n font-size: 1rem;\n font-weight: 500;\n margin: 1rem 0;\n line-height: normal;\n}\nfooter div.rows div.row a {\n width: fit-content;\n font-size: 14px;\n opacity: 0.6;\n display: block;\n text-decoration: none;\n margin-bottom: 1rem;\n}\nfooter div.rows div.row a:hover {\n opacity: 0.8;\n}\nfooter p {\n opacity: 0.7;\n}\n\n@media (max-width: 1000px) {\n footer div.rows {\n grid-auto-flow: row;\n grid-template-columns: repeat(2, 1fr);\n }\n footer div.rows div.row {\n margin-bottom: 1rem;\n }\n}\n@media (max-width: 600px) {\n footer div.rows {\n grid-template-columns: 1fr;\n }\n}"]}
|
||||
{"version":3,"sources":["footer.sass","_vars.sass","footer.css"],"names":[],"mappings":"AAEA;EACI,iBAAA;EACA,iBAAA;EACA,gBCcS;ACfb;AFGI;EACI,iBCYK;ACbb;AFGI;EACI,aAAA;EACA,sBAAA;EAEA,mBAAA;AEFR;AFIQ;EACI,oBAAA;EACA,qBAAA;AEFZ;AFIY;EACI,eAAA;EACA,gBAAA;AEFhB;AFIY;EACI,UAAA;EACA,eAAA;EACA,gBAAA;EACA,cAAA;EACA,mBAAA;AEFhB;AFIY;EACI,uBAAA;EAAA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,cAAA;EACA,qBAAA;EACA,mBAAA;AEFhB;AFIgB;EACI,YAAA;AEFpB;AFII;EACI,YAAA;AEFR;;AFIA;EAEQ;IACI,mBAAA;IACA,qCAAA;EEFV;EFIU;IACI,mBAAA;EEFd;AACF;AFGA;EAEQ;IACI,0BAAA;EEFV;AACF","file":"footer.css","sourcesContent":["@import '_vars'\n\nfooter\n padding-top: 4rem\n margin: 4rem auto\n max-width: $main-width\n\n &.wide\n max-width: $more-width\n\n div.rows\n display: grid\n grid-auto-flow: column\n // justify-content: space-between\n margin-bottom: 2rem\n\n div.row\n margin-right: 1.5rem\n margin-bottom: 0.5rem\n\n &:last-child\n margin-right: 0\n margin-bottom: 0\n\n h2\n opacity: 1\n font-size: 1rem\n font-weight: 500\n margin: 1rem 0\n line-height: normal\n\n a\n width: fit-content\n font-size: 14px\n opacity: 0.6\n display: block\n text-decoration: none\n margin-bottom: 1rem\n\n &:hover\n opacity: 0.8\n\n p\n opacity: 0.7\n\n@media (max-width: 1000px)\n footer\n div.rows\n grid-auto-flow: row\n grid-template-columns: repeat(2, 1fr)\n\n div.row\n margin-bottom: 1rem\n\n@media (max-width: 600px)\n footer\n div.rows\n grid-template-columns: 1fr\n","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #5f44b9\n$primary-light: #b88df0\n$primary-glow: #683a9638\n$primary-soft: #cc9af724\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n","footer {\n padding-top: 4rem;\n margin: 4rem auto;\n max-width: 800px;\n}\nfooter.wide {\n max-width: 1000px;\n}\nfooter div.rows {\n display: grid;\n grid-auto-flow: column;\n margin-bottom: 2rem;\n}\nfooter div.rows div.row {\n margin-right: 1.5rem;\n margin-bottom: 0.5rem;\n}\nfooter div.rows div.row:last-child {\n margin-right: 0;\n margin-bottom: 0;\n}\nfooter div.rows div.row h2 {\n opacity: 1;\n font-size: 1rem;\n font-weight: 500;\n margin: 1rem 0;\n line-height: normal;\n}\nfooter div.rows div.row a {\n width: fit-content;\n font-size: 14px;\n opacity: 0.6;\n display: block;\n text-decoration: none;\n margin-bottom: 1rem;\n}\nfooter div.rows div.row a:hover {\n opacity: 0.8;\n}\nfooter p {\n opacity: 0.7;\n}\n\n@media (max-width: 1000px) {\n footer div.rows {\n grid-auto-flow: row;\n grid-template-columns: repeat(2, 1fr);\n }\n footer div.rows div.row {\n margin-bottom: 1rem;\n }\n}\n@media (max-width: 600px) {\n footer div.rows {\n grid-template-columns: 1fr;\n }\n}"]}
|
|
@ -9,42 +9,38 @@ header h1 {
|
|||
line-height: 4rem;
|
||||
}
|
||||
|
||||
div.featured-box {
|
||||
background: rgba(247, 154, 182, 0.1411764706);
|
||||
border: 2px solid rgba(244, 90, 136, 0.3803921569);
|
||||
border-radius: 5px;
|
||||
padding: 2rem;
|
||||
div.featured__facts {
|
||||
margin-block: 2rem;
|
||||
display: flex;
|
||||
vertical-align: middle;
|
||||
transition: all 200ms;
|
||||
}
|
||||
div.featured-box:hover {
|
||||
div.featured__facts:hover {
|
||||
scale: 1.025;
|
||||
filter: brightness(1.1) saturate(1.1);
|
||||
box-shadow: 0 0 30px rgba(244, 90, 136, 0.3803921569);
|
||||
box-shadow: 0 0 30px rgba(104, 58, 150, 0.2196078431);
|
||||
}
|
||||
div.featured-box img {
|
||||
div.featured__facts img, div.featured__facts svg {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
}
|
||||
div.featured-box h2 {
|
||||
div.featured__facts h2 {
|
||||
vertical-align: middle;
|
||||
margin-block: auto;
|
||||
margin-left: 1rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
div.featured-box h2 span {
|
||||
color: #f45a88;
|
||||
div.featured__facts h2 span {
|
||||
color: #b88df0;
|
||||
}
|
||||
|
||||
div.user-quotes div.user-quote__field {
|
||||
cursor: pointer;
|
||||
margin-block: 2rem;
|
||||
padding-inline: 2rem;
|
||||
padding-block: 2rem;
|
||||
background: rgba(247, 154, 182, 0.1411764706);
|
||||
border: 2px solid rgba(244, 90, 136, 0.3803921569);
|
||||
background: rgba(204, 154, 247, 0.1411764706);
|
||||
border: 2px solid rgba(104, 58, 150, 0.2196078431);
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
transition: all 200ms;
|
||||
|
@ -54,13 +50,13 @@ div.user-quotes div.user-quote__field {
|
|||
div.user-quotes div.user-quote__field:hover {
|
||||
scale: 1.025;
|
||||
filter: brightness(1.1) saturate(1.1);
|
||||
box-shadow: 0 0 30px rgba(244, 90, 136, 0.3803921569);
|
||||
box-shadow: 0 0 30px rgba(104, 58, 150, 0.2196078431);
|
||||
}
|
||||
div.user-quotes div.user-quote__field::before {
|
||||
font-family: "Times New Roman", Times, serif;
|
||||
content: "“";
|
||||
font-size: 150px;
|
||||
color: rgba(247, 154, 182, 0.1411764706);
|
||||
color: rgba(204, 154, 247, 0.1411764706);
|
||||
position: absolute;
|
||||
bottom: -1rem;
|
||||
left: 1rem;
|
||||
|
@ -71,7 +67,7 @@ div.user-quotes div.user-quote__field img {
|
|||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid rgba(244, 90, 136, 0.3803921569);
|
||||
border: 3px solid rgba(104, 58, 150, 0.2196078431);
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
|
@ -81,7 +77,7 @@ div.user-quotes div.user-quote__field img {
|
|||
div.user-quotes div.user-quote__field span.user-quote__username {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: #b53d61;
|
||||
color: #b88df0;
|
||||
}
|
||||
div.user-quotes div.user-quote__field p {
|
||||
margin-block: 0;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -9,11 +9,7 @@ header
|
|||
h1
|
||||
line-height: 4rem
|
||||
|
||||
div.featured-box
|
||||
background: $primary-soft
|
||||
border: 2px solid $primary-glow
|
||||
border-radius: $edge
|
||||
padding: 2rem
|
||||
div.featured__facts
|
||||
margin-block: 2rem
|
||||
display: flex
|
||||
vertical-align: middle
|
||||
|
@ -24,7 +20,8 @@ div.featured-box
|
|||
filter: brightness(1.1) saturate(1.1)
|
||||
box-shadow: 0 0 30px $primary-glow
|
||||
|
||||
img
|
||||
img, svg
|
||||
width: 50px
|
||||
height: 50px
|
||||
object-fit: cover
|
||||
|
||||
|
@ -43,9 +40,8 @@ div.user-quotes
|
|||
// grid-gap: 2rem
|
||||
|
||||
div.user-quote__field
|
||||
cursor: pointer
|
||||
margin-block: 2rem
|
||||
padding-inline: 2rem
|
||||
padding-block: 2rem
|
||||
background: $primary-soft
|
||||
border: 2px solid $primary-glow
|
||||
border-radius: $edge
|
||||
|
@ -85,7 +81,7 @@ div.user-quotes
|
|||
span.user-quote__username
|
||||
font-size: 1rem
|
||||
font-weight: 600
|
||||
color: $primary
|
||||
color: $primary-light
|
||||
|
||||
p
|
||||
margin-block: 0
|
||||
|
|
|
@ -7,17 +7,17 @@ button {
|
|||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: #f3f3f3;
|
||||
background: #b53d61;
|
||||
background: #5f44b9;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
button:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
button.special {
|
||||
box-shadow: 0 0 20px rgba(244, 90, 136, 0.3803921569);
|
||||
box-shadow: 0 0 20px rgba(104, 58, 150, 0.2196078431);
|
||||
}
|
||||
button.special:hover {
|
||||
box-shadow: 0 0 20px #b53d61;
|
||||
box-shadow: 0 0 20px #5f44b9;
|
||||
}
|
||||
button.secondary {
|
||||
color: #f3f3f3;
|
||||
|
@ -41,7 +41,7 @@ input:not([type=checkbox]):not([type=radio]) {
|
|||
padding: 0.5rem 1rem;
|
||||
color: #f3f3f3;
|
||||
background: #252a38;
|
||||
border: 1px solid #b53d61;
|
||||
border: 1px solid #5f44b9;
|
||||
}
|
||||
input:not([type=checkbox]):not([type=radio]):focus {
|
||||
outline: none;
|
||||
|
@ -49,4 +49,30 @@ input:not([type=checkbox]):not([type=radio]):focus {
|
|||
|
||||
input[type=radio] {
|
||||
filter: hue-rotate(50deg);
|
||||
}
|
||||
|
||||
span.secret {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-family: monospace;
|
||||
padding: 2px 4px;
|
||||
border-radius: 5px;
|
||||
color: transparent;
|
||||
background: rgba(252, 247, 248, 0.1411764706);
|
||||
transition: color 200ms;
|
||||
}
|
||||
span.secret.revealed {
|
||||
color: #f3f3f3;
|
||||
background: rgba(252, 247, 248, 0.1411764706);
|
||||
}
|
||||
|
||||
.copied::after {
|
||||
content: "Copied!";
|
||||
position: absolute;
|
||||
padding: 2px 4px;
|
||||
transform: translateX(10px);
|
||||
border-radius: 5px;
|
||||
background: rgba(252, 247, 248, 0.1411764706);
|
||||
border: 1px solid #28ef6b;
|
||||
color: #f3f3f3;
|
||||
}/*# sourceMappingURL=input.css.map */
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["input.sass","_vars.sass","input.css"],"names":[],"mappings":"AAEA;EACI,cAAA;EACA,eAAA;EACA,eAAA;EACA,kBCWG;EDVH,sBAAA;EACA,gBAAA;EACA,mBAAA;EAEA,cCXG;EDYH,mBCLM;EDON,2BAAA;AEHJ;AFKI;EACI,uBAAA;AEHR;AFKI;EACI,qDAAA;AEHR;AFKQ;EACI,4BAAA;AEHZ;AFKI;EACI,cC1BD;ED2BC,mBCzBI;ED0BJ,gDAAA;AEHR;AFKI;EACI,YAAA;EACA,qBAAA;EACA,sBAAA;EACA,mBAAA;AEHR;AFKI;EACI,6CChCD;AC6BP;;AFKA;EACI,WAAA;EACA,eAAA;EACA,kBCzBG;ED0BH,oBAAA;EAEA,cC7CG;ED8CH,mBC5CQ;ED6CR,yBAAA;AEHJ;AFKI;EACI,aAAA;AEHR;;AFKA;EACI,yBAAA;AEFJ","file":"input.css","sourcesContent":["@import '_vars'\n\nbutton\n line-height: 2\n cursor: pointer\n font-size: 16px\n border-radius: $edge\n padding: 0.7rem 1.5rem\n font-weight: 600\n margin-bottom: 1rem\n\n color: $text\n background: $primary\n\n transition: box-shadow 0.2s\n\n &:hover\n filter: brightness(1.2)\n\n &.special\n box-shadow: 0 0 20px $primary-glow\n\n &:hover\n box-shadow: 0 0 20px $primary\n\n &.secondary\n color: $text\n background: $secondary\n border: 1px solid $border\n\n svg, img\n height: 24px\n display: inline-block\n vertical-align: middle\n filter: invert(180)\n\n mark\n background: $soft\n\ninput:not([type=\"checkbox\"]):not([type=\"radio\"])\n width: 100%\n font-size: 18px\n border-radius: $edge\n padding: 0.5rem 1rem\n\n color: $text\n background: $secondary\n border: 1px solid $primary\n\n &:focus\n outline: none\n\ninput[type=\"radio\"]\n filter: hue-rotate(50deg)\n","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #b53d61\n$primary-light: #f45a88\n$primary-glow: #f45a8861\n$primary-soft: #f79ab624\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n","button {\n line-height: 2;\n cursor: pointer;\n font-size: 16px;\n border-radius: 5px;\n padding: 0.7rem 1.5rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: #f3f3f3;\n background: #b53d61;\n transition: box-shadow 0.2s;\n}\nbutton:hover {\n filter: brightness(1.2);\n}\nbutton.special {\n box-shadow: 0 0 20px rgba(244, 90, 136, 0.3803921569);\n}\nbutton.special:hover {\n box-shadow: 0 0 20px #b53d61;\n}\nbutton.secondary {\n color: #f3f3f3;\n background: #252a38;\n border: 1px solid rgba(22, 29, 43, 0.6901960784);\n}\nbutton svg, button img {\n height: 24px;\n display: inline-block;\n vertical-align: middle;\n filter: invert(180);\n}\nbutton mark {\n background: rgba(252, 247, 248, 0.1411764706);\n}\n\ninput:not([type=checkbox]):not([type=radio]) {\n width: 100%;\n font-size: 18px;\n border-radius: 5px;\n padding: 0.5rem 1rem;\n color: #f3f3f3;\n background: #252a38;\n border: 1px solid #b53d61;\n}\ninput:not([type=checkbox]):not([type=radio]):focus {\n outline: none;\n}\n\ninput[type=radio] {\n filter: hue-rotate(50deg);\n}"]}
|
||||
{"version":3,"sources":["input.sass","_vars.sass","input.css"],"names":[],"mappings":"AAEA;EACI,cAAA;EACA,eAAA;EACA,eAAA;EACA,kBCWG;EDVH,sBAAA;EACA,gBAAA;EACA,mBAAA;EAEA,cCXG;EDYH,mBCLM;EDON,2BAAA;AEHJ;AFKI;EACI,uBAAA;AEHR;AFKI;EACI,qDAAA;AEHR;AFKQ;EACI,4BAAA;AEHZ;AFKI;EACI,cC1BD;ED2BC,mBCzBI;ED0BJ,gDAAA;AEHR;AFKI;EACI,YAAA;EACA,qBAAA;EACA,sBAAA;EACA,mBAAA;AEHR;AFKI;EACI,6CChCD;AC6BP;;AFKA;EACI,WAAA;EACA,eAAA;EACA,kBCzBG;ED0BH,oBAAA;EAEA,cC7CG;ED8CH,mBC5CQ;ED6CR,yBAAA;AEHJ;AFKI;EACI,aAAA;AEHR;;AFKA;EACI,yBAAA;AEFJ;;AFIA;EACI,eAAA;EACA,eAAA;EACA,sBAAA;EACA,gBAAA;EACA,kBC3CG;ED4CH,kBAAA;EACA,6CCzDG;ED2DH,uBAAA;AEFJ;AFII;EACI,cCnED;EDoEC,6CC/DD;AC6DP;;AFIA;EACI,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,2BAAA;EACA,kBC1DG;ED2DH,6CCvEG;EDwEH,yBAAA;EACA,cC9EG;AC6EP","file":"input.css","sourcesContent":["@import '_vars'\n\nbutton\n line-height: 2\n cursor: pointer\n font-size: 16px\n border-radius: $edge\n padding: 0.7rem 1.5rem\n font-weight: 600\n margin-bottom: 1rem\n\n color: $text\n background: $primary\n\n transition: box-shadow 0.2s\n\n &:hover\n filter: brightness(1.2)\n\n &.special\n box-shadow: 0 0 20px $primary-glow\n\n &:hover\n box-shadow: 0 0 20px $primary\n\n &.secondary\n color: $text\n background: $secondary\n border: 1px solid $border\n\n svg, img\n height: 24px\n display: inline-block\n vertical-align: middle\n filter: invert(180)\n\n mark\n background: $soft\n\ninput:not([type=\"checkbox\"]):not([type=\"radio\"])\n width: 100%\n font-size: 18px\n border-radius: $edge\n padding: 0.5rem 1rem\n\n color: $text\n background: $secondary\n border: 1px solid $primary\n\n &:focus\n outline: none\n\ninput[type=\"radio\"]\n filter: hue-rotate(50deg)\n\nspan.secret\n cursor: pointer\n font-size: 14px\n font-family: monospace\n padding: 2px 4px\n border-radius: $edge\n color: transparent\n background: $soft\n\n transition: color 200ms\n\n &.revealed\n color: $text\n background: $soft\n\n.copied::after\n content: 'Copied!'\n position: absolute\n padding: 2px 4px\n transform: translateX(10px)\n border-radius: $edge\n background: $soft\n border: 1px solid $success\n color: $text\n","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #5f44b9\n$primary-light: #b88df0\n$primary-glow: #683a9638\n$primary-soft: #cc9af724\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n","button {\n line-height: 2;\n cursor: pointer;\n font-size: 16px;\n border-radius: 5px;\n padding: 0.7rem 1.5rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: #f3f3f3;\n background: #5f44b9;\n transition: box-shadow 0.2s;\n}\nbutton:hover {\n filter: brightness(1.2);\n}\nbutton.special {\n box-shadow: 0 0 20px rgba(104, 58, 150, 0.2196078431);\n}\nbutton.special:hover {\n box-shadow: 0 0 20px #5f44b9;\n}\nbutton.secondary {\n color: #f3f3f3;\n background: #252a38;\n border: 1px solid rgba(22, 29, 43, 0.6901960784);\n}\nbutton svg, button img {\n height: 24px;\n display: inline-block;\n vertical-align: middle;\n filter: invert(180);\n}\nbutton mark {\n background: rgba(252, 247, 248, 0.1411764706);\n}\n\ninput:not([type=checkbox]):not([type=radio]) {\n width: 100%;\n font-size: 18px;\n border-radius: 5px;\n padding: 0.5rem 1rem;\n color: #f3f3f3;\n background: #252a38;\n border: 1px solid #5f44b9;\n}\ninput:not([type=checkbox]):not([type=radio]):focus {\n outline: none;\n}\n\ninput[type=radio] {\n filter: hue-rotate(50deg);\n}\n\nspan.secret {\n cursor: pointer;\n font-size: 14px;\n font-family: monospace;\n padding: 2px 4px;\n border-radius: 5px;\n color: transparent;\n background: rgba(252, 247, 248, 0.1411764706);\n transition: color 200ms;\n}\nspan.secret.revealed {\n color: #f3f3f3;\n background: rgba(252, 247, 248, 0.1411764706);\n}\n\n.copied::after {\n content: \"Copied!\";\n position: absolute;\n padding: 2px 4px;\n transform: translateX(10px);\n border-radius: 5px;\n background: rgba(252, 247, 248, 0.1411764706);\n border: 1px solid #28ef6b;\n color: #f3f3f3;\n}"]}
|
|
@ -52,3 +52,28 @@ input:not([type="checkbox"]):not([type="radio"])
|
|||
|
||||
input[type="radio"]
|
||||
filter: hue-rotate(50deg)
|
||||
|
||||
span.secret
|
||||
cursor: pointer
|
||||
font-size: 14px
|
||||
font-family: monospace
|
||||
padding: 2px 4px
|
||||
border-radius: $edge
|
||||
color: transparent
|
||||
background: $soft
|
||||
|
||||
transition: color 200ms
|
||||
|
||||
&.revealed
|
||||
color: $text
|
||||
background: $soft
|
||||
|
||||
.copied::after
|
||||
content: 'Copied!'
|
||||
position: absolute
|
||||
padding: 2px 4px
|
||||
transform: translateX(10px)
|
||||
border-radius: $edge
|
||||
background: $soft
|
||||
border: 1px solid $success
|
||||
color: $text
|
||||
|
|
|
@ -5,7 +5,7 @@ nav {
|
|||
}
|
||||
nav > .logo {
|
||||
display: inline-block;
|
||||
stroke: #f45a88;
|
||||
stroke: #b88df0;
|
||||
min-height: 40px;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
|
@ -41,7 +41,7 @@ nav #menu {
|
|||
transition: color 0.1s;
|
||||
}
|
||||
.link-menu > a:hover {
|
||||
color: #f45a88;
|
||||
color: #b88df0;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
|
@ -71,7 +71,7 @@ nav #menu {
|
|||
line-height: 3rem;
|
||||
}
|
||||
nav .logo {
|
||||
stroke: #f45a88;
|
||||
stroke: #b88df0;
|
||||
}
|
||||
nav #menu {
|
||||
display: block;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["navbar.sass","navbar.css","_vars.sass"],"names":[],"mappings":"AAEA;EACI,aAAA;EACA,mBAAA;EACA,kBAAA;ACDJ;ADGI;EACI,qBAAA;EACA,eEDQ;EFER,gBAAA;EACA,eAAA;EACA,YAAA;EACA,WAAA;EAEA,iBAAA;EACA,uBAAA;ACFR;ADII;EACI,gBAAA;EACA,eAAA;EACA,yBAAA;KAAA,sBAAA;UAAA,iBAAA;ACFR;ADIQ;EACI,eAAA;EACA,kBAAA;EACA,SAAA;ACFZ;ADKI;EACI,YAAA;ACHR;ADMI;EACI,aAAA;EACA,eAAA;ACJR;;ADOI;EACI,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,sBAAA;ACJR;ADMQ;EACI,cEtCI;ADkChB;;ADMA;EACI;IACI,sCAAA;IACA,UAAA;IAEA,YAAA;IACA,YAAA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,mBExDI;IFyDJ,eAAA;IACA,kBE3CD;IF4CC,kCAAA;YAAA,0BAAA;IACA,gDAAA;IAEA,wCAAA;ECLN;EDOM;IACI,UAAA;IACA,kBAAA;ECLV;EDOM;IACI,eAAA;IACA,cAAA;IACA,iBAAA;ECLV;EDQM;IACI,eErEI;ED+Dd;EDQM;IACI,cAAA;IACA,gBAAA;IACA,eAAA;IACA,YAAA;IACA,WAAA;IACA,eAAA;IACA,gBAAA;ECNV;EDQU;IACI,wBAAA;ECNd;AACF;ADOA;EAEQ;IACI,aAAA;ECNV;AACF","file":"navbar.css","sourcesContent":["@import '_vars'\n\nnav\n display: flex\n align-items: center\n position: relative\n\n >.logo\n display: inline-block\n stroke: $primary-light\n min-height: 40px\n min-width: 40px\n height: 40px\n width: 40px\n\n margin-right: 8px\n transition: stroke 0.2s\n\n >h1\n font-weight: 500\n font-size: 20px\n user-select: none\n\n mark\n font-size: 1rem\n position: relative\n top: -3px\n\n\n >span\n flex-grow: 1\n\n\n #menu\n display: none\n cursor: pointer\n\n.link-menu\n >a\n font-size: 14px\n font-weight: 600\n margin-left: 2rem\n text-decoration: none\n transition: color 0.1s\n\n &:hover\n color: $primary-light\n\n@media (max-width: 800px)\n .link-menu\n transform: scale(0.8) translateX(1rem)\n opacity: 0\n\n z-index: 100\n width: 200px\n position: absolute\n top: 5rem\n right: 2rem\n background: $secondary\n padding: 1rem 0\n border-radius: $edge\n backdrop-filter: blur(4px)\n border: 1px solid $border\n\n transition: transform 0.2s, opacity 0.2s\n\n &.open\n opacity: 1\n transform: inherit\n\n a\n font-size: 20px\n display: block\n line-height: 3rem\n\n nav\n .logo\n stroke: $primary-light\n\n #menu\n display: block\n min-height: 32px\n min-width: 32px\n height: 32px\n width: 32px\n cursor: pointer\n transition: 0.5s\n\n &.active\n transform: rotate(90deg)\n\n@media (max-width: 400px)\n nav\n h1\n display: none","nav {\n display: flex;\n align-items: center;\n position: relative;\n}\nnav > .logo {\n display: inline-block;\n stroke: #f45a88;\n min-height: 40px;\n min-width: 40px;\n height: 40px;\n width: 40px;\n margin-right: 8px;\n transition: stroke 0.2s;\n}\nnav > h1 {\n font-weight: 500;\n font-size: 20px;\n user-select: none;\n}\nnav > h1 mark {\n font-size: 1rem;\n position: relative;\n top: -3px;\n}\nnav > span {\n flex-grow: 1;\n}\nnav #menu {\n display: none;\n cursor: pointer;\n}\n\n.link-menu > a {\n font-size: 14px;\n font-weight: 600;\n margin-left: 2rem;\n text-decoration: none;\n transition: color 0.1s;\n}\n.link-menu > a:hover {\n color: #f45a88;\n}\n\n@media (max-width: 800px) {\n .link-menu {\n transform: scale(0.8) translateX(1rem);\n opacity: 0;\n z-index: 100;\n width: 200px;\n position: absolute;\n top: 5rem;\n right: 2rem;\n background: #252a38;\n padding: 1rem 0;\n border-radius: 5px;\n backdrop-filter: blur(4px);\n border: 1px solid rgba(22, 29, 43, 0.6901960784);\n transition: transform 0.2s, opacity 0.2s;\n }\n .link-menu.open {\n opacity: 1;\n transform: inherit;\n }\n .link-menu a {\n font-size: 20px;\n display: block;\n line-height: 3rem;\n }\n nav .logo {\n stroke: #f45a88;\n }\n nav #menu {\n display: block;\n min-height: 32px;\n min-width: 32px;\n height: 32px;\n width: 32px;\n cursor: pointer;\n transition: 0.5s;\n }\n nav #menu.active {\n transform: rotate(90deg);\n }\n}\n@media (max-width: 400px) {\n nav h1 {\n display: none;\n }\n}","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #b53d61\n$primary-light: #f45a88\n$primary-glow: #f45a8861\n$primary-soft: #f79ab624\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n"]}
|
||||
{"version":3,"sources":["navbar.sass","navbar.css","_vars.sass"],"names":[],"mappings":"AAEA;EACI,aAAA;EACA,mBAAA;EACA,kBAAA;ACDJ;ADGI;EACI,qBAAA;EACA,eEDQ;EFER,gBAAA;EACA,eAAA;EACA,YAAA;EACA,WAAA;EAEA,iBAAA;EACA,uBAAA;ACFR;ADII;EACI,gBAAA;EACA,eAAA;EACA,yBAAA;KAAA,sBAAA;UAAA,iBAAA;ACFR;ADIQ;EACI,eAAA;EACA,kBAAA;EACA,SAAA;ACFZ;ADKI;EACI,YAAA;ACHR;ADMI;EACI,aAAA;EACA,eAAA;ACJR;;ADOI;EACI,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,sBAAA;ACJR;ADMQ;EACI,cEtCI;ADkChB;;ADMA;EACI;IACI,sCAAA;IACA,UAAA;IAEA,YAAA;IACA,YAAA;IACA,kBAAA;IACA,SAAA;IACA,WAAA;IACA,mBExDI;IFyDJ,eAAA;IACA,kBE3CD;IF4CC,kCAAA;YAAA,0BAAA;IACA,gDAAA;IAEA,wCAAA;ECLN;EDOM;IACI,UAAA;IACA,kBAAA;ECLV;EDOM;IACI,eAAA;IACA,cAAA;IACA,iBAAA;ECLV;EDQM;IACI,eErEI;ED+Dd;EDQM;IACI,cAAA;IACA,gBAAA;IACA,eAAA;IACA,YAAA;IACA,WAAA;IACA,eAAA;IACA,gBAAA;ECNV;EDQU;IACI,wBAAA;ECNd;AACF;ADOA;EAEQ;IACI,aAAA;ECNV;AACF","file":"navbar.css","sourcesContent":["@import '_vars'\n\nnav\n display: flex\n align-items: center\n position: relative\n\n >.logo\n display: inline-block\n stroke: $primary-light\n min-height: 40px\n min-width: 40px\n height: 40px\n width: 40px\n\n margin-right: 8px\n transition: stroke 0.2s\n\n >h1\n font-weight: 500\n font-size: 20px\n user-select: none\n\n mark\n font-size: 1rem\n position: relative\n top: -3px\n\n\n >span\n flex-grow: 1\n\n\n #menu\n display: none\n cursor: pointer\n\n.link-menu\n >a\n font-size: 14px\n font-weight: 600\n margin-left: 2rem\n text-decoration: none\n transition: color 0.1s\n\n &:hover\n color: $primary-light\n\n@media (max-width: 800px)\n .link-menu\n transform: scale(0.8) translateX(1rem)\n opacity: 0\n\n z-index: 100\n width: 200px\n position: absolute\n top: 5rem\n right: 2rem\n background: $secondary\n padding: 1rem 0\n border-radius: $edge\n backdrop-filter: blur(4px)\n border: 1px solid $border\n\n transition: transform 0.2s, opacity 0.2s\n\n &.open\n opacity: 1\n transform: inherit\n\n a\n font-size: 20px\n display: block\n line-height: 3rem\n\n nav\n .logo\n stroke: $primary-light\n\n #menu\n display: block\n min-height: 32px\n min-width: 32px\n height: 32px\n width: 32px\n cursor: pointer\n transition: 0.5s\n\n &.active\n transform: rotate(90deg)\n\n@media (max-width: 400px)\n nav\n h1\n display: none","nav {\n display: flex;\n align-items: center;\n position: relative;\n}\nnav > .logo {\n display: inline-block;\n stroke: #b88df0;\n min-height: 40px;\n min-width: 40px;\n height: 40px;\n width: 40px;\n margin-right: 8px;\n transition: stroke 0.2s;\n}\nnav > h1 {\n font-weight: 500;\n font-size: 20px;\n user-select: none;\n}\nnav > h1 mark {\n font-size: 1rem;\n position: relative;\n top: -3px;\n}\nnav > span {\n flex-grow: 1;\n}\nnav #menu {\n display: none;\n cursor: pointer;\n}\n\n.link-menu > a {\n font-size: 14px;\n font-weight: 600;\n margin-left: 2rem;\n text-decoration: none;\n transition: color 0.1s;\n}\n.link-menu > a:hover {\n color: #b88df0;\n}\n\n@media (max-width: 800px) {\n .link-menu {\n transform: scale(0.8) translateX(1rem);\n opacity: 0;\n z-index: 100;\n width: 200px;\n position: absolute;\n top: 5rem;\n right: 2rem;\n background: #252a38;\n padding: 1rem 0;\n border-radius: 5px;\n backdrop-filter: blur(4px);\n border: 1px solid rgba(22, 29, 43, 0.6901960784);\n transition: transform 0.2s, opacity 0.2s;\n }\n .link-menu.open {\n opacity: 1;\n transform: inherit;\n }\n .link-menu a {\n font-size: 20px;\n display: block;\n line-height: 3rem;\n }\n nav .logo {\n stroke: #b88df0;\n }\n nav #menu {\n display: block;\n min-height: 32px;\n min-width: 32px;\n height: 32px;\n width: 32px;\n cursor: pointer;\n transition: 0.5s;\n }\n nav #menu.active {\n transform: rotate(90deg);\n }\n}\n@media (max-width: 400px) {\n nav h1 {\n display: none;\n }\n}","$text: #f3f3f3\n$background: #03060d\n$secondary: #252a38\n$secondary-dark: #0e0e0e\n$border: #161d2bb0\n$soft: #fcf7f824\n\n$primary: #5f44b9\n$primary-light: #b88df0\n$primary-glow: #683a9638\n$primary-soft: #cc9af724\n$accent: #28aaf0\n\n$error: #ef3628\n$warn: #f09928\n$success: #28ef6b\n\n$edge: 5px\n\n$main-width: 800px\n$more-width: 1000px\n"]}
|
20
web/static/css/profile.css
Normal file
20
web/static/css/profile.css
Normal file
|
@ -0,0 +1,20 @@
|
|||
div.profile-base div.profile-header {
|
||||
display: flex;
|
||||
}
|
||||
div.profile-base div.profile-header img {
|
||||
height: 100px;
|
||||
-o-object-fit: cover;
|
||||
object-fit: cover;
|
||||
-o-object-position: center;
|
||||
object-position: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
div.profile-base div.profile-header h2 {
|
||||
margin-block: auto;
|
||||
margin-left: 1rem;
|
||||
font-size: 2rem;
|
||||
}
|
||||
div.profile-base div.profile-info {
|
||||
line-height: 1.5rem;
|
||||
padding: 2rem;
|
||||
}/*# sourceMappingURL=profile.css.map */
|
1
web/static/css/profile.css.map
Normal file
1
web/static/css/profile.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["profile.sass","profile.css"],"names":[],"mappings":"AAGI;EACI,aAAA;ACFR;ADIQ;EACI,aAAA;EACA,oBAAA;KAAA,iBAAA;EACA,0BAAA;KAAA,uBAAA;EACA,kBAAA;ACFZ;ADIQ;EACI,kBAAA;EACA,iBAAA;EACA,eAAA;ACFZ;ADII;EACI,mBAAA;EACA,aAAA;ACFR","file":"profile.css","sourcesContent":["@import '_vars'\n\ndiv.profile-base\n div.profile-header\n display: flex\n\n img\n height: 100px\n object-fit: cover\n object-position: center\n border-radius: 50%\n\n h2\n margin-block: auto\n margin-left: 1rem\n font-size: 2rem\n\n div.profile-info\n line-height: 1.5rem\n padding: 2rem\n","div.profile-base div.profile-header {\n display: flex;\n}\ndiv.profile-base div.profile-header img {\n height: 100px;\n object-fit: cover;\n object-position: center;\n border-radius: 50%;\n}\ndiv.profile-base div.profile-header h2 {\n margin-block: auto;\n margin-left: 1rem;\n font-size: 2rem;\n}\ndiv.profile-base div.profile-info {\n line-height: 1.5rem;\n padding: 2rem;\n}"]}
|
20
web/static/css/profile.sass
Normal file
20
web/static/css/profile.sass
Normal file
|
@ -0,0 +1,20 @@
|
|||
@import '_vars'
|
||||
|
||||
div.profile-base
|
||||
div.profile-header
|
||||
display: flex
|
||||
|
||||
img
|
||||
height: 100px
|
||||
object-fit: cover
|
||||
object-position: center
|
||||
border-radius: 50%
|
||||
|
||||
h2
|
||||
margin-block: auto
|
||||
margin-left: 1rem
|
||||
font-size: 2rem
|
||||
|
||||
div.profile-info
|
||||
line-height: 1.5rem
|
||||
padding: 2rem
|
|
@ -1,8 +1,43 @@
|
|||
{% include 'common/begin.html' %}
|
||||
|
||||
<main>
|
||||
<h1>Welcome back, {{ user.username }}</h1>
|
||||
<h1>Welcome back, <a>{{ user.display_name or 'Guest' }}</a>!</h1>
|
||||
|
||||
<div class="profile-base">
|
||||
<div class="profile-header">
|
||||
<img src="{{ user.avatar }}" alt="Discord profile avatar">
|
||||
<h2>{{ user.username or 'Guest' }}</h2>
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<b>Your reward rank: </b> {{ user.role or 'default' }}<br>
|
||||
<b>API credits: </b> {{ user.credits or 0 }}<br>
|
||||
<b>Secret API key (click to reveal): </b>
|
||||
<br>
|
||||
<span class="secret">{{ user.api_key or '-' }}</span>
|
||||
<br>(Click again to copy)
|
||||
<br>
|
||||
<script>
|
||||
let clicks = 0;
|
||||
|
||||
// reveal secret API key on click by adding "revealed" class
|
||||
document.querySelector('.secret').addEventListener('click', function() {
|
||||
this.classList.add('revealed');
|
||||
clicks++;
|
||||
});
|
||||
|
||||
// copy on click
|
||||
document.querySelector('.secret').addEventListener('click', function() {
|
||||
if (clicks > 1) {
|
||||
navigator.clipboard.writeText(this.textContent);
|
||||
this.classList.add('copied')
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<br>
|
||||
<a href="/logout">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{% include 'common/end.html' %}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
{% include 'common/seo.html' %}
|
||||
|
||||
{% for css in 'navbar base footer input fonts'.split() %}
|
||||
{% for css in 'navbar base footer input fonts profile'.split() %}
|
||||
<link rel="stylesheet" href="/static/css/{{ css }}.css">
|
||||
{% endfor %}
|
||||
|
||||
|
|
|
@ -3,18 +3,18 @@
|
|||
|
||||
<header>
|
||||
<h1>Free Generative AI for <span class="special-gradient">Everyone</span></h1>
|
||||
<h3>Make AI Open Again</h3>
|
||||
<h3>Open source ・ no CC required</h3>
|
||||
<a href="https://discord.nova-oss.com" target="_blank">
|
||||
<button class="special">
|
||||
<i class="bi bi-discord"></i>
|
||||
Join 2,300+ members
|
||||
Join 3,400+ members
|
||||
</button>
|
||||
</a>
|
||||
<!-- <a href="/login"> -->
|
||||
<button class="secondary" style="pointer-events: none; cursor: not-allowed; opacity: 0.5;">
|
||||
Log in <mark>coming soon</mark>
|
||||
<a href="/login">
|
||||
<button class="secondary">
|
||||
Log in <mark>beta</mark>
|
||||
</button>
|
||||
<!-- </a> -->
|
||||
</a>
|
||||
<br>
|
||||
</header>
|
||||
<main>
|
||||
|
@ -28,15 +28,22 @@
|
|||
</p>
|
||||
|
||||
<h2>About Nova</h2>
|
||||
<div class="featured-box">
|
||||
<img src="https://icons.getbootstrap.com/assets/icons/cash-coin.svg" style="filter: invert(1);">
|
||||
<div class="featured__facts box">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-cash-coin" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M11 15a4 4 0 1 0 0-8 4 4 0 0 0 0 8zm5-4a5 5 0 1 1-10 0 5 5 0 0 1 10 0z"/>
|
||||
<path d="M9.438 11.944c.047.596.518 1.06 1.363 1.116v.44h.375v-.443c.875-.061 1.386-.529 1.386-1.207 0-.618-.39-.936-1.09-1.1l-.296-.07v-1.2c.376.043.614.248.671.532h.658c-.047-.575-.54-1.024-1.329-1.073V8.5h-.375v.45c-.747.073-1.255.522-1.255 1.158 0 .562.378.92 1.007 1.066l.248.061v1.272c-.384-.058-.639-.27-.696-.563h-.668zm1.36-1.354c-.369-.085-.569-.26-.569-.522 0-.294.216-.514.572-.578v1.1h-.003zm.432.746c.449.104.655.272.655.569 0 .339-.257.571-.709.614v-1.195l.054.012z"/>
|
||||
<path d="M1 0a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4.083c.058-.344.145-.678.258-1H3a2 2 0 0 0-2-2V3a2 2 0 0 0 2-2h10a2 2 0 0 0 2 2v3.528c.38.34.717.728 1 1.154V1a1 1 0 0 0-1-1H1z"/>
|
||||
<path d="M9.998 5.083 10 5a2 2 0 1 0-3.132 1.65 5.982 5.982 0 0 1 3.13-1.567z"/>
|
||||
</svg>
|
||||
<h2>Free <span>forever</span> - no credit card required</h2>
|
||||
</div>
|
||||
<div class="featured-box" onclick="window.open('https://github.com/orgs/NovaOSS/repositories', '_blank')">
|
||||
<img src="https://icons.getbootstrap.com/assets/icons/github.svg" style="filter: invert(1);">
|
||||
<div class="featured__facts box" onclick="window.open('https://github.com/orgs/NovaOSS/repositories', '_blank')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-github" viewBox="0 0 16 16">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||
</svg>
|
||||
<h2>Open source on <span>GitHub</span></h2>
|
||||
</div>
|
||||
<div class="featured-box" onclick="window.open('https://fmhy.pages.dev/ai', '_blank')">
|
||||
<div class="featured__facts box" onclick="window.open('https://fmhy.pages.dev/ai', '_blank')">
|
||||
<img src="https://fmhy.pages.dev/static/fmhy.ico">
|
||||
<h2>Featured in <span>Free Media Heck Yeah</span></h2>
|
||||
</div>
|
||||
|
@ -44,43 +51,49 @@
|
|||
<h2>What users say</h2>
|
||||
|
||||
<div class="user-quotes">
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1144279505981153302', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1144279505981153302', '_blank')">
|
||||
<img src="https://i.ibb.co/dfWkyB3/86b4f6da0e44bf8545be937d66017b71.png">
|
||||
<span class="user-quote__username">Krit</span>
|
||||
<p>We can all agree that NovaAI is the best.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1148559579890864178', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1151770993837219871', '_blank')">
|
||||
<img src="https://i.ibb.co/XbnHFQm/a2000af4431e49565a8f8d97455418b9.png">
|
||||
<span class="user-quote__username">forrany</span>
|
||||
<p>NovaAI responses are so fast. Probably the fastest API I've ever used, other [Discord servers] like FoxGPT and PurGPT are not as fast as NovaAI.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1148559579890864178', '_blank')">
|
||||
<img src="https://i.ibb.co/p4TB2nm/f44610c370eec2b28ccc926e61fb86fe.png">
|
||||
<span class="user-quote__username">Tech With Anirudh</span>
|
||||
<p>NovaOSS is really good, I mean really. The code's good. The website's good. The API's good.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1145791262063075378', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1145791262063075378', '_blank')">
|
||||
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Femoji.gg%2Fassets%2Femoji%2F1129-discord.png&f=1&nofb=1&ipt=c507c1ea551b33c06e1f2bc2baa5f1d3eb29bca0d721db852876a86de198a944&ipo=images">
|
||||
<span class="user-quote__username">David</span>
|
||||
<p>Nova is good. I love it because [it's] free and easy.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1117511140440821852/1149316497265660045/1149316515724787752', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1117511140440821852/1149316497265660045/1149316515724787752', '_blank')">
|
||||
<img src="https://i.ibb.co/XzDPQJs/image.png">
|
||||
<span class="user-quote__username">Tolgchu (co-owner of PurGPT)</span>
|
||||
<p>Would you like a fully open-source API including GPT-4-32k? It's even fully free and has 0% reverse engineering!</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120753218071310346/1149291492335177818/1149293863597514772', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120753218071310346/1149291492335177818/1149293863597514772', '_blank')">
|
||||
<img src="https://i.ibb.co/DGxdgWX/image.png">
|
||||
<span class="user-quote__username">Koru (owner of Skailar)</span>
|
||||
<p>Nova [is] an open source, ethically sourced (no reverse engineering, just like us) API with high limits and a big amount of available models.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1145324231236780092', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1145324231236780092', '_blank')">
|
||||
<img src="https://i.ibb.co/DKDm8hg/image.png">
|
||||
<span class="user-quote__username">Perl (owner of GeniusAI)</span>
|
||||
<p>I love the credit system in this API.</p>
|
||||
</div>
|
||||
|
||||
<div class="user-quote__field" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1143784944888447037', '_blank')">
|
||||
<div class="user-quote__field box" onclick="window.open('https://discord.com/channels/1120037287300976640/1120037729644855427/1143784944888447037', '_blank')">
|
||||
<img src="https://i.ibb.co/9grjkW2/b461ea5ea97a773d000300e4d978e24d.png">
|
||||
<span class="user-quote__username">Flying Elephant</span>
|
||||
<p>You are so excellent [...]. Thank you for your contributions.</p>
|
||||
|
|
0
web/tos.py
Normal file → Executable file
0
web/tos.py
Normal file → Executable file
Loading…
Reference in a new issue