Prototype Finish

This commit is contained in:
Aaron Lee 2021-09-12 17:39:09 +08:00
parent a47d69a954
commit 6ee0ce15d5
14 changed files with 841 additions and 484 deletions

View file

@ -1,35 +0,0 @@
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
1 number name eng_name
2 1 朱昱翧 Themis
3 2 余欣璇 Zoe
4 3 吳丞育 Audrey
5 4 吳欣芃 Lisa
6 5 吳苡瑄 Rachel
7 6 王怡捷 Audrey
8 7 林子琳 Emma
9 8 林思佑 Una
10 9 林珈年 Jessica
11 10 姜心唯 Misha
12 11 張庭暄 Chang
13 12 許詠淳 Catherine
14 13 陳宣彤 idk
15 14 羅子珊 Shannon
16 15 蘇宜柔 Chloe
17 16 王邦熹 Wallace
18 17 李秉謙 Alan
19 18 劉青懷 idk
20 19 林稟翔 Wilbert
21 20 柯喬勳 Joshua
22 21 馮顗中 idk
23 22 張睿恩 Brian
24 23 姜廉竣 idk
25 24 陳允昊 Jeremy
26 25 陳宣豪 Demetris
27 26 陳宥嘉 Joseph
28 27 陳麟泳 Aaron
29 28 賀凱強 Jonathan
30 29 楊上霆 Chase
31 30 楊承武 Ben
32 31 廖建瑋 Daniel
33 32 潘逸 James
34 33 朱禹安 Iforgot
35 34 徐敏萱 idk

View file

@ -1,35 +0,0 @@
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
1 number 3-IG
2 1 1103-01
3 2 1103-01
4 3 1103-02
5 4 1103-01
6 5 1103-01
7 6 1103-02
8 7 1103-01
9 8 1103-01
10 9 1103-01
11 10 1103-01
12 11 1103-01
13 12 1103-01
14 13 1103-02
15 14 1103-01
16 15 1103-02
17 16 1103-01
18 17 1103-02
19 18 1103-02
20 19 1103-01
21 20 1103-02
22 21 1103-01
23 22 1103-02
24 23 1103-01
25 24 1103-02
26 25 1103-02
27 26 1103-02
28 27 1103-01
29 28 1103-02
30 29 1103-01
31 30 1103-01
32 31 1103-01
33 32 1103-01
34 33 1103-02
35 34 1103-01

View file

@ -1,35 +0,0 @@
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
1 number name eng_name 3-IG
2 1 王子芯 Heidi 1103-01
3 2 朱宸儀 Megan 1103-01
4 3 牟奇薇 Summer 1103-02
5 4 吳偲梵 Sophia 1103-01
6 5 林書誼 Charlotte 1103-01
7 6 林葦亭 Chelsea 1103-02
8 7 凌孟妍 Iris 1103-01
9 8 翁翊婷 Evelyn 1103-01
10 9 郭倚熏 Patty 1103-01
11 10 陳宣穎 Renee 1103-01
12 11 曾若霏 Danielle 1103-01
13 12 湯家綺 Joanna 1103-01
14 13 黃以甯 Kate 1103-02
15 14 黃玄 Cheryl 1103-01
16 15 劉煒琪 Winona 1103-02
17 16 潘俞希 Alina 1103-01
18 17 鄭軒 Jasper 1103-02
19 18 吳彥縢 Austin 1103-02
20 19 吳昶佑 Eric 1103-01
21 20 李翊愷 Aaron Lee 1103-02
22 21 李翊誠 Alex 1103-01
23 22 曹庭睿 Alvin 1103-02
24 23 莊家睿 Gary 1103-01
25 24 張馨予 Cindy 1103-02
26 25 常有慈 Cindy 1103-02
27 26 陳柏元 Michael 1103-02
28 27 陳雋喆 Derek 1103-01
29 28 曾柏皓 Cory 1103-02
30 29 黃獻主 Arthur 1103-01
31 30 盧秉漢 Hiro 1103-01
32 31 李文 Tom 1103-01
33 32 謝承霖 Walter 1103-01
34 33 關義 Aaron Kuan 1103-02
35 34 謝佾儒 Yi-Ju 1103-01

View file

@ -1,35 +0,0 @@
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
1 number 3-IG 2-TEST
2 1 1103-01 1102-5
3 2 1103-01 1102-5
4 3 1103-02 1102-5
5 4 1103-01 1102-5
6 5 1103-01 1102-5
7 6 1103-02 1102-5
8 7 1103-01 1102-5
9 8 1103-01 1102-5
10 9 1103-01 1102-5
11 10 1103-01 1102-5
12 11 1103-01 1102-5
13 12 1103-01 1102-5
14 13 1103-02 1102-5
15 14 1103-01 1102-5
16 15 1103-02 1102-5
17 16 1103-01 1102-5
18 17 1103-02 1102-5
19 18 1103-02 1102-5
20 19 1103-01 1102-5
21 20 1103-02 1102-5
22 21 1103-01 1102-9
23 22 1103-02 1102-9
24 23 1103-01 1102-9
25 24 1103-02 1102-9
26 25 1103-02 1102-9
27 26 1103-02 1102-9
28 27 1103-01 1102-9
29 28 1103-02 1102-9
30 29 1103-01 1102-9
31 30 1103-01 1102-9
32 31 1103-01 1102-9
33 32 1103-01 1102-9
34 33 1103-02 1102-9
35 34 1103-01 1102-9

View file

@ -1,35 +0,0 @@
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
1 number name eng_name
2 1 王子芯 Heidi
3 2 朱宸儀 Megan
4 3 牟奇薇 Summer
5 4 吳偲梵 Sophia
6 5 林書誼 Charlotte
7 6 林葦亭 Chelsea
8 7 凌孟妍 Iris
9 8 翁翊婷 Evelyn
10 9 郭倚熏 Patty
11 10 陳宣穎 Renee
12 11 曾若霏 Danielle
13 12 湯家綺 Joanna
14 13 黃以甯 Kate
15 14 黃玄 Cheryl
16 15 劉煒琪 Winona
17 16 潘俞希 Alina
18 17 鄭軒 Jasper
19 18 吳彥縢 Austin
20 19 吳昶佑 Eric
21 20 李翊愷 Aaron Lee
22 21 李翊誠 Alex
23 22 曹庭睿 Alvin
24 23 莊家睿 Gary
25 24 張馨予 Cindy
26 25 常有慈 Cindy
27 26 陳柏元 Michael
28 27 陳雋喆 Derek
29 28 曾柏皓 Cory
30 29 黃獻主 Arthur
31 30 盧秉漢 Hiro
32 31 李文 Tom
33 32 謝承霖 Walter
34 33 關義 Aaron Kuan
35 34 謝佾儒 Yi-Ju

View file

@ -1,35 +0,0 @@
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
1 number 3-IG
2 1 1103-01
3 2 1103-01
4 3 1103-02
5 4 1103-01
6 5 1103-01
7 6 1103-02
8 7 1103-01
9 8 1103-01
10 9 1103-01
11 10 1103-01
12 11 1103-01
13 12 1103-01
14 13 1103-02
15 14 1103-01
16 15 1103-02
17 16 1103-01
18 17 1103-02
19 18 1103-02
20 19 1103-01
21 20 1103-02
22 21 1103-01
23 22 1103-02
24 23 1103-01
25 24 1103-02
26 25 1103-02
27 26 1103-02
28 27 1103-01
29 28 1103-02
30 29 1103-01
31 30 1103-01
32 31 1103-01
33 32 1103-01
34 33 1103-02
35 34 1103-01

460
app.py
View file

@ -1,12 +1,12 @@
from flask import * from flask import *
import pyrebase import pyrebase
from datetime import datetime from datetime import datetime
import time
import pytz import pytz
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
import csv import csv
import os import os
import pandas as pd
import base64
from random import randint
from dotenv import load_dotenv from dotenv import load_dotenv
from pprint import pprint from pprint import pprint
load_dotenv() load_dotenv()
@ -26,6 +26,7 @@ config = {
firebase = pyrebase.initialize_app(config) firebase = pyrebase.initialize_app(config)
db = firebase.database() db = firebase.database()
auth = firebase.auth() auth = firebase.auth()
storage = firebase.storage()
tz = pytz.timezone('Asia/Taipei') tz = pytz.timezone('Asia/Taipei')
@ -42,149 +43,138 @@ def manageProcess(fCommand, fData):
# end bug fix # end bug fix
pl = db.child("Users").child( pl = db.child("Users").child(
session['uid']).child("permission").get().val() session['uid']).child("permission").get().val()
print(pl)
print(db.child("Users").child(
'DRZqqSSpg3OkPSCuWkv417dv0vh1').child("permission").get().val())
print(fCommand, fData, session['uid'], pl)
if pl == 'admin': if pl == 'admin':
return pl homerooms = db.child("Homerooms").get().val()
currRoom = []
if fCommand == "admin":
currRoom = fData[0].split("^")
else:
for i in homerooms:
currRoom.append(i)
for j in homerooms[i]:
currRoom.append(j)
break
break
homeroomData = homerooms[currRoom[0]][currRoom[1]]
absData = homeroomData["Absent"]
homeroomData.pop('Absent')
homeroomData.pop('placeholder')
currDate = ""
if fCommand != "":
currDate = fData[1]
else:
for i in absData:
currDate = i
if i >= datetime.now(tz).strftime("%Y-%m-%d"):
break
return render_template('admin.html', homerooms=homerooms, absData=absData, homeroomCode=currRoom, homeroomData=homeroomData, currDate=currDate, periods=['m', '1', '2', '3', '4', 'n', '5', '6', '7', '8', '9'])
elif pl == 'group': elif pl == 'group':
classes = db.child("Users").child( classes = db.child("Users").child(
session['uid']).child("class").get().val() session['uid']).child("class").get().val()
cclass = {} cclass = {}
cateData = {}
for i in classes: for i in classes:
cateData = db.child("Classes").child(
"GP_Class").child(i).get().val()
cclass = { cclass = {
"name": db.child("Classes").child(i).child( "name": cateData['Class'][classes[i]]['name'],
"Class").child(classes[i]).child("name").get().val(), "teacher": cateData['Class'][classes[i]]['teacher'],
"classroom": cateData['Class'][classes[i]]['classroom'],
"category": i, "category": i,
"class_id": classes[i] "class_id": classes[i]
} }
print("got class") print("got class")
students = db.child("Classes").child(cclass['category']).child( homerooms = cateData['Homerooms']
"Class").child(cclass['class_id']).child("Students").get().val() currDate = ""
print(students['9']['11']) absData = {}
all_stud_list = {} for h in homerooms:
for grade in students: h = h.split('^')
print(grade) print(h)
all_stud_list[grade] = {} hrData = db.child("Homerooms").child(h[0]).child(h[1]).get().val()
print(type(students[grade])) tmpAbsData = hrData['Absent']
for homeroom in students[grade]: hrData.pop('Absent')
print(homeroom) hrData.pop('placeholder')
roomData = db.child("Homerooms").child( periods = []
grade).child(homeroom).get().val() dow = ""
all_stud_list[grade][homeroom] = {} if currDate == "":
if type(students[grade][homeroom]) == list: if fCommand == 'date':
i = 0 currDate = fData
for student in students[grade][homeroom]: for j in tmpAbsData[currDate]:
if student == 0: if j == "dow":
all_stud_list[grade][homeroom][i] = { dow = tmpAbsData[currDate][j]
"name": roomData[str(i)]["name"], continue
"eng_name": roomData[str(i)]["eng_name"] elif j == "confirm":
} continue
i += 1 if (tmpAbsData[currDate][j]['name'] == 'GP' and
else: tmpAbsData[currDate][j]['teacher'] == cclass['category']):
for student in students[grade][homeroom]: periods.append(j)
print(student)
all_stud_list[grade][homeroom][student] = {
"name": roomData[student]["name"],
"eng_name": roomData[student]["eng_name"]
}
print("got students")
dates = db.child("Classes").child(
cclass['category']).child("Dates").get().val()
status = 0
attendance = {}
if fCommand == 'date': else:
currDate = fData for i in tmpAbsData:
if cclass['class_id'] in dates[currDate]: currDate = i
status = 1 if i >= datetime.now(tz).strftime("%Y-%m-%d"):
for grade in dates[currDate]['Absent']: tmp = False
attendance[grade] = {} for j in tmpAbsData[i]:
for homeroom in dates[currDate]['Absent'][grade]: if j == "dow":
attendance[grade][homeroom] = {} dow = tmpAbsData[i][j]
for student in dates[currDate]['Absent'][grade][homeroom]: continue
attendance[grade][homeroom][student] = 0 elif j == "confirm":
else: continue
for i in dates: if (tmpAbsData[i][j]['name'] == 'GP' and
if i >= datetime.now(tz).strftime("%Y-%m-%d"): tmpAbsData[i][j]['teacher'] == cclass['category']):
currDate = i periods.append(j)
if cclass['class_id'] in dates[currDate]: tmp = True
status = 1 if tmp == True:
for grade in dates[currDate]['Absent']: break
attendance[grade] = {} else:
for homeroom in dates[currDate]['Absent'][grade]: for j in tmpAbsData[currDate]:
attendance[grade][homeroom] = {} if j == "dow":
for student in dates[currDate]['Absent'][grade][homeroom]: dow = tmpAbsData[currDate][j]
attendance[grade][homeroom][student] = 0 continue
break elif j == "confirm":
dates[i].pop('placeholder') continue
print("got dates") if (tmpAbsData[currDate][j]['name'] == 'GP' and
return render_template('group_teach.html', cclass=cclass, all_stud_list=all_stud_list, dates=dates, currDate=currDate, status=status, attendance=attendance) tmpAbsData[currDate][j]['teacher'] == cclass['category']):
periods.append(j)
for p in periods:
if not p in absData:
absData[p] = {}
for p in periods:
if not h[0] in absData[p]:
absData[p][h[0]] = {}
absData[p][h[0]][h[1]] = {}
for num in hrData:
if (cclass['category'] in hrData[num]['GP_Class'] and
hrData[num]['GP_Class'][cclass['category']] == cclass['class_id']):
for p in periods:
absData[p][h[0]][h[1]][num] = {
"name": hrData[num]['name'],
"eng_name": hrData[num]['eng_name'],
"alr_fill": ('signature' in tmpAbsData[currDate][p] and
cclass['class_id'] in tmpAbsData[currDate][p]['signature']),
"absent": num in tmpAbsData[currDate][p]
}
print(absData)
return render_template('group_teach.html', cclass=cclass, absData=absData, dow=dow, currDate=currDate, tmpAbsData=tmpAbsData)
elif pl == 'homeroom': elif pl == 'homeroom':
homeroom = db.child("Users").child( homeroom = db.child("Users").child(
session['uid']).child("homeroom").get().val() session['uid']).child("homeroom").get().val().split('^')
homeroomCode = homeroom.split('^') homeroomData = db.child("Homerooms").child(homeroom[0]).child(
homeroom = db.child("Homerooms").child( homeroom[1]).get().val()
homeroomCode[0]).child(homeroomCode[1]).get().val() absData = homeroomData["Absent"]
categories = homeroom['Categories'].split('^') homeroomData.pop('Absent')
currCategory = categories[0] homeroomData.pop('placeholder')
currDate = "" currDate = ""
gpClasses = db.child("Classes").child(currCategory).get().val()
dates = gpClasses['Dates']
confirmedClasses = []
status = 0
if fCommand == 'date': if fCommand == 'date':
currDate = fData currDate = fData
tmp1 = 0
tmp2 = 0
for k in gpClasses['Class']:
if k in dates[currDate]:
confirmedClasses.append(k)
tmp2 += 1
tmp1 += 1
if tmp1 == tmp2:
status = 1
else: else:
for i in dates: for i in absData:
currDate = i
if i >= datetime.now(tz).strftime("%Y-%m-%d"): if i >= datetime.now(tz).strftime("%Y-%m-%d"):
currDate = i
tmp1 = 0
tmp2 = 0
for k in gpClasses['Class']:
if k in dates[currDate]:
confirmedClasses.append(k)
tmp2 += 1
tmp1 += 1
if tmp1 == tmp2:
status = 1
break break
print("got dates") return render_template('homeroom.html', absData=absData, homeroomCode=homeroom, homeroomData=homeroomData, currDate=currDate, periods=['m', '1', '2', '3', '4', 'n', '5', '6', '7', '8', '9'])
db.child("Classes").child(currCategory).child("Dates")
homeroom.pop('Categories')
all_stud_list = {}
for i in homeroom:
all_stud_list[i] = {}
all_stud_list[i]['name'] = homeroom[i]['name']
all_stud_list[i]['eng_name'] = homeroom[i]['eng_name']
all_stud_list[i]['gpClass'] = homeroom[i]['Classes'][currCategory]
if all_stud_list[i]['gpClass'] in confirmedClasses:
if (homeroomCode[0] in gpClasses['Dates'][currDate]['Absent'] and
homeroomCode[1] in gpClasses['Dates'][currDate]['Absent'][homeroomCode[0]] and
i in gpClasses['Dates'][currDate]['Absent'][homeroomCode[0]][homeroomCode[1]]):
# confirmed by teacher and absent
all_stud_list[i]['status'] = 2
else:
# confirmed by teacher and not absent
all_stud_list[i]['status'] = 1
else:
all_stud_list[i]['status'] = 0 # not yet confirmed by teacher
return render_template('homeroom.html', all_stud_list=all_stud_list, currDate=currDate, dates=dates, gpClasses=gpClasses, confirmedClasses=confirmedClasses,
currCategory=currCategory, categories=categories, homeroomCode=homeroomCode, status=status)
else: else:
return redirect('/') return redirect('/logout')
@ app.route('/', methods=['GET', 'POST']) @ app.route('/', methods=['GET', 'POST'])
@ -211,17 +201,26 @@ def index():
return redirect('/manage') return redirect('/manage')
@app.route('/manage', methods=['GET']) @ app.route('/manage', methods=['GET'])
def manage(): def manage():
return manageProcess("", "") return manageProcess("", "")
@app.route('/manage/date', methods=['POST']) @ app.route('/manage/date', methods=['POST'])
def manage_date(): def manage_date():
return manageProcess("date", request.form['date']) return manageProcess("date", request.form['date'])
@app.route('/manage/group_teach_publish', methods=['POST']) @app.route('/manage/admin', methods=['POST'])
def manage_admin():
data = [
request.form['grade'] + '^' + request.form['room'],
request.form['date']
]
return manageProcess("admin", data)
@ app.route('/manage/group_teach_publish', methods=['POST'])
def group_teach_publish(): def group_teach_publish():
classes = db.child("Users").child( classes = db.child("Users").child(
session['uid']).child("class").get().val() session['uid']).child("class").get().val()
@ -231,28 +230,83 @@ def group_teach_publish():
"name": db.child("Classes").child(i).child( "name": db.child("Classes").child(i).child(
"Class").child(classes[i]).child("name").get().val(), "Class").child(classes[i]).child("name").get().val(),
"category": i, "category": i,
"class_id": classes[i] "class_id": classes[i],
"homerooms": db.child("Classes").child(
"GP_Class").child(i).child("Homerooms").get().val()
} }
print("got class") print("got class")
cDate = "" date = request.form['date']
for key in request.form.keys(): period = request.form['period']
print(type(key), key) signature = request.form['signatureData']
if key == 'date': signature = signature.removeprefix('data:image/png;base64,')
print('here') signature = bytes(signature, 'utf-8')
cDate = request.form[key] rand = str(randint(100000000000000, 999999999999999))
db.child("Classes").child(cclass['category']).child( rand += ".png"
"Dates").child(request.form[key]).update({'confirmed': 0}) with open(os.path.join('temp', rand), "wb") as fh:
db.child("Classes").child(cclass['category']).child( fh.write(base64.decodebytes(signature))
"Dates").child(request.form[key]).update({cclass['class_id']: request.form['signatureData']}) storage.child(os.path.join('signatures', rand)
elif key == 'signatureData': ).put(os.path.join('temp', rand))
pass
else: formData = request.form.to_dict()
# spilt string formData.pop('signatureData')
id = key.split('^') formData.pop('date')
print(id) formData.pop('period')
db.child("Classes").child(cclass['category']).child("Dates").child( for i in formData:
cDate).child("Absent").child(id[0]).child(id[1]).update({id[2]: 1}) i = i.split('^')
return "Success!" db.child("Homerooms").child(i[0]).child(i[1]).child(
"Absent").child(date).child(period).update({i[2]: 0})
for h in cclass['homerooms']:
h = h.split('^')
db.child("Homerooms").child(h[0]).child(h[1]).child(
"Absent").child(date).child(period).child("signature").update({cclass['class_id']: str(storage.child(os.path.join('signatures', rand)).get_url(None))})
os.remove(os.path.join('temp', rand))
return redirect('/manage')
@ app.route('/manage/homeroom_abs', methods=['POST'])
def homeroom_abs_publish():
date = request.form['date']
homeroom = request.form['homeroom'].split('^')
period = request.form['period']
signature = request.form['signatureData']
signature = signature.removeprefix('data:image/png;base64,')
signature = bytes(signature, 'utf-8')
rand = str(randint(100000000000000, 999999999999999))
rand += ".png"
with open(os.path.join('temp', rand), "wb") as fh:
fh.write(base64.decodebytes(signature))
storage.child(os.path.join('signatures', rand)
).put(os.path.join('temp', rand))
formData = request.form.to_dict()
formData.pop('signatureData')
formData.pop('date')
formData.pop('homeroom')
formData.pop('period')
for i in formData:
db.child("Homerooms").child(homeroom[0]).child(
homeroom[1]).child("Absent").child(date).child(period).update({i: 0})
db.child("Homerooms").child(homeroom[0]).child(homeroom[1]).child(
"Absent").child(date).child(period).update({'signature': str(storage.child(os.path.join('signatures', rand)).get_url(None))})
os.remove(os.path.join('temp', rand))
return redirect('/manage')
@app.route('/manage/homeroom_confirm', methods=['POST'])
def homeroom_confirm():
date = request.form['date']
homeroom = request.form['homeroom'].split('^')
signature = request.form['signatureData']
signature = signature.removeprefix('data:image/png;base64,')
signature = bytes(signature, 'utf-8')
rand = str(randint(100000000000000, 999999999999999))
rand += ".png"
with open(os.path.join('temp', rand), "wb") as fh:
fh.write(base64.decodebytes(signature))
storage.child(os.path.join('signatures', rand)
).put(os.path.join('temp', rand))
db.child("Homerooms").child(homeroom[0]).child(homeroom[1]).child("Absent").child(date).update(
{"confirm": str(storage.child(os.path.join('signatures', rand)).get_url(None))})
return redirect('/manage')
@ app.route('/upload/homeroom', methods=['GET', 'POST']) @ app.route('/upload/homeroom', methods=['GET', 'POST'])
@ -280,6 +334,36 @@ def upload_homeroom():
return "Successfully uploaded " + gradec + "-" + classc return "Successfully uploaded " + gradec + "-" + classc
@ app.route('/upload/gp_classes', methods=['GET', 'POST'])
def upload_gp_classes():
if request.method == 'GET':
return render_template('uploadcsv.html', title="Group Classes", url="/upload/gp_classes")
elif request.method == 'POST':
try:
csv_file = request.files['csv']
filepath = os.path.join('./temp', csv_file.filename)
csv_file.save(filepath)
csv_dict = pd.read_csv(filepath)
category_cnt = csv_dict.shape[1] - 1
for i in range(category_cnt):
tmp_csv = csv_dict[csv_dict.columns[i+1]].tolist()
for j in range(len(tmp_csv)):
if type(tmp_csv[j]) == float:
break
if j % 4 == 0:
db.child("Classes").child("GP_Class").child(csv_dict.columns[i+1]).child("Class").child(
tmp_csv[j]).child("name").set(tmp_csv[j+1])
db.child("Classes").child("GP_Class").child(csv_dict.columns[i+1]).child("Class").child(
tmp_csv[j]).child("teacher").set(tmp_csv[j+2])
db.child("Classes").child("GP_Class").child(csv_dict.columns[i+1]).child("Class").child(
tmp_csv[j]).child("classroom").set(tmp_csv[j+3])
os.remove(filepath)
except Exception as e:
os.remove(filepath)
return "Error. Please try again\n("+str(e)+")"
return "Successfully uploaded"
@ app.route('/upload/stud_in_group', methods=['GET', 'POST']) @ app.route('/upload/stud_in_group', methods=['GET', 'POST'])
def upload_stud_in_group(): def upload_stud_in_group():
if request.method == 'GET': if request.method == 'GET':
@ -295,13 +379,13 @@ def upload_stud_in_group():
csv_dict = csv.DictReader(file) csv_dict = csv.DictReader(file)
headers = csv_dict.fieldnames headers = csv_dict.fieldnames
headers = headers[1:] headers = headers[1:]
for h in headers:
db.child("Classes").child("GP_Class").child(
h).child("Homerooms").update({gradec+'^'+classc: 0})
for row in csv_dict: for row in csv_dict:
for h in headers: for h in headers:
db.child("Homerooms").child(gradec).child(classc).child( db.child("Homerooms").child(gradec).child(classc).child(
row['number']).child("Classes").child(h).set(row[h]) row['number']).child("GP_Class").update({h: row[h]})
db.child("Classes").child(h).child("Class").child(row[h]).child(
"Students").child(gradec).child(classc).update({str(row['number']): 0})
os.remove(filepath) os.remove(filepath)
except Exception as e: except Exception as e:
os.remove(filepath) os.remove(filepath)
@ -309,6 +393,76 @@ def upload_stud_in_group():
return "Successfully uploaded " + gradec + "-" + classc return "Successfully uploaded " + gradec + "-" + classc
@ app.route('/upload/period_list', methods=['GET', 'POST'])
def upload_period_list():
if request.method == 'GET':
return render_template('uploadcsv.html', title="Period List", url="/upload/period_list")
elif request.method == 'POST':
try:
# get csv
gradec = request.form['gradeCode']
classc = request.form['classcode']
csv_file = request.files['csv']
filepath = os.path.join('./temp', csv_file.filename)
csv_file.save(filepath)
csv_dict = pd.read_csv(filepath)
periodCodes = csv_dict['Period Day'].tolist()
for i in range(5):
tmp_csv = csv_dict[str(i+1)].tolist()
print(tmp_csv)
for j in range(len(tmp_csv)):
if not (periodCodes[j].endswith('-t')):
if type(tmp_csv[j]) == float:
db.child("Classes").child("Homeroom").child(gradec).child(classc).child(
str(i+1)).child(periodCodes[j]).update({'name': '--'})
else:
db.child("Classes").child("Homeroom").child(gradec).child(classc).child(
str(i+1)).child(periodCodes[j]).update({'name': tmp_csv[j]})
if not(periodCodes[j] == 'm' or periodCodes[j] == 'n'):
j += 1
db.child("Classes").child("Homeroom").child(gradec).child(classc).child(
str(i+1)).child(periodCodes[j-1]).update({'teacher': tmp_csv[j]})
os.remove(filepath)
except Exception as e:
os.remove(filepath)
return "Error. Please try again\n("+str(e)+")"
return "Successfully uploaded " + gradec + "-" + classc
@ app.route('/upload/dates', methods=['GET', 'POST'])
def upload_dates():
if request.method == 'GET':
return render_template('uploadcsv.html', title="School Days", url="/upload/dates")
elif request.method == 'POST':
try:
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
temp = db.child("Homerooms").get().val()
for row in csv_dict:
for h in headers:
for t in temp:
for i in temp[t]:
periodData = db.child("Classes").child(
"Homeroom").child(t).child(i).get().val()
print(type(t), t)
print(type(i), i)
db.child("Homerooms").child(t).child(i).child(
"Absent").child(h).update({"dow": row[h]})
db.child("Homerooms").child(t).child(i).child(
"Absent").child(h).update(
periodData[int(row[h])]
)
os.remove(filepath)
except Exception as e:
os.remove(filepath)
return "Error. Please try again\n("+str(e)+")"
return "Successfully uploaded dates"
# @ app.route('/upload/rm_all_data_of_class', methods=['GET', "POST"]) # @ app.route('/upload/rm_all_data_of_class', methods=['GET', "POST"])
# def rm_all_data_of_class(): # def rm_all_data_of_class():
# if request.method == 'GET': # if request.method == 'GET':
@ -322,7 +476,7 @@ def upload_stud_in_group():
# return "Successfully removed " + classc # return "Successfully removed " + classc
@app.route('/logout', methods=['GET']) @ app.route('/logout', methods=['GET'])
def logout(): def logout():
session.clear() session.clear()
return redirect('/') return redirect('/')

