mirror of
https://github.com/aaronleetw/Attendance.git
synced 2024-11-14 19:11:39 -08:00
first commit
This commit is contained in:
commit
47d685568e
15 changed files with 562 additions and 0 deletions
35
911_namelist.csv
Normal file
35
911_namelist.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,name,eng_name
|
||||
1,朱昱翧,Themis
|
||||
2,余欣璇,Zoe
|
||||
3,吳丞育,Audrey
|
||||
4,吳欣芃,Lisa
|
||||
5,吳苡瑄,Rachel
|
||||
6,王怡捷,Audrey
|
||||
7,林子琳,Emma
|
||||
8,林思佑,Una
|
||||
9,林珈年,Jessica
|
||||
10,姜心唯,Misha
|
||||
11,張庭暄,Chang
|
||||
12,許詠淳,Catherine
|
||||
13,陳宣彤,idk
|
||||
14,羅子珊,Shannon
|
||||
15,蘇宜柔,Chloe
|
||||
16,王邦熹,Wallace
|
||||
17,李秉謙,Alan
|
||||
18,劉青懷,idk
|
||||
19,林稟翔,Wilbert
|
||||
20,柯喬勳,Joshua
|
||||
21,馮顗中,idk
|
||||
22,張睿恩,Brian
|
||||
23,姜廉竣,idk
|
||||
24,陳允昊,Jeremy
|
||||
25,陳宣豪,Demetris
|
||||
26,陳宥嘉,Joseph
|
||||
27,陳麟泳,Aaron
|
||||
28,賀凱強,Jonathan
|
||||
29,楊上霆,Chase
|
||||
30,楊承武,Ben
|
||||
31,廖建瑋,Daniel
|
||||
32,潘逸,James
|
||||
33,朱禹安,Iforgot
|
||||
34,徐敏萱,idk
|
|
35
911_simple_gplist.csv
Normal file
35
911_simple_gplist.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,3-IG
|
||||
1,1103-01
|
||||
2,1103-01
|
||||
3,1103-02
|
||||
4,1103-01
|
||||
5,1103-01
|
||||
6,1103-02
|
||||
7,1103-01
|
||||
8,1103-01
|
||||
9,1103-01
|
||||
10,1103-01
|
||||
11,1103-01
|
||||
12,1103-01
|
||||
13,1103-02
|
||||
14,1103-01
|
||||
15,1103-02
|
||||
16,1103-01
|
||||
17,1103-02
|
||||
18,1103-02
|
||||
19,1103-01
|
||||
20,1103-02
|
||||
21,1103-01
|
||||
22,1103-02
|
||||
23,1103-01
|
||||
24,1103-02
|
||||
25,1103-02
|
||||
26,1103-02
|
||||
27,1103-01
|
||||
28,1103-02
|
||||
29,1103-01
|
||||
30,1103-01
|
||||
31,1103-01
|
||||
32,1103-01
|
||||
33,1103-02
|
||||
34,1103-01
|
|
35
912_beforeformat.csv
Normal file
35
912_beforeformat.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,name,eng_name,3-IG
|
||||
1,王子芯,Heidi,1103-01
|
||||
2,朱宸儀,Megan,1103-01
|
||||
3,牟奇薇,Summer,1103-02
|
||||
4,吳偲梵,Sophia,1103-01
|
||||
5,林書誼,Charlotte,1103-01
|
||||
6,林葦亭,Chelsea,1103-02
|
||||
7,凌孟妍,Iris,1103-01
|
||||
8,翁翊婷,Evelyn,1103-01
|
||||
9,郭倚熏,Patty,1103-01
|
||||
10,陳宣穎,Renee,1103-01
|
||||
11,曾若霏,Danielle,1103-01
|
||||
12,湯家綺,Joanna,1103-01
|
||||
13,黃以甯,Kate,1103-02
|
||||
14,黃玄,Cheryl,1103-01
|
||||
15,劉煒琪,Winona,1103-02
|
||||
16,潘俞希,Alina,1103-01
|
||||
17,鄭軒,Jasper,1103-02
|
||||
18,吳彥縢,Austin,1103-02
|
||||
19,吳昶佑,Eric,1103-01
|
||||
20,李翊愷,Aaron Lee,1103-02
|
||||
21,李翊誠,Alex,1103-01
|
||||
22,曹庭睿,Alvin,1103-02
|
||||
23,莊家睿,Gary,1103-01
|
||||
24,張馨予,Cindy,1103-02
|
||||
25,常有慈,Cindy,1103-02
|
||||
26,陳柏元,Michael,1103-02
|
||||
27,陳雋喆,Derek,1103-01
|
||||
28,曾柏皓,Cory,1103-02
|
||||
29,黃獻主,Arthur,1103-01
|
||||
30,盧秉漢,Hiro,1103-01
|
||||
31,李文,Tom,1103-01
|
||||
32,謝承霖,Walter,1103-01
|
||||
33,關義,Aaron Kuan,1103-02
|
||||
34,謝佾儒,Yi-Ju,1103-01
|
|
35
912_gplist.csv
Normal file
35
912_gplist.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,3-IG,2-TEST
|
||||
1,1103-01,1102-5
|
||||
2,1103-01,1102-5
|
||||
3,1103-02,1102-5
|
||||
4,1103-01,1102-5
|
||||
5,1103-01,1102-5
|
||||
6,1103-02,1102-5
|
||||
7,1103-01,1102-5
|
||||
8,1103-01,1102-5
|
||||
9,1103-01,1102-5
|
||||
10,1103-01,1102-5
|
||||
11,1103-01,1102-5
|
||||
12,1103-01,1102-5
|
||||
13,1103-02,1102-5
|
||||
14,1103-01,1102-5
|
||||
15,1103-02,1102-5
|
||||
16,1103-01,1102-5
|
||||
17,1103-02,1102-5
|
||||
18,1103-02,1102-5
|
||||
19,1103-01,1102-5
|
||||
20,1103-02,1102-5
|
||||
21,1103-01,1102-9
|
||||
22,1103-02,1102-9
|
||||
23,1103-01,1102-9
|
||||
24,1103-02,1102-9
|
||||
25,1103-02,1102-9
|
||||
26,1103-02,1102-9
|
||||
27,1103-01,1102-9
|
||||
28,1103-02,1102-9
|
||||
29,1103-01,1102-9
|
||||
30,1103-01,1102-9
|
||||
31,1103-01,1102-9
|
||||
32,1103-01,1102-9
|
||||
33,1103-02,1102-9
|
||||
34,1103-01,1102-9
|
|
35
912_namelist.csv
Normal file
35
912_namelist.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,name,eng_name
|
||||
1,王子芯,Heidi
|
||||
2,朱宸儀,Megan
|
||||
3,牟奇薇,Summer
|
||||
4,吳偲梵,Sophia
|
||||
5,林書誼,Charlotte
|
||||
6,林葦亭,Chelsea
|
||||
7,凌孟妍,Iris
|
||||
8,翁翊婷,Evelyn
|
||||
9,郭倚熏,Patty
|
||||
10,陳宣穎,Renee
|
||||
11,曾若霏,Danielle
|
||||
12,湯家綺,Joanna
|
||||
13,黃以甯,Kate
|
||||
14,黃玄,Cheryl
|
||||
15,劉煒琪,Winona
|
||||
16,潘俞希,Alina
|
||||
17,鄭軒,Jasper
|
||||
18,吳彥縢,Austin
|
||||
19,吳昶佑,Eric
|
||||
20,李翊愷,Aaron Lee
|
||||
21,李翊誠,Alex
|
||||
22,曹庭睿,Alvin
|
||||
23,莊家睿,Gary
|
||||
24,張馨予,Cindy
|
||||
25,常有慈,Cindy
|
||||
26,陳柏元,Michael
|
||||
27,陳雋喆,Derek
|
||||
28,曾柏皓,Cory
|
||||
29,黃獻主,Arthur
|
||||
30,盧秉漢,Hiro
|
||||
31,李文,Tom
|
||||
32,謝承霖,Walter
|
||||
33,關義,Aaron Kuan
|
||||
34,謝佾儒,Yi-Ju
|
|
35
912_simple_gplist.csv
Normal file
35
912_simple_gplist.csv
Normal file
|
@ -0,0 +1,35 @@
|
|||
number,3-IG
|
||||
1,1103-01
|
||||
2,1103-01
|
||||
3,1103-02
|
||||
4,1103-01
|
||||
5,1103-01
|
||||
6,1103-02
|
||||
7,1103-01
|
||||
8,1103-01
|
||||
9,1103-01
|
||||
10,1103-01
|
||||
11,1103-01
|
||||
12,1103-01
|
||||
13,1103-02
|
||||
14,1103-01
|
||||
15,1103-02
|
||||
16,1103-01
|
||||
17,1103-02
|
||||
18,1103-02
|
||||
19,1103-01
|
||||
20,1103-02
|
||||
21,1103-01
|
||||
22,1103-02
|
||||
23,1103-01
|
||||
24,1103-02
|
||||
25,1103-02
|
||||
26,1103-02
|
||||
27,1103-01
|
||||
28,1103-02
|
||||
29,1103-01
|
||||
30,1103-01
|
||||
31,1103-01
|
||||
32,1103-01
|
||||
33,1103-02
|
||||
34,1103-01
|
|
206
app.py
Normal file
206
app.py
Normal file
|
@ -0,0 +1,206 @@
|
|||
from flask import *
|
||||
import pyrebase
|
||||
from datetime import datetime
|
||||
import pytz
|
||||
from sendgrid import SendGridAPIClient
|
||||
from sendgrid.helpers.mail import Mail
|
||||
import csv
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from pprint import pprint
|
||||
load_dotenv()
|
||||
app = Flask(__name__)
|
||||
|
||||
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
|
||||
config = {
|
||||
"apiKey": os.environ.get('apiKey'),
|
||||
"authDomain": os.environ.get('authDomain'),
|
||||
"databaseURL": os.environ.get('databaseURL'),
|
||||
"storageBucket": os.environ.get('storageBucket'),
|
||||
"serviceAccount": os.environ.get('serviceAccount'),
|
||||
"messagingSenderId": os.environ.get('messagingSenderId'),
|
||||
"appId": os.environ.get('appId'),
|
||||
"measurementId": os.environ.get('measurementId'),
|
||||
}
|
||||
firebase = pyrebase.initialize_app(config)
|
||||
db = firebase.database()
|
||||
auth = firebase.auth()
|
||||
tz = pytz.timezone('Asia/Taipei')
|
||||
|
||||
|
||||
def check_login_status():
|
||||
return ('is_logged_in' not in session or
|
||||
session['is_logged_in'] == False or
|
||||
(datetime.now(tz) - session['loginTime']).total_seconds() > 3600)
|
||||
|
||||
|
||||
@ app.route('/', methods=['GET', 'POST'])
|
||||
def index():
|
||||
if request.method == 'GET':
|
||||
if check_login_status():
|
||||
return render_template('login.html', error=False)
|
||||
return redirect('/manage')
|
||||
elif request.method == 'POST':
|
||||
if check_login_status():
|
||||
try:
|
||||
user = auth.sign_in_with_email_and_password(
|
||||
request.form['username'] + "@group-attendence.fhjh.tp.edu.tw", request.form['password'])
|
||||
session['is_logged_in'] = True
|
||||
session['email'] = user['email']
|
||||
session['uid'] = user['localId']
|
||||
session['token'] = user['idToken']
|
||||
session['refreshToken'] = user['refreshToken']
|
||||
session['loginTime'] = datetime.now(tz)
|
||||
return redirect('/manage')
|
||||
except Exception as e:
|
||||
return render_template('login.html', error=True)
|
||||
else:
|
||||
return redirect('/manage')
|
||||
|
||||
|
||||
@app.route('/manage', methods=['GET'])
|
||||
def manage():
|
||||
pl = db.child("Users").child(
|
||||
session['uid']).child("permission").get().val()
|
||||
print(pl)
|
||||
s = str(pl)
|
||||
if pl == 'admin':
|
||||
return s
|
||||
elif pl == 'group':
|
||||
classes = db.child("Users").child(
|
||||
session['uid']).child("class").get().val()
|
||||
cclass = {}
|
||||
for i in classes:
|
||||
cclass = {
|
||||
"name": db.child("Classes").child(i).child(
|
||||
"Class").child(classes[i]).child("name").get().val(),
|
||||
"category": i,
|
||||
"class_id": classes[i]
|
||||
}
|
||||
print("got class")
|
||||
students = db.child("Classes").child(cclass['category']).child(
|
||||
"Class").child(cclass['class_id']).child("Students").get().val()
|
||||
all_stud_list = {}
|
||||
for homeroom in students:
|
||||
print(homeroom)
|
||||
all_stud_list[homeroom] = {}
|
||||
if type(students[homeroom]) == list:
|
||||
i = 0
|
||||
for student in students[homeroom]:
|
||||
if student == 0:
|
||||
# print(i)
|
||||
# print(db.child("Homerooms").child(
|
||||
# homeroom).child(i).child("name").get().val())
|
||||
all_stud_list[homeroom][i] = {
|
||||
"name": db.child("Homerooms").child(homeroom).child(i).child("name").get().val(),
|
||||
"eng_name": db.child("Homerooms").child(homeroom).child(i).child("eng_name").get().val(),
|
||||
}
|
||||
i += 1
|
||||
else:
|
||||
for student in students[homeroom]:
|
||||
all_stud_list[homeroom][student] = {
|
||||
"name": db.child("Homerooms").child(homeroom).child(student).child("name").get().val(),
|
||||
"eng_name": db.child("Homerooms").child(homeroom).child(student).child("eng_name").get().val(),
|
||||
}
|
||||
|
||||
print("got students")
|
||||
# for homeroom in all_stud_list:
|
||||
# for student in all_stud_list[homeroom]:
|
||||
# print("homeroom: ", homeroom)
|
||||
# print("student: ", student)
|
||||
# print("all_stud_list['homeroom']['student']['name']: ",
|
||||
# all_stud_list['homeroom']['student']['name'])
|
||||
# print("all_stud_list['homeroom']['student']['eng_name']: ",
|
||||
# all_stud_list['homeroom']['student']['eng_name'])
|
||||
# get dates
|
||||
dates = db.child("Classes").child(
|
||||
cclass['category']).child("Dates").get().val()
|
||||
for i in dates:
|
||||
dates[i].pop('placeholder')
|
||||
if i >= datetime.now(tz).strftime("%Y-%m-%d"):
|
||||
currDate = i
|
||||
break
|
||||
print("got dates")
|
||||
return render_template('group_teach.html', cclass=cclass, all_stud_list=all_stud_list, dates=dates, currDate=currDate)
|
||||
elif pl == 'homeroom':
|
||||
homeroom = db.child("Users").child(
|
||||
session['uid']).child("homeroom").get().val()
|
||||
s += " " + homeroom # 912
|
||||
return s
|
||||
else:
|
||||
return "no permission"
|
||||
|
||||
|
||||
@ app.route('/upload/homeroom', methods=['GET', 'POST'])
|
||||
def upload_homeroom():
|
||||
if request.method == 'GET':
|
||||
return render_template('uploadcsv.html', title="Homeroom List", url="/upload/homeroom")
|
||||
elif request.method == 'POST':
|
||||
try:
|
||||
# get csv
|
||||
classc = request.form['classcode']
|
||||
csv_file = request.files['csv']
|
||||
filepath = os.path.join('./temp', csv_file.filename)
|
||||
csv_file.save(filepath)
|
||||
with open(filepath) as file:
|
||||
csv_dict = csv.DictReader(file)
|
||||
for row in csv_dict:
|
||||
db.child("Homerooms").child(
|
||||
classc).child(row['number']).set(row)
|
||||
# row['class'] row['number'] row['name'] row['eng_name']
|
||||
os.remove(filepath)
|
||||
except Exception as e:
|
||||
os.remove(filepath)
|
||||
return "Error. Please try again\n("+str(e)+")"
|
||||
return "Successfully uploaded " + classc
|
||||
|
||||
|
||||
@ app.route('/upload/stud_in_group', methods=['GET', 'POST'])
|
||||
def upload_stud_in_group():
|
||||
if request.method == 'GET':
|
||||
return render_template('uploadcsv.html', title="Student in Group List", url="/upload/stud_in_group")
|
||||
elif request.method == 'POST':
|
||||
try:
|
||||
classc = request.form['classcode']
|
||||
csv_file = request.files['csv']
|
||||
filepath = os.path.join('./temp', csv_file.filename)
|
||||
csv_file.save(filepath)
|
||||
with open(filepath) as file:
|
||||
csv_dict = csv.DictReader(file)
|
||||
headers = csv_dict.fieldnames
|
||||
headers = headers[1:]
|
||||
for row in csv_dict:
|
||||
for h in headers:
|
||||
db.child("Homerooms").child(classc).child(
|
||||
row['number']).child("Classes").child(h).set(row[h])
|
||||
db.child("Classes").child(h).child("Class").child(row[h]).child(
|
||||
"Students").child(classc).update({str(row['number']): 0})
|
||||
|
||||
os.remove(filepath)
|
||||
except Exception as e:
|
||||
os.remove(filepath)
|
||||
return "Error. Please try again\n("+str(e)+")"
|
||||
return "Successfully uploaded " + classc
|
||||
|
||||
|
||||
# @ app.route('/upload/rm_all_data_of_class', methods=['GET', "POST"])
|
||||
# def rm_all_data_of_class():
|
||||
# if request.method == 'GET':
|
||||
# return render_template('uploadcsv.html', title="Remove all data of class", url="/upload/rm_all_data_of_class")
|
||||
# elif request.method == 'POST':
|
||||
# try:
|
||||
# classc = request.form['classcode']
|
||||
# db.child("Homerooms").child(classc).remove()
|
||||
# except Exception as e:
|
||||
# return "Error. Please try again\n("+str(e)+")"
|
||||
# return "Successfully removed " + classc
|
||||
|
||||
|
||||
@app.route('/logout', methods=['GET'])
|
||||
def logout():
|
||||
session.clear()
|
||||
return redirect('/')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
3
static/allpages.css
Normal file
3
static/allpages.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
div.col .row .col {
|
||||
border: 1px solid black;
|
||||
}
|
BIN
static/loading.gif
Normal file
BIN
static/loading.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
8
static/login.css
Normal file
8
static/login.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
div.container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
0
templates/admin.html
Normal file
0
templates/admin.html
Normal file
42
templates/group_teach.html
Normal file
42
templates/group_teach.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Group_Teach_View</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="/static/allpages.css">
|
||||
<link rel="stylesheet" href="/static/login.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Group_Teach_View</h1>
|
||||
<h2>{{cclass['category']}}: {{cclass['class_id']}}: {{cclass['name']}}</h2>
|
||||
<div class="col">
|
||||
<div class="row title">
|
||||
<div class="col">Class Code</div>
|
||||
<div class="col">Number</div>
|
||||
<div class="col">Name</div>
|
||||
<div class="col">Eng Name</div>
|
||||
<div class="col">Attendance</div>
|
||||
</div>
|
||||
{% if data != None %}
|
||||
{% for homeroom in all_stud_list %}
|
||||
{% for student in all_stud_list[homeroom] %}
|
||||
<div class="row">
|
||||
<div class="col">{{homeroom}}</div>
|
||||
<div class="col">{{ student }}</div>
|
||||
<div class="col">{{ all_stud_list[homeroom][student]['name'] }}</div>
|
||||
<div class="col">{{ all_stud_list[homeroom][student]['eng_name'] }}</div>
|
||||
<div class="col"><input type="checkbox" id="{{homeroom}}^{{student}}"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
0
templates/homeroom.html
Normal file
0
templates/homeroom.html
Normal file
53
templates/login.html
Normal file
53
templates/login.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="/static/allpages.css">
|
||||
<link rel="stylesheet" href="/static/login.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- login form center -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4 offset-md-4">
|
||||
<h1 class="text-center">Login</h1>
|
||||
<form action="/" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" name="username" id="username" placeholder="Username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" name="password" id="password"
|
||||
placeholder="Password">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block" onclick="loadingAnimation()">Login</button>
|
||||
</form>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
Incorrect username or password
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt=""
|
||||
style="height:100%;" />
|
||||
</div>
|
||||
<!-- end login form center -->
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
|
||||
<script>
|
||||
function loadingAnimation() {
|
||||
$('.container').hide();
|
||||
$('#loading').show();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
40
templates/uploadcsv.html
Normal file
40
templates/uploadcsv.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="/static/allpages.css">
|
||||
<link rel="stylesheet" href="/static/login.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- csv form center -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4 offset-md-4">
|
||||
<h1 class="text-center">Upload {{title}}</h1>
|
||||
<!-- upload csv -->
|
||||
<form action="{{url}}" method="post" enctype="multipart/form-data">
|
||||
<!-- input class code -->
|
||||
<div class="form-group">
|
||||
<label for="classcode">Class Code</label>
|
||||
<input type="text" class="form-control" id="classcode" name="classcode"
|
||||
placeholder="Enter Class Code">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="csv">{{title}}</label>
|
||||
<input type="file" class="form-control-file" id="csv" name="csv">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end csv form center -->
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue