Lots of good progress getting it setup. Need to figure out templating, easier calling of functions, and cleaner routing.
This commit is contained in:
BIN
__pycache__/apicalls.cpython-311.pyc
Normal file
BIN
__pycache__/apicalls.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/config.cpython-311.pyc
Normal file
BIN
__pycache__/config.cpython-311.pyc
Normal file
Binary file not shown.
1
apicalls.py
Normal file
1
apicalls.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from app import app
|
||||||
7
app/__init__.py
Normal file
7
app/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from flask import Flask
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(Config)
|
||||||
|
|
||||||
|
from app import routes
|
||||||
BIN
app/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
app/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/routes.cpython-311.pyc
Normal file
BIN
app/__pycache__/routes.cpython-311.pyc
Normal file
Binary file not shown.
8
app/forms.py
Normal file
8
app/forms.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, PasswordField, BooleanField, SubmitField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
|
||||||
|
class RequestForm(FlaskForm):
|
||||||
|
apikey = StringField("Academy API Key", validators=[DataRequired()])
|
||||||
|
submit = SubmitField("Submit")
|
||||||
39
app/getpage.html
Normal file
39
app/getpage.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% extends 'head.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header class="header">
|
||||||
|
<div>
|
||||||
|
<h1>Hello there, <span id="userName">CUSTOMER SUCCESS MANAGER</span>.</h1>
|
||||||
|
<img src="/static/NP-Logo-Primary-FC.png" alt="Northpass Full Color Logo"></img>
|
||||||
|
<p>Today is <span id="currentDate">Monday 1, January 2000</span>.</p>
|
||||||
|
</div>
|
||||||
|
<p id="currentTime">{{ request.form.apikey }}</p>
|
||||||
|
</header>
|
||||||
|
<h4>Hello! Please select what you'd like to do.</h4>
|
||||||
|
<main id="cardContainer">
|
||||||
|
<form class="card"
|
||||||
|
action="{{ url_for('get_courses')}}"
|
||||||
|
method="post">
|
||||||
|
<a class="card"
|
||||||
|
onclick="document.forms[0].submit()"
|
||||||
|
style="cursor:pointer;">
|
||||||
|
<i class="ri-plane-line card__icon"></i>
|
||||||
|
<p class="card__name">Get Fucked</p>
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
<main id="cardContainer">
|
||||||
|
<form class="card"
|
||||||
|
action="{{ url_for('get_courses')}}"
|
||||||
|
method="post">
|
||||||
|
<a class="card"
|
||||||
|
onclick="document.forms[0].submit()"
|
||||||
|
style="cursor:pointer;">
|
||||||
|
<i class="ri-plane-line card__icon"></i>
|
||||||
|
<p class="card__name">Get Fucked</p>
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
{% endblock %}
|
||||||
72
app/routes.py
Normal file
72
app/routes.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from app import app
|
||||||
|
from flask import request, Flask, flash, render_template, session, make_response
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import pandas as pd
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/", methods=["GET", "POST"])
|
||||||
|
def ask_key():
|
||||||
|
if request.method == "POST":
|
||||||
|
session['key'] = request.form.get('apikey')
|
||||||
|
print(session['key'])
|
||||||
|
flash(session['key'])
|
||||||
|
if re.search(r'(\S+\w+)', session['key']) and len(session['key']) > 5:
|
||||||
|
print("regex worked")
|
||||||
|
print(len(session['key']))
|
||||||
|
return render_template("get.html", title="Options")
|
||||||
|
else:
|
||||||
|
error = "Hm. That doesn't seem right"
|
||||||
|
return render_template("index.html", title="Home", error=error)
|
||||||
|
else:
|
||||||
|
return render_template("index.html", title="Home")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/get_courses", methods=["GET", "POST"])
|
||||||
|
def get_courses():
|
||||||
|
array = []
|
||||||
|
df = pd.DataFrame()
|
||||||
|
if request.method == "POST":
|
||||||
|
url = "https://api.northpass.com/v2/courses"
|
||||||
|
headers = {"accept": "application/json", "X-Api-Key": session['key']}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
jsonresponse = response.json()
|
||||||
|
dt = jsonresponse["data"]
|
||||||
|
for course in dt:
|
||||||
|
df = df.append(course["attributes"], ignore_index=True)
|
||||||
|
else:
|
||||||
|
return "This isn't working. Let's go our own way."
|
||||||
|
print(df)
|
||||||
|
download = make_response(df.to_csv())
|
||||||
|
download.headers["Content-Disposition"] = "attachment; filename=export.csv"
|
||||||
|
download.headers["Content-Type"] = "text/csv"
|
||||||
|
return download
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/get_people", methods=["GET", "POST"])
|
||||||
|
def get_people():
|
||||||
|
print(session['key'])
|
||||||
|
if request.method == "POST":
|
||||||
|
url = "https://api.northpass.com/v2/people"
|
||||||
|
headers = {"accept": "application/json", "X-Api-Key": session['key']}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
jsonresponse = response.json()
|
||||||
|
dt = jsonresponse
|
||||||
|
person = dt
|
||||||
|
print(person)
|
||||||
|
return person
|
||||||
|
else:
|
||||||
|
return "what what"
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/startpage", methods=["GET", "POST"])
|
||||||
|
def startpage():
|
||||||
|
return render_template("startpage.html", title="StartTest")
|
||||||
|
|
||||||
|
|
||||||
|
app.secret_key = "@&I\x1a?\xce\x94\xbb0w\x17\xbf&Y\xa2\xc2(A\xf5\xf2\x97\xba\xeb\xfa"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ask_key()
|
||||||
BIN
app/static/NP-Logo-Primary-FC.png
Normal file
BIN
app/static/NP-Logo-Primary-FC.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 178 KiB |
BIN
app/static/NP-Logo-Primary-White.png
Normal file
BIN
app/static/NP-Logo-Primary-White.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
143
app/static/app.js
Normal file
143
app/static/app.js
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
|
||||||
|
/*****************/
|
||||||
|
/* EDITABLE INFO */
|
||||||
|
/*****************/
|
||||||
|
|
||||||
|
/* -------------------------------------------------------- */
|
||||||
|
|
||||||
|
const NAME = "Norm";
|
||||||
|
|
||||||
|
const CARDS = [
|
||||||
|
{
|
||||||
|
name: "Get all Users",
|
||||||
|
icon: "ri-admin-line",
|
||||||
|
link: "submit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get all Courses",
|
||||||
|
icon: "ri-mail-line",
|
||||||
|
link: "submit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Get all Assignments",
|
||||||
|
icon: "ri-calendar-line",
|
||||||
|
link: "submit",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
/* -------------------------------------------------------- */
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* CLOCK FUNCTION */
|
||||||
|
/******************/
|
||||||
|
|
||||||
|
const DAYS = [
|
||||||
|
"Sunday",
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
];
|
||||||
|
|
||||||
|
const MONTHS = [
|
||||||
|
"January",
|
||||||
|
"February",
|
||||||
|
"March",
|
||||||
|
"April",
|
||||||
|
"May",
|
||||||
|
"June",
|
||||||
|
"July",
|
||||||
|
"August",
|
||||||
|
"September",
|
||||||
|
"October",
|
||||||
|
"November",
|
||||||
|
"December",
|
||||||
|
];
|
||||||
|
|
||||||
|
const updateDate = () => {
|
||||||
|
// Create a new Date object and get the complete Date/Time information
|
||||||
|
const completeDate = new Date();
|
||||||
|
|
||||||
|
// Time Variables
|
||||||
|
let currentHour = formatDigit(completeDate.getHours());
|
||||||
|
let currentMinute = formatDigit(completeDate.getMinutes());
|
||||||
|
|
||||||
|
// Date Variables
|
||||||
|
let currentDay = completeDate.getDay();
|
||||||
|
let currentNumber = completeDate.getDate();
|
||||||
|
let currentMonth = completeDate.getMonth();
|
||||||
|
let currentYear = completeDate.getFullYear();
|
||||||
|
|
||||||
|
// Update the Time
|
||||||
|
currentTime.innerHTML = `${
|
||||||
|
currentHour % 12 == 0 ? "12" : currentHour % 12
|
||||||
|
}:${currentMinute} ${currentHour > 11 ? "PM" : "AM"}`;
|
||||||
|
|
||||||
|
// Update the Date
|
||||||
|
currentDate.innerHTML = `${DAYS[currentDay]} ${currentNumber}, ${MONTHS[currentMonth]} ${currentYear}`;
|
||||||
|
|
||||||
|
// Create a Loop
|
||||||
|
setTimeout(() => {
|
||||||
|
updateDate();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDigit = (digit) => {
|
||||||
|
return digit > 9 ? `${digit}` : `0${digit}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* CARDS FUNCTION */
|
||||||
|
/******************/
|
||||||
|
|
||||||
|
const printCards = () => {
|
||||||
|
for (const card of CARDS) {
|
||||||
|
let currentCard = document.createElement("a");
|
||||||
|
let currentCardText = document.createElement("p");
|
||||||
|
currentCardText.appendChild(document.createTextNode(card.name));
|
||||||
|
let currentCardIcon = document.createElement("i");
|
||||||
|
currentCardIcon.classList.add(card.icon);
|
||||||
|
|
||||||
|
// Style the Card Element
|
||||||
|
currentCard.classList.add("card");
|
||||||
|
currentCard.href = card.link;
|
||||||
|
|
||||||
|
// Handle the click event
|
||||||
|
currentCard.addEventListener("click", async (event) => {
|
||||||
|
//document.forms["apiform"].submit();
|
||||||
|
// Copy the href to the clipboard
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(card.link);
|
||||||
|
currentCard.blur();
|
||||||
|
currentCardText.innerText = "Saved to clipboard!";
|
||||||
|
setTimeout(() => {
|
||||||
|
currentCardText.innerText = card.name;
|
||||||
|
}, 1500);
|
||||||
|
} catch {
|
||||||
|
currentCardText.innerText = "Unable to copy";
|
||||||
|
setTimeout(() => {
|
||||||
|
currentCardText.innerText = card.name;
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Style the Icon
|
||||||
|
currentCardIcon.classList.add("card__icon");
|
||||||
|
|
||||||
|
// Style the Text
|
||||||
|
currentCardText.classList.add("card__name");
|
||||||
|
|
||||||
|
currentCard.append(currentCardIcon);
|
||||||
|
currentCard.append(currentCardText);
|
||||||
|
cardContainer.appendChild(currentCard);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************/
|
||||||
|
/* STARTER CODE */
|
||||||
|
/****************/
|
||||||
|
|
||||||
|
userName.innerHTML = NAME;
|
||||||
|
printCards();
|
||||||
|
updateDate();
|
||||||
167
app/static/css/styles.css
Normal file
167
app/static/css/styles.css
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
|
||||||
|
/* Custom Variables | Color Scheme */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--primary: #fff;
|
||||||
|
--text-light: #E5E9F0;
|
||||||
|
--background: #3B4252;
|
||||||
|
--background-light: #4C566A;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-bottom: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
background: linear-gradient(
|
||||||
|
145deg, #81A1C1, #88C0D0, #8FBCBB, #A3BE8C, #EBCB8B, #D08770
|
||||||
|
);
|
||||||
|
background-size: 700% 550%;
|
||||||
|
animation: gradient 7s ease-in-out infinite;
|
||||||
|
height: 125vh;
|
||||||
|
margin-top: -100px;
|
||||||
|
padding-top: 100px;
|
||||||
|
color: var(--text-light);
|
||||||
|
font-family: 'Space Grotesk', sans-serif;
|
||||||
|
padding: 2rem 4rem;
|
||||||
|
background-color: var(--background);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes gradient {
|
||||||
|
0% {
|
||||||
|
background-position: 0% 79%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 22%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0% 79%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 > span {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 50px;
|
||||||
|
width 500px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
margin: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-weight: 200;
|
||||||
|
margin-top: 80px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#currentDate {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#currentTime {
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1250px) {
|
||||||
|
h1 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#currentTime {
|
||||||
|
font-size: 3rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fullDate {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:link,
|
||||||
|
.card:visited {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
margin: 1.2rem;
|
||||||
|
padding: 4rem 8rem;
|
||||||
|
|
||||||
|
background-color: var(--background-light);
|
||||||
|
border-radius: 15px;
|
||||||
|
border: 1px solid #B48EAD;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
outline: none;
|
||||||
|
transition: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover,
|
||||||
|
.card:focus {
|
||||||
|
border-color: var(--primary);
|
||||||
|
color: var(--primary);
|
||||||
|
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:focus > .card__name {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover > .card__name {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card__icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #81A1C1;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card__name {
|
||||||
|
font-weight: 400;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
position: absolute;
|
||||||
|
bottom: -25%;
|
||||||
|
left: 50%;
|
||||||
|
transition: 0.1s;
|
||||||
|
}
|
||||||
41
app/templates/get.html
Normal file
41
app/templates/get.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{% extends 'head.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header class="header">
|
||||||
|
<div>
|
||||||
|
<h1>Hello there, <span id="userName">CUSTOMER SUCCESS MANAGER</span>.</h1>
|
||||||
|
<img src="/static/NP-Logo-Primary-FC.png" alt="Northpass Full Color Logo"></img>
|
||||||
|
<p>Today is <span id="currentDate">Monday 1, January 2000</span>.</p>
|
||||||
|
</div>
|
||||||
|
<p id="currentTime">{{ request.form.apikey }}</p>
|
||||||
|
</header>
|
||||||
|
<h4>Hello! Please select what you'd like to do.</h4>
|
||||||
|
<main id="cardContainer">
|
||||||
|
<form class="card"
|
||||||
|
action="{{ url_for('get_people')}}"
|
||||||
|
method="post">
|
||||||
|
<a class="card"
|
||||||
|
onclick="document.forms[0].submit()"
|
||||||
|
style="cursor:pointer;">
|
||||||
|
<i class="ri-car-line card__icon"></i>
|
||||||
|
<p class="card__name">Get People</p>
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<main id="cardContainer">
|
||||||
|
<form class="card"
|
||||||
|
id="get_courses"
|
||||||
|
action="{{ url_for('get_courses')}}"
|
||||||
|
method="post">
|
||||||
|
<a class="card"
|
||||||
|
onclick="document.forms['get_courses'].submit()"
|
||||||
|
style="cursor:pointer;">
|
||||||
|
<i class="ri-plane-line card__icon"></i>
|
||||||
|
<p class="card__name">Get Courses</p>
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
{% endblock %}
|
||||||
21
app/templates/get_courses.html
Normal file
21
app/templates/get_courses.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Northpass CSM Bulk Actions</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="topnav">
|
||||||
|
<div class="logo_container">
|
||||||
|
<img src="/static/NP-Logo-Primary-FC.png" alt="Northpass Full Color Logo"></img>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<h1>Hello! Please select what you'd like to do.</h1>
|
||||||
|
<form action="{{ url_for("get_courses")}}" method="post">
|
||||||
|
<label for="apikey">API Key:</label>
|
||||||
|
<input type="text" id="api" name="apikey"/>
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
20
app/templates/head.html
Normal file
20
app/templates/head.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link
|
||||||
|
href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<title>CSM Bulk Actions</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename="css/styles.css") }}" />
|
||||||
|
</head>
|
||||||
|
{% block content %} {% endblock %}
|
||||||
|
</html>
|
||||||
20
app/templates/index.html
Normal file
20
app/templates/index.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{% extends 'head.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header class="header">
|
||||||
|
<div>
|
||||||
|
<h1>Hello there, CUSTOMER SUCCESS MANAGER.</h1>
|
||||||
|
<img src="/static/NP-Logo-Primary-FC.png" alt="Northpass Full Color Logo"></img>
|
||||||
|
</header>
|
||||||
|
<h4>Hello! Please click below to enter your key.</h4>
|
||||||
|
{% if error %}
|
||||||
|
<p class=error><strong>Error! </strong>{{ error }}
|
||||||
|
{% endif %}
|
||||||
|
<form action="{{ url_for("ask_key")}}" method="post">
|
||||||
|
<input type="text" name="apikey">
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user