View file

@ -7,13 +7,13 @@ Flask == 2.0.1
# Attendance/test.py: 1 # Attendance/test.py: 1
Pyrebase == 3.0.27 Pyrebase == 3.0.27
# Attendance/app.py: 9 # Attendance/app.py: 7
pandas == 1.1.3
# Attendance/app.py: 10
# Attendance/test.py: 3 # Attendance/test.py: 3
python_dotenv == 0.19.0 python_dotenv == 0.19.0
# Attendance/app.py: 4 # Attendance/app.py: 4
pytz == 2020.1 pytz == 2020.1
# Attendance/app.py: 5,6
sendgrid == 6.7.1
gunicorn == 20.1.0 gunicorn == 20.1.0

View file

@ -30,6 +30,14 @@ div.forSign canvas {
height: 100%; height: 100%;
} }
.margin-bottom {
margin-bottom: 50px;
}
div.signDiv {
margin-bottom: 50px;
}
p.highlightAbs { p.highlightAbs {
margin-bottom: 0; margin-bottom: 0;
} }
@ -42,6 +50,6 @@ p.highlightAbs.n-2 {
color: red; color: red;
} }
div.classlist { .margin-top {
text-align: left; margin-top: 20px;
} }

22
static/homeroom.css Normal file
View file

@ -0,0 +1,22 @@
div.container {
max-width: 90%;
}
.btn.afterSelButton {
padding: .200rem .50rem;
}
body {
text-align: center;
}
.viewSignatures .col .row .col {
border: 1px solid;
margin-bottom: 10px;
text-align: center;
}
.row {
--bs-gutter-x: 0;
}

