-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtrainer.htm
More file actions
257 lines (231 loc) · 11.9 KB
/
Copy pathtrainer.htm
File metadata and controls
257 lines (231 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link REL="SHORTCUT ICON" HREF="img/favicon.ico">
<title>Grace Trainer</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.css" />
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid-theme.min.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script>
<script src="lib/papaparse.min.js"></script>
</head>
<style>
body { font-family:SegoeUI,Verdana,Geneva,sans-serif; font-size:16px; box-sizing:border-box;
padding:0; margin:0; position:fixed; width:100%;
}
.lz-splash { color:#999; text-align:center; margin-top:10%;
}
.lz-main { width:100%; height:var(--maxvh); user-select: none; display:none;
}
.lz-confirm { position:absolute; width:300px; padding: 16px; left:calc(50% - 150px); top:calc(50vh - 50px); user-select: none;
border-radius: 8px; background-color: #fff; border: 1px solid #999; box-shadow: 4px 2px 12px 2px #aaa;
}
.lz-popup { position:absolute; width: auto; max-width:200px; padding: 12px; left: calc(50% - 100px); top: calc(66% - 50px);
border-radius: 8px; background-color: #eee; border: 1px solid #999; box-shadow: 4px 2px 12px 2px #aaa;
font-size: 14px; text-align:center; display: none;
}
.lz-is { border-radius:16px; padding:0 8px; width:250px; height: 24px;
border:1px solid #999; font-size: 13px;
}
.lz-bs { cursor: pointer; color:#fff; text-align: center; border-radius: 16px; display: inline-block;
font-size: 16px; background-color: #27ae60; padding: 4px 12px 4px 12px; vertical-align:3px;user-select: none;
}
.jsgrid-cell { overflow:hidden; }
:root { --maxvh: 100vh }
table { border-spacing: 0px; }
@font-face { font-family: SegoeUI; src: url(img/segoeui.ttf); }
body ::-webkit-scrollbar { width: 9px; height:8px }
body ::-webkit-scrollbar-track { background: transparent; }
body ::-webkit-scrollbar-thumb { border-radius:8px ;background:#a4baec }
body ::-webkit-scrollbar-thumb:hover { background: #a4baec }
</style>
<body>
<div class="lz-main" id="mainDiv">
<img src="img/smlogo.png" style="height:80px;margin:12px">
<span style="vertical-align:42px;font-size:30px;margin-right:12px"><b>TRAINING DATA REVIEW</b></span>
<div class="lz-bs" style="float:right;margin:40px 16px 0 0" onclick="app.SaveAsCSV()">Save as CSV file</div>
<div id="jsGrid-data"></div>
</div>
<div id="splashDiv" class="lz-splash">
<img src="img/ACTlogo.png" style='width:200px' alt="logo"><br><br>
<p style="color:#000;font-size:14px"><b>Email: </b><input class='lz-is' type='text' id='email' style="margin:4px"><br>
<b>Password: </b><input class='lz-is' type='password' id='password'></p><br><br>
<div id="loginBut" class="lz-bs">LOG IN</div>
<br><br><br><br><div style="font-size:11px">© 2022 StageTools </div>
</div>
<script>
/////////////////////////////////////////////////////////////////////////////////////////////////
// MAIN
/////////////////////////////////////////////////////////////////////////////////////////////////
var app=null;
$(document).ready(function() { // ON PAGE LOADED
$("#splashDiv").fadeIn(2000); // Fade in splash page
if (window.location.host == "localhost") { // Not in debug
app=new App(); // Load app
$("#mainDiv").fadeIn(2000); // Fade in splash page
$("#splashDiv").remove(); // Remove splash
}
$("#loginBut").on("click",()=> { // ON LOG IN
fetch(`//${window.location.host}:8081?q=login&role=admin&email=${$("#email").val()}&password=${$("#password").val()}`)
.then(res => res.text()) // Get as text
.then(text =>{ // Process
if (text != "OK") { // Bad password or email
Sound("delete"); // Delete sound
PopUp("Sorry, but that's not the right email or password"); // Alert
return; // Quit
}
app=new App(); // Load app
$("#mainDiv").fadeIn(2000); // Fade in splash page
$("#splashDiv").remove(); // Remove splash
});
});
$("#typeChoice").on("change",()=> { // ON LOG IN
app.curType=$("#typeChoice").val(); // Set type
app.Load(); // Load from SQL
});
});
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// APP
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class App {
constructor() // CONSTRUCTOR
{
app=this; // App global pointer
this.curType="TWG"; // Current type of data to load
this.InitGrid(); // Init grid
this.activityId=0; // Activity to sort by
this.trainingData=[]; // Holds raw data
$("#jsGrid-data").jsGrid("option","data",[]); // Add lines to grid
let v=window.location.search.substring(1).split("&"); // Get query string
for (let i=0;i<v.length;++i) { // For each param
if (v[i] && v[i].match(/a=/)) this.activityId=v[i].substring(2) // Get activity id
}
}
InitGrid() // INIT JS GRID
{
this.pFields=[ { name:"date", type:"text", width:50 },
{ name:"email", type:"text", width:50 },
{ name:"remark", type:"text", width:250 },
{ name:"intent", type:"text", width:50 },
{ name:"save", type:"checkbox", width:25},
{ type: "control", deleteButton: false}];
$("#jsGrid-data").jsGrid({ width:"100%", height:"calc(100vh - 168px)",
inserting:true, editing:true, sorting:true,
fields: this.pFields, data:[],
onItemEditing: function(args) { trace (1);app.curRow=args.itemIndex; },
});
$("#jsGrid-data").css({padding:0, "font-size":"12px"}); // Style
this.Load(); // Load data
}
Load() // LOAD DATA FROM SQL
{
let i,j,v,o;
fetch(`//${window.location.host}:8081?q=loadall&a=b&type=${this.curType}`) // Fetch dat from SQL
.then(res => res.json()) // Get as JSON
.then(data =>{ // On data
this.trainingData=[]; // Clear
for (i=0;i<data.length;++i) { // Look at each
if (data[i].type != "TWG") continue; // Only Grace
if (this.activityId && (data[i].password != this.activityId)) continue; // Limit by activity
o=JSON.parse(data[i].data); // Objectify
for (j=0;j<o.length;++j) { // Look at each
if (o[j].from != "Teacher") continue; // Only remarks
v={ date:data[i].date, act:data[i].password, email:data[i].email, save:0 }; // Boilerplate
v.remark=o[j].text; // Save remark
v.intent=o[j].intent; // Save intent
this.trainingData.push(v); // Add line
}
}
$("#jsGrid-data").jsGrid("option","data",this.trainingData); // Fill grid with data
$("#jsGrid-data").jsGrid("sort", { field: "date", order: "desc" }); // Sort by id, latest first
});
}
SaveAsCSV() // SAVE AS CSV FILE
{
let i,cData=[];
let fields=["remark","intent"]; // Field names
let data=$("#jsGrid-data").jsGrid("option","data"); // Get from grid
for (i=0;i<data.length;++i) // For each line
if (data[i].save) cData.push({intent:data[i].intent, remark:data[i].remark}); // Add if saving
let str=Papa.unparse(cData,{ header:true, skipEmptyLines:true, columns:fields }); // Make CSV using lib
SaveTextAsFile("*.csv", str); // Save to file
}
} // Class closure
/////////////////////////////////////////////////////////////////////////////////////////////////
// HELPERS
/////////////////////////////////////////////////////////////////////////////////////////////////
function trace(msg, p1, p2, p3, p4) // CONSOLE
{
if (p4 != undefined)
console.log(msg,p1,p2,p3,p4);
else if (p3 != undefined)
console.log(msg,p1,p2,p3);
else if (p2 != undefined)
console.log(msg,p1,p2);
else if (p1 != undefined)
console.log(msg,p1);
else
console.log(msg);
}
function Sound(sound, mute) // PLAY SOUND
{
var snd=new Audio(); // Init audio object
if (sound.match(/\.mp3/i)) snd=new Audio(sound) // If an MP3 file
else snd=new Audio("img/"+sound+".mp3"); // Use built in mp3
if (!mute) { // If not initing or muting
snd.volume=100/100; // Set volume
snd.play(); // Play it
}
}
function PopUp(msg, time, div) // TIMED POPUP
{
var str="";
$("#popupDiv").remove(); // Kill old one, if any
str+="<div id='popupDiv' class='lz-popup'>"; // Add div
if (time == -1) { // If has close but
time=100000; // Increase time
str+="<img id='pu-close' src='img/closedot.gif' style='float:right;cursor:pointer'>"; // Add close button
}
str+=msg+"</div>"; // Add div
$(div ? "#"+div : "body").append(str); // Add popup to div or body
$("#pu-close").click(function() { $("#popupDiv").remove(); }); // Remove on click of close but
$("#popupDiv").fadeIn(500).delay(time ? time*1000 : 3000).fadeOut(500); // Animate in and out
}
function GetTextBox(title, content, def, callback) // GET TEXT LINE BOX
{
$("#confirmBoxDiv").remove(); // Remove
$("body").append("<div class='lz-confirm' id='confirmBoxDiv'></div>"); // Add box
var str="<img src='img/smlogo.png' width='64' style='vertical-align:-8px'/> ";
str+="<span style='font-size:14px; color:#666'><b>"+title+"</b></span><br><br>";
str+="<p>"+content+"<p>";
str+="<p><input class='lz-is' style='width:75%' type='text' id='gtBoxTt' value='"+def+"'></p>";
str+="<div id='dialogOK' class='lz-bs'>OK</div>";
str+="<div id='dialogCancel' class='lz-bs' style='margin-left:8px;background-color:#999'>Cancel</div></div>";
$("#confirmBoxDiv").html(str); // Add to div
$("#gtBoxTt").focus(); // Focus on button
$("#gtBoxTt").on("change", function() { callback($("#gtBoxTt").val()); $("#confirmBoxDiv").remove(); }); // ONE ENTER
$("#dialogOK").on("click", function() { callback($("#gtBoxTt").val()); $("#confirmBoxDiv").remove(); }); // ON OK
$("#dialogCancel").on("click", function() { $("#confirmBoxDiv").remove(); }); // ON CANCEL
}
function SaveTextAsFile(file, contents) // SAVE TEXT TO LOCAL FILE
{
if (file.charAt(0) == "*") { // If asking
GetTextBox("Type file name","", "", (s)=>{ SaveTextAsFile(s+file.substr(1), contents); }); // Ask for name
return; // Quit
}
var textFileAsBlob=new Blob([contents], {type:'text/plain'});
var downloadLink=document.createElement("a");
downloadLink.download=file;
downloadLink.innerHTML="Download File";
downloadLink.href=window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick=()=>{ downloadLink.remove(); };
downloadLink.style.display="none";
downloadLink.id="tdll";
document.body.appendChild(downloadLink);
downloadLink.click();
}
</script>
</body>
</html>