View file

@ -0,0 +1,221 @@
<!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>Admin_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/homeroom.css">
</head>
<body>
<div class="container">
<h1>Admin_View</h1>
<h2>{{homeroomCode[0]}}: {{homeroomCode[1]}}</h2>
<h2>Status: ({{currDate}}, 星期{{absData[currDate]['dow']}})</h2>
<a href="/logout"><button class="btn btn-primary">Logout 登出</button></a>
<div class="container margin-bottom">
<form action="/manage/admin" id="adminSelForm" method="post">
<div class="row">
<div class="col">
<select name="grade" id="sel-grade" class="form-select" onchange="getHR()" required>
<option value="">選擇年級</option>
{% for grade in homerooms %}
<option value="{{grade}}">{{grade}}</option>
{% endfor %}
</select>
</div>
<div class="col">
<select name="room" id="sel-room" class="form-select" disabled required>
<option value="">請先選擇年級</option>
</select>
</div>
<div class="col">
<select name="date" id="date" class="form-select">
{% for date in absData %}
{% if date == currDate %}
<option value="{{date}}" selected="selected">{{date}}</option>
{% else %}
<option value="{{date}}">{{date}}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="col-1">
<button class="btn btn-primary" onclick="loadingAnimation()">查詢</button>
</div>
</div>
</form>
</div>
<div class="col">
<div class="row title">
<div class="col">HR</div>
<div class="col">Number</div>
<div class="col">Name</div>
<div class="col">Eng Name</div>
<div class="col">Morning</div>
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">Nap</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
</div>
<div class="row title">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
{% for i in periods %}
<div class="col">{{absData[currDate][i]['name']}}</div>
{% endfor %}
</div>
<div class="row title">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
{% for i in periods %}
<div class="col">{{absData[currDate][i]['teacher']}}</div>
{% endfor %}
</div>
{% if data != None %}
{% for i in homeroomData %}
<div class="row">
<div class="col">{{homeroomCode[0]}}{{homeroomCode[1]}}</div>
<div class="col">{{i}}</div>
<div class="col">{{ homeroomData[i]['name'] }}</div>
<div class="col">{{ homeroomData[i]['eng_name'] }}</div>
{% for j in periods %}
{% if 'signature' in absData[currDate][j] %}
{% if i in absData[currDate][j] %}
<div class="col">
<p class="highlightAbs n-2">X</p>
</div>
{% else %}
{% if absData[currDate][j]['name'] != 'GP' %}
<div class="col">
<p class="highlightAbs n-1">V</p>
</div>
{% else %}
{% if (homeroomData[i]['GP_Class'][absData[currDate][j]['teacher']] in
absData[currDate][j]['signature'])%}
<div class="col">
<p class="highlightAbs n-1">V</p>
</div>
{% else %}
<div class="col">
<p class="highlightAbs n-2"></p>
</div>
{% endif %}
{% endif %}
{% endif %}
{% else %}
<div class="col">
<p class="highlightAbs"></p>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
{% endif %}
{% for c in range(periods|length + 1) %}
{% if c % 2 == 0 %}
<div class="row signatures">
{% endif %}
<div class="col half">
{% if c == 0 %}
<div class="row">Homeroom Teacher</div>
<div class="row"><img src="{{absData[currDate]['confirm']}}" alt=""></div>
{% else %}
{% if absData[currDate][periods[c-1]]['name'] == 'GP' %}
{% if 'signature' in absData[currDate][periods[c-1]] %}
{% for i in absData[currDate][periods[c-1]]['signature'] %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['teacher']}}: {{i}}</div>
<div class="row"><img src="{{absData[currDate][periods[c-1]]['signature'][i]}}" alt=""></div>
{% endfor %}
{% else %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['teacher']}}: No Signature
</div>
<div class="row"></div>
{% endif %}
{% else %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['name']}}:
{{absData[currDate][periods[c-1]]['teacher']}}
</div>
<div class="row"><img src="{{absData[currDate][periods[c-1]]['signature']}}" alt=""></div>
{% endif %}
{% endif %}
</div>
{% if c % 2 == 1 %}
</div>
{% endif %}
{% endfor %}
</div>
<div class="row margin-top">
<div class="col">
<h3>此排請勿點選</h3>
</div>
<div class="col">
<a href="/upload/homeroom"><button class="btn btn-primary">1. Add Homeroom</button></a>
</div>
<div class="col">
<a href="/upload/gp_classes"><button class="btn btn-primary">2. Add GP Classes</button></a>
</div>
<div class="col">
<a href="/upload/stud_in_group"><button class="btn btn-primary">3. Add GP Student List</button></a>
</div>
<div class="col">
<a href="/upload/period_list"><button class="btn btn-primary">4. Period List</button></a>
</div>
<div class="col">
<a href="/upload/dates"><button class="btn btn-primary">[WEEKLY] Dates</button></a>
</div>
</div>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt=""
style="height:100%;" />
</div>
<script>
var homerooms = {};
{% for i in homerooms %}
homerooms['{{i}}'] = [];
{% for j in homerooms[i] %}
homerooms['{{i}}'].push({{ j }});
{% endfor %}
{% endfor %}
console.log(homerooms)
function loadingAnimation() {
$('.container').hide();
$('#loading').show();
}
function getHR() {
var grade = $('#sel-grade').val();
$('#sel-room').html('<option value="">請先選擇年級</option>');
if (grade === "") {
$('#sel-room').attr('disabled', 'disabled')
return
}
homerooms[grade].forEach(element => {
$('#sel-room').append(`<option value="${element}">${element}</option>`)
});
$('#sel-room').removeAttr('disabled')
}
function submitQuery() {
loadingAnimation();
document.getElementById('hrSelForm').submit();
}
</script>
</body>
</html>

View file

@ -16,10 +16,11 @@
<div class="container"> <div class="container">
<h1>Group_Teach_View</h1> <h1>Group_Teach_View</h1>
<h2>{{cclass['category']}}: {{cclass['class_id']}}: {{cclass['name']}}</h2> <h2>{{cclass['category']}}: {{cclass['class_id']}}: {{cclass['name']}}</h2>
<h2>Status: {{status}} ({{currDate}})</h2> <h2>({{currDate}}) ({{dow}})</h2>
<a href="/logout"><button class="btn btn-primary">Logout 登出</button></a>
<form action="/manage/date" id="dateSelForm" method="post"> <form action="/manage/date" id="dateSelForm" method="post">
<select name="date" id="date" class="form-select" onchange="chgDate(this);"> <select name="date" id="date" class="form-select" onchange="chgDate(this);">
{% for date in dates %} {% for date in tmpAbsData %}
{% if date == currDate %} {% if date == currDate %}
<option value="{{date}}" selected="selected">{{date}}</option> <option value="{{date}}" selected="selected">{{date}}</option>
{% else %} {% else %}
@ -28,15 +29,12 @@
{% endfor %} {% endfor %}
</select> </select>
</form> </form>
{% if status == 1 %} {% set alr_fill = namespace(found=false) %}
<div class="alert alert-warning" role="alert"> {% for i in absData %}
Already Sumitted! <form action="/manage/group_teach_publish" id="attendanceData^{{i}}" method="post">
</div>
{% endif %}
{% if status == 0 %}
<form action="/manage/group_teach_publish" id="attendanceData" method="post">
<input type="hidden" name="date" value="{{currDate}}"> <input type="hidden" name="date" value="{{currDate}}">
<input type="hidden" name="signatureData" value=""> <input type="hidden" name="period" value="{{i}}">
<input type="hidden" class="signatureData" name="signatureData" value="">
<div class="col"> <div class="col">
<div class="row title"> <div class="row title">
<div class="col">Grade</div> <div class="col">Grade</div>
@ -44,58 +42,96 @@
<div class="col">Number</div> <div class="col">Number</div>
<div class="col">Name</div> <div class="col">Name</div>
<div class="col">Eng Name</div> <div class="col">Eng Name</div>
<div class="col">Attendance (Check Absent)</div> <div class="col">Period {{i}}</div>
</div> </div>
{% if data != None %} {% if data != None %}
{% for grade in all_stud_list %} {% for grade in absData[i] %}
{% for homeroom in all_stud_list[grade] %} {% for homeroom in absData[i][grade] %}
{% for student in all_stud_list[grade][homeroom] %} {% for student in absData[i][grade][homeroom] %}
<div class="row"> <div class="row">
<div class="col">{{grade}}</div> <div class="col">{{grade}}</div>
<div class="col">{{homeroom}}</div> <div class="col">{{homeroom}}</div>
<div class="col">{{ student }}</div> <div class="col">{{ student }}</div>
<div class="col">{{ all_stud_list[grade][homeroom][student]['name'] }}</div> <div class="col">{{ absData[i][grade][homeroom][student]['name'] }}</div>
<div class="col">{{ all_stud_list[grade][homeroom][student]['eng_name'] }}</div> <div class="col">{{ absData[i][grade][homeroom][student]['eng_name'] }}</div>
<div class="col"><input type="checkbox" name="{{grade}}^{{homeroom}}^{{student}}"></div> {% if absData[i][grade][homeroom][student]['alr_fill'] %}
{% set alr_fill.found = true %}
{% if absData[i][grade][homeroom][student]['absent'] %}
<div class="col">
<p class="highlightAbs n-2">X</p>
</div>
{% else %}
<div class="col">
<p class="highlightAbs n-1">V</p>
</div>
{% endif %}
{% else %}
<div class="col">
{% if 'confirm' in absData[i][grade][homeroom] %}
<p class="highlightAbs">--</p>
{% else %}
<input type="checkbox" class="{{grade}}^{{homeroom}}^{{student}}">
{% endif %}
</div>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
<h3>Please Sign Below</h3> {% if alr_fill.found %}
<div class="forSign"><canvas id="signature_pad"></canvas></div> <button class="btn btn-primary margin-bottom viewSignatureBtn" type="button"
<button class="btn btn-secondary" type="button" onclick="signaturePad.clear()">Clear Signature</button> onclick="viewSignature('{{i}}')" disabled="disabled">
<button class="btn btn-primary" type="button" onclick="submitForm()">Submit</button> Already Submitted</button>
{% else %}
<button class="btn btn-primary margin-bottom viewSignatureBtn" type="button"
onclick="viewSignature('{{i}}')">
↑ Confirmed, Sign (Period {{i}}) ↑</button>
{% endif %}
<div class="signDiv" id="sign^{{i}}" hidden="hidden">
<h3>Please Sign Below</h3>
<div class="forSign"><canvas id="signature_pad^{{i}}"></canvas></div>
<button class="btn btn-secondary" type="button" onclick="signaturePad.clear()">Clear
Signature</button><button class="btn btn-primary" type="button"
onclick="submitForm()">Submit</button>
</div>
</div> </div>
</form> </form>
{% endfor %}
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script> <script src=" https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script> <script>
var canvas = document.getElementById("signature_pad"); var signaturePad, selPeriod;
var signaturePad = new SignaturePad(canvas);
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
function submitForm() { function submitForm() {
if (!signaturePad.isEmpty()) { if (!signaturePad.isEmpty()) {
signaturePad.off(); signaturePad.off();
var data = signaturePad.toDataURL('image/png'); var data = signaturePad.toDataURL('image/png');
document.getElementsByName('signatureData')[0].value = data; document.getElementById("attendanceData^" + selPeriod).getElementsByClassName("signatureData")[0].value = data;
document.getElementById('attendanceData').submit(); document.getElementById("attendanceData^" + selPeriod).submit();
} }
else { else {
alert("Please sign first"); alert("Please sign first");
} }
} }
function viewSignature(period) {
selPeriod = period
$('.viewSignatureBtn').attr({ 'disabled': 'disabled' });
$('.viewSignatureBtn').removeClass('margin-bottom');
document.getElementById('sign^' + period).removeAttribute('hidden');
var canvas = document.getElementById("signature_pad^" + period);
signaturePad = new SignaturePad(canvas);
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
}
</script> </script>
{% endif %}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt="" <div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt=""
style="height:100%;" /> style="height:100%;" />
</div> </div>

View file

@ -9,17 +9,18 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous"> integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<link rel="stylesheet" href="/static/allpages.css"> <link rel="stylesheet" href="/static/allpages.css">
<link rel="stylesheet" href="/static/login.css"> <link rel="stylesheet" href="/static/homeroom.css">
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<h1>Homeroom_View</h1> <h1>Homeroom_View</h1>
<h2>{{homeroomCode[0]}}: {{homeroomCode[1]}}</h2> <h2>{{homeroomCode[0]}}: {{homeroomCode[1]}}</h2>
<h2>Status: ({{currDate}})</h2> <h2>Status: ({{currDate}}, 星期{{absData[currDate]['dow']}})</h2>
<a href="/logout"><button class="btn btn-primary">Logout 登出</button></a>
<form action="/manage/date" id="dateSelForm" method="post"> <form action="/manage/date" id="dateSelForm" method="post">
<select name="date" id="date" class="form-select" onchange="chgDate();"> <select name="date" id="date" class="form-select" onchange="chgDate();">
{% for date in dates %} {% for date in absData %}
{% if date == currDate %} {% if date == currDate %}
<option value="{{date}}" selected="selected">{{date}}</option> <option value="{{date}}" selected="selected">{{date}}</option>
{% else %} {% else %}
@ -30,114 +31,172 @@
</form> </form>
<form action="/manage/homeroom_confirm" id="homeroom_confirm" method="post"> <form action="/manage/homeroom_confirm" id="homeroom_confirm" method="post">
<input type="hidden" name="date" value="{{currDate}}"> <input type="hidden" name="date" value="{{currDate}}">
<input type="hidden" name="category" value="{{currCategory}}"> <input type="hidden" name="homeroom" value="{{homeroomCode[0]}}^{{homeroomCode[1]}}">
<input type="hidden" name="signatureData" value=""> <input type="hidden" id="hrCfrm-sign" name="signatureData" value="">
</form> </form>
<div class="col"> <div class="col">
<div class="row title"> <div class="row title">
<div class="col">Homeroom</div> <div class="col">HR</div>
<div class="col">Number</div> <div class="col">Number</div>
<div class="col">Name</div> <div class="col">Name</div>
<div class="col">Eng Name</div> <div class="col">Eng Name</div>
<div class="col">GP_Class</div> <div class="col">Morning</div>
<div class="col">Attendance (Here=V, Abs=X)</div> <div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">Nap</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
</div>
<div class="row title">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
{% for i in periods %}
<div class="col">{{absData[currDate][i]['name']}}</div>
{% endfor %}
</div>
<div class="row title">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
{% for i in periods %}
<div class="col">{{absData[currDate][i]['teacher']}}</div>
{% endfor %}
</div> </div>
{% if data != None %} {% if data != None %}
{% for i in all_stud_list %} {% for i in homeroomData %}
<div class="row"> <div class="row">
<div class="col">{{homeroomCode[0]}}{{homeroomCode[1]}}</div> <div class="col">{{homeroomCode[0]}}{{homeroomCode[1]}}</div>
<div class="col">{{i}}</div> <div class="col">{{i}}</div>
<div class="col">{{ all_stud_list[i]['name'] }}</div> <div class="col">{{ homeroomData[i]['name'] }}</div>
<div class="col">{{ all_stud_list[i]['eng_name'] }}</div> <div class="col">{{ homeroomData[i]['eng_name'] }}</div>
<div class="col">{{ all_stud_list[i]['gpClass'] }}: {% for j in periods %}
{{gpClasses['Class'][all_stud_list[i]['gpClass']]['name']}}</div> {% if 'signature' in absData[currDate][j] %}
{% if i in absData[currDate][j] %}
<div class="col"> <div class="col">
<p class="highlightAbs n-{{all_stud_list[i]['status']}}"> <p class="highlightAbs n-2">X</p>
{% if all_stud_list[i]['status'] == 1 %}
V
{% elif all_stud_list[i]['status'] == 2 %}
X
{% endif %}
</p>
</div> </div>
{% else %}
{% if absData[currDate][j]['name'] != 'GP' %}
<div class="col">
<p class="highlightAbs n-1">V</p>
</div>
{% else %}
{% if (homeroomData[i]['GP_Class'][absData[currDate][j]['teacher']] in
absData[currDate][j]['signature'])%}
<div class="col">
<p class="highlightAbs n-1">V</p>
</div>
{% else %}
<div class="col">
<p class="highlightAbs n-2"></p>
</div>
{% endif %}
{% endif %}
{% endif %}
{% elif absData[currDate][j]['name'] == 'GP' %}
<div class="col">
<p class="highlightAbs"></p>
</div>
{% else %}
<div class="col">
{% if 'confirm' in absData[currDate] %}
<p class="highlightAbs"></p>
{% else %}
<input type="checkbox" class="tobeform {{j}}^{{i}}">
{% endif %}
</div>
{% endif %}
{% endfor %}
</div> </div>
{% endfor %} {% endfor %}
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
{% for i in periods %}
<div class="col">
{% if ('signature' in absData[currDate][i] or absData[currDate][i]['name'] == 'GP' or
'confirm' in absData[currDate]) %}
<button class="btn btn-primary afterSelButton" disabled="disabled"
onclick="afterSelAbs('{{i|string}}')">Confirm</button>
{% else %}
<button class="btn btn-primary afterSelButton"
onclick="afterSelAbs('{{i|string}}')">Confirm</button>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %} {% endif %}
<!-- show signature of confirmed classes --> <form action="/manage/homeroom_abs" id="postHomeroomAbs" hidden="hidden" method="post">
{% for c in range(confirmedClasses|length) %} <input type="text" id="HR-date" name="date" value="{{currDate}}">
<input type="text" id="HR-period" name="period" value="">
<input type="text" id="HR-signatureData" name="signatureData" value="">
<input type="text" id="HR-homeroom" name="homeroom" value="{{homeroomCode[0]}}^{{homeroomCode[1]}}">
</form>
{% if 'confirm' in absData[currDate] %}
<button class="btn btn-primary margin-top afterSelButton" onclick="homeroomCfrm()" disabled="disabled">
Already Confirmed</button>
{% else %}
<button class="btn btn-primary margin-top afterSelButton" onclick="homeroomCfrm()">Homeroom
Teacher Confirm</button>
{% endif %}
<div id="finalCheck" hidden="hidden">
<h3>Please Sign Below</h3>
<div class="forSign"><canvas id="signature_pad"></canvas></div>
<button class="btn btn-secondary" type="button" onclick="signaturePad.clear()">Clear Signature</button>
<button class="btn btn-primary" type="button" onclick="submitForm()">Submit</button>
</div>
{% for c in range(periods|length + 1) %}
{% if c % 2 == 0 %} {% if c % 2 == 0 %}
<div class="row signatures"> <div class="row signatures">
{% endif %} {% endif %}
<div class="col half"> <div class="col half">
<div class="row">{{confirmedClasses[c]}}: {{gpClasses['Class'][confirmedClasses[c]]['name']}} {% if c == 0 %}
<div class="row">Homeroom Teacher</div>
<div class="row"><img src="{{absData[currDate]['confirm']}}" alt=""></div>
{% else %}
{% if absData[currDate][periods[c-1]]['name'] == 'GP' %}
{% if 'signature' in absData[currDate][periods[c-1]] %}
{% for i in absData[currDate][periods[c-1]]['signature'] %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['teacher']}}: {{i}}</div>
<div class="row"><img src="{{absData[currDate][periods[c-1]]['signature'][i]}}" alt=""></div>
{% endfor %}
{% else %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['teacher']}}: No Signature
</div> </div>
<div class="row"><img src="{{gpClasses['Dates'][currDate][confirmedClasses[c]]}}" alt=""></div> <div class="row"></div>
{% endif %}
{% else %}
<div class="row">{{periods[c-1]}}: {{absData[currDate][periods[c-1]]['name']}}:
{{absData[currDate][periods[c-1]]['teacher']}}
</div>
<div class="row"><img src="{{absData[currDate][periods[c-1]]['signature']}}" alt=""></div>
{% endif %}
{% endif %}
</div> </div>
{% if c % 2 == 1 %} {% if c % 2 == 1 %}
</div> </div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<!-- Show Class Data -->
<div class="classlist">
<h2>Classes in {{currCategory}}</h2>
<ul>
{% for c in gpClasses['Class'] %}
<li>
<h3>{{c}}: {{gpClasses['Class'][c]['name']}}</h3>
</li>
<ul>
<li>
<h4>Classroom: {{ gpClasses['Class'][c]['classroom'] }}</h4>
</li>
<li>
<h4>Teacher: {{ gpClasses['Class'][c]['teacher'] }}</h4>
</li>
</ul>
{% endfor %}
</ul>
</div>
{% if status == 1 %}
<h3>Please Sign Below</h3>
<div class="forSign"><canvas id="signature_pad"></canvas></div>
<button class="btn btn-secondary" type="button" onclick="signaturePad.clear()">Clear Signature</button>
<button class="btn btn-primary" type="button" onclick="submitForm()">Submit</button>
{% else %}
<h3>Please wait for all {{currCategory}} teachers to enter data.</h3>
{% endif %}
</div> </div>
</div> </div>
{% if status == 1 %}
<script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/signature_pad@2.3.2/dist/signature_pad.min.js"></script>
<script>
var canvas = document.getElementById("signature_pad");
var signaturePad = new SignaturePad(canvas);
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
function submitForm() {
if (!signaturePad.isEmpty()) {
signaturePad.off();
var data = signaturePad.toDataURL('image/png');
document.getElementsByName('signatureData')[0].value = data;
document.getElementsByTagName('form')[0].submit();
}
else {
alert("Please sign first");
}
}
</script>
{% endif %}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt="" <div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt=""
style="height:100%;" /> style="height:100%;" />
</div> </div>
<script> <script>
var signaturePad, hrCfrm = false;
function loadingAnimation() { function loadingAnimation() {
$('.container').hide(); $('.container').hide();
$('#loading').show(); $('#loading').show();
@ -146,6 +205,56 @@
loadingAnimation(); loadingAnimation();
document.getElementById('dateSelForm').submit(); document.getElementById('dateSelForm').submit();
} }
function submitForm() {
if (!signaturePad.isEmpty()) {
loadingAnimation()
signaturePad.off();
var data = signaturePad.toDataURL('image/png');
if (hrCfrm) {
$('#hrCfrm-sign').val(data);
document.getElementById('homeroom_confirm').submit()
} else {
document.getElementById('HR-signatureData').value = data;
document.getElementById('postHomeroomAbs').submit();
}
}
else {
alert("Please sign first");
}
}
function showSignaturePad() {
$('#finalCheck').removeAttr('hidden');
var canvas = document.getElementById("signature_pad");
signaturePad = new SignaturePad(canvas);
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
}
function afterSelAbs(period) {
var tobeformArr = [];
$('#postHomeroomAbs #HR-period').val(period);
$('.tobeform').attr('disabled', 'disabled');
$('.afterSelButton').attr('disabled', 'disabled');
$('.tobeform').each(function (i, obj) {
if ($(this).attr('class').split(' ')[1].split('^')[0] == period &&
$(this).is(":checked")) {
$('#postHomeroomAbs').append('<input type="checkbox" name="' + $(this).attr('class').split(' ')[1].split('^')[1]
+ '" checked="checked">');
}
});
// show signature pad
showSignaturePad()
}
function homeroomCfrm() {
hrCfrm = true;
showSignaturePad();
}
</script> </script>
</body> </body>

View file

@ -34,11 +34,28 @@
<label for="csv">{{title}}</label> <label for="csv">{{title}}</label>
<input type="file" class="form-control-file" id="csv" name="csv"> <input type="file" class="form-control-file" id="csv" name="csv">
</div> </div>
<button type="submit" class="btn btn-primary">Upload</button> <button onclick="loadingAnimation()" type="submit" class="btn btn-primary">Upload</button>
</form> </form>
<!-- show danger zone -->
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">Warning! 警告!</h4>
<p>If you are not the adminstrator, please do not click "upload" This might make the system
unuseable.</p>
<p>非管理員請勿點選! 可能會讓系統無法使用!</p>
</div>
</div> </div>
</div> </div>
</div> </div>
<div id="loading" style="text-align:center; width:100%; display:none;"><img src="/static/loading.gif" alt=""
style="height:100%;" />
</div>
<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>
<!-- end csv form center --> <!-- end csv form center -->
</body> </body>