GameSentenceMiner 2.16.6__py3-none-any.whl → 2.16.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of GameSentenceMiner might be problematic. Click here for more details.
- GameSentenceMiner/config_gui.py +8 -0
- GameSentenceMiner/util/configuration.py +1 -0
- GameSentenceMiner/util/db.py +83 -2
- GameSentenceMiner/util/ffmpeg.py +1 -0
- GameSentenceMiner/vad.py +2 -1
- GameSentenceMiner/web/database_api.py +64 -36
- GameSentenceMiner/web/static/js/search.js +1 -1
- GameSentenceMiner/web/static/js/stats.js +35 -11
- GameSentenceMiner/web/templates/stats.html +464 -422
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/RECORD +15 -15
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.16.6.dist-info → gamesentenceminer-2.16.8.dist-info}/top_level.txt +0 -0
|
@@ -1,520 +1,562 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset="UTF-8">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
7
|
<title>GSM Dashboard</title>
|
|
7
8
|
<!-- Include Chart.js from a CDN -->
|
|
8
9
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
<!-- Include html2canvas for screenshot functionality -->
|
|
11
12
|
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
|
|
12
|
-
|
|
13
|
+
|
|
13
14
|
<!-- Include shared theme styles -->
|
|
14
15
|
{% include 'components/theme-styles.html' %}
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
<!-- Include shared CSS -->
|
|
17
18
|
<link rel="stylesheet" href="/static/css/shared.css">
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
<!-- Include stats-specific CSS -->
|
|
20
21
|
<link rel="stylesheet" href="/static/css/stats.css">
|
|
21
|
-
|
|
22
|
+
|
|
22
23
|
<!-- Include shared kanji grid CSS -->
|
|
23
24
|
<link rel="stylesheet" href="/static/css/kanji-grid.css">
|
|
24
25
|
</head>
|
|
26
|
+
|
|
25
27
|
<body>
|
|
26
28
|
|
|
27
|
-
<div class="container">
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<!-- Include shared navigation -->
|
|
31
|
-
{% include 'components/navigation.html' %}
|
|
29
|
+
<div class="container">
|
|
30
|
+
<h1>GSM - Statistics</h1>
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
|
|
52
|
-
<span class="dashboard-stat-value" id="currentTotalChars">-</span>
|
|
53
|
-
<span class="dashboard-stat-label">Characters</span>
|
|
54
|
-
</div>
|
|
55
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
|
|
56
|
-
<span class="dashboard-stat-value" id="currentTotalTime">-</span>
|
|
57
|
-
<span class="dashboard-stat-label">Time Spent</span>
|
|
58
|
-
</div>
|
|
59
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
|
|
60
|
-
<span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
|
|
61
|
-
<span class="dashboard-stat-label">Chars/Hour</span>
|
|
62
|
-
</div>
|
|
63
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
|
|
64
|
-
<span class="dashboard-stat-value" id="currentSessions">-</span>
|
|
65
|
-
<span class="dashboard-stat-label">Sessions</span>
|
|
32
|
+
<!-- Include shared navigation -->
|
|
33
|
+
{% include 'components/navigation.html' %}
|
|
34
|
+
|
|
35
|
+
<!-- Dashboard Statistics Sections -->
|
|
36
|
+
<div class="dashboard-container">
|
|
37
|
+
<!-- Current Game Statistics Panel -->
|
|
38
|
+
<div class="dashboard-card current-game" id="currentGameCard">
|
|
39
|
+
<div class="dashboard-card-header">
|
|
40
|
+
<div>
|
|
41
|
+
<h3 class="dashboard-card-title">
|
|
42
|
+
<span class="dashboard-card-icon">🎮</span>
|
|
43
|
+
Current Game Statistics
|
|
44
|
+
</h3>
|
|
45
|
+
<p class="dashboard-card-subtitle" id="currentGameName">Loading...</p>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="dashboard-streak-indicator" id="currentGameStreak" style="display: none;">
|
|
48
|
+
<span id="currentStreakValue">0</span> day streak
|
|
49
|
+
</div>
|
|
66
50
|
</div>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<
|
|
51
|
+
|
|
52
|
+
<div class="dashboard-stats-grid" id="currentGameStats">
|
|
53
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
|
|
54
|
+
<span class="dashboard-stat-value" id="currentTotalChars">-</span>
|
|
55
|
+
<span class="dashboard-stat-label">Characters</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
|
|
58
|
+
<span class="dashboard-stat-value" id="currentTotalTime">-</span>
|
|
59
|
+
<span class="dashboard-stat-label">Time Spent</span>
|
|
75
60
|
</div>
|
|
76
|
-
<div class="dashboard-
|
|
77
|
-
<
|
|
78
|
-
<
|
|
61
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
|
|
62
|
+
<span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
|
|
63
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
|
79
64
|
</div>
|
|
80
|
-
<div class="dashboard-
|
|
81
|
-
<
|
|
82
|
-
<
|
|
65
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
|
|
66
|
+
<span class="dashboard-stat-value" id="currentSessions">-</span>
|
|
67
|
+
<span class="dashboard-stat-label">Sessions</span>
|
|
83
68
|
</div>
|
|
84
69
|
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
71
|
+
<div class="dashboard-progress-section">
|
|
72
|
+
<div class="dashboard-progress-title">Recent Progress</div>
|
|
73
|
+
<div class="dashboard-progress-items">
|
|
74
|
+
<div class="dashboard-progress-item">
|
|
75
|
+
<div class="dashboard-progress-value positive" id="currentMonthlyChars">-</div>
|
|
76
|
+
<div class="dashboard-progress-label">Monthly Characters</div>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="dashboard-progress-item">
|
|
79
|
+
<div class="dashboard-progress-value neutral" id="currentFirstDate">-</div>
|
|
80
|
+
<div class="dashboard-progress-label">Started</div>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="dashboard-progress-item">
|
|
83
|
+
<div class="dashboard-progress-value neutral" id="currentLastDate">-</div>
|
|
84
|
+
<div class="dashboard-progress-label">Last Activity</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
100
87
|
</div>
|
|
101
88
|
</div>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
|
|
117
|
-
<span class="dashboard-stat-value" id="allSessions">-</span>
|
|
118
|
-
<span class="dashboard-stat-label">Sessions</span>
|
|
89
|
+
|
|
90
|
+
<!-- All Games Historical Overview -->
|
|
91
|
+
<div class="dashboard-card all-games" id="allGamesCard">
|
|
92
|
+
<div class="dashboard-card-header">
|
|
93
|
+
<div>
|
|
94
|
+
<h3 class="dashboard-card-title">
|
|
95
|
+
<span class="dashboard-card-icon">📚</span>
|
|
96
|
+
All Games Overview
|
|
97
|
+
</h3>
|
|
98
|
+
<p class="dashboard-card-subtitle" id="totalGamesCount">Loading...</p>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="dashboard-streak-indicator" id="allGamesStreak" style="display: none;">
|
|
101
|
+
<span id="allStreakValue">0</span> day streak
|
|
102
|
+
</div>
|
|
119
103
|
</div>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
<
|
|
104
|
+
|
|
105
|
+
<div class="dashboard-stats-grid" id="allGamesStats">
|
|
106
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read across all games">
|
|
107
|
+
<span class="dashboard-stat-value" id="allTotalChars">-</span>
|
|
108
|
+
<span class="dashboard-stat-label">Characters</span>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading across all games">
|
|
111
|
+
<span class="dashboard-stat-value" id="allTotalTime">-</span>
|
|
112
|
+
<span class="dashboard-stat-label">Time Spent</span>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Overall average reading speed">
|
|
115
|
+
<span class="dashboard-stat-value" id="allReadingSpeed">-</span>
|
|
116
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
|
128
117
|
</div>
|
|
129
|
-
<div class="dashboard-
|
|
130
|
-
<
|
|
131
|
-
<
|
|
118
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
|
|
119
|
+
<span class="dashboard-stat-value" id="allSessions">-</span>
|
|
120
|
+
<span class="dashboard-stat-label">Sessions</span>
|
|
132
121
|
</div>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div class="dashboard-progress-section">
|
|
125
|
+
<div class="dashboard-progress-title">Overall Progress</div>
|
|
126
|
+
<div class="dashboard-progress-items">
|
|
127
|
+
<div class="dashboard-progress-item">
|
|
128
|
+
<div class="dashboard-progress-value positive" id="allMonthlyChars">-</div>
|
|
129
|
+
<div class="dashboard-progress-label">Monthly Characters</div>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="dashboard-progress-item">
|
|
132
|
+
<div class="dashboard-progress-value neutral" id="allUniqueGames">-</div>
|
|
133
|
+
<div class="dashboard-progress-label">Games Played</div>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="dashboard-progress-item">
|
|
136
|
+
<div class="dashboard-progress-value neutral" id="allTotalSentences">-</div>
|
|
137
|
+
<div class="dashboard-progress-label">Total Sentences</div>
|
|
138
|
+
</div>
|
|
136
139
|
</div>
|
|
137
140
|
</div>
|
|
138
141
|
</div>
|
|
139
142
|
</div>
|
|
140
|
-
</div>
|
|
141
143
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
<!-- Loading/Error states for dashboard -->
|
|
145
|
+
<div class="dashboard-loading" id="dashboardLoading" style="display: none;">
|
|
146
|
+
<div class="spinner"></div>
|
|
147
|
+
<span>Loading dashboard statistics...</span>
|
|
148
|
+
</div>
|
|
147
149
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
<div class="dashboard-error" id="dashboardError" style="display: none;">
|
|
151
|
+
<div class="dashboard-error-icon">⚠️</div>
|
|
152
|
+
<div class="dashboard-error-message">Failed to load dashboard statistics</div>
|
|
153
|
+
<button class="dashboard-retry-btn" data-action="loadDashboardData">Retry</button>
|
|
154
|
+
</div>
|
|
153
155
|
|
|
154
156
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
</div>
|
|
164
|
-
<div class="dashboard-stats-grid" id="todayStats">
|
|
165
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
|
|
166
|
-
<span class="dashboard-stat-value" id="todayTotalHours">-</span>
|
|
167
|
-
<span class="dashboard-stat-label">Hours Spent</span>
|
|
168
|
-
</div>
|
|
169
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
|
|
170
|
-
<span class="dashboard-stat-value" id="todayTotalChars">-</span>
|
|
171
|
-
<span class="dashboard-stat-label">Characters</span>
|
|
172
|
-
</div>
|
|
173
|
-
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
|
|
174
|
-
<span class="dashboard-stat-value" id="todaySessions">-</span>
|
|
175
|
-
<span class="dashboard-stat-label">Sessions</span>
|
|
157
|
+
<!-- Today's Overview Card -->
|
|
158
|
+
<div class="dashboard-card today-overview" id="todayOverviewCard" style="margin-bottom: 24px;">
|
|
159
|
+
<div class="dashboard-card-header">
|
|
160
|
+
<h3 class="dashboard-card-title">
|
|
161
|
+
<span class="dashboard-card-icon">📅</span>
|
|
162
|
+
Today's Overview
|
|
163
|
+
</h3>
|
|
164
|
+
<p class="dashboard-card-subtitle" id="todayDate">Loading...</p>
|
|
176
165
|
</div>
|
|
177
|
-
<div class="dashboard-
|
|
178
|
-
<
|
|
179
|
-
|
|
166
|
+
<div class="dashboard-stats-grid" id="todayStats">
|
|
167
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
|
|
168
|
+
<span class="dashboard-stat-value" id="todayTotalHours">-</span>
|
|
169
|
+
<span class="dashboard-stat-label">Hours Spent</span>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
|
|
172
|
+
<span class="dashboard-stat-value" id="todayTotalChars">-</span>
|
|
173
|
+
<span class="dashboard-stat-label">Characters</span>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
|
|
176
|
+
<span class="dashboard-stat-value" id="todaySessions">-</span>
|
|
177
|
+
<span class="dashboard-stat-label">Sessions</span>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed today">
|
|
180
|
+
<span class="dashboard-stat-value" id="todayCharsPerHour">-</span>
|
|
181
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
|
182
|
+
</div>
|
|
180
183
|
</div>
|
|
181
184
|
</div>
|
|
182
|
-
</div>
|
|
183
185
|
|
|
184
186
|
<!-- Goal Progress Chart -->
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
<div class="dashboard-card goal-progress-chart" id="goalProgressChart" style="margin-bottom: 30px;">
|
|
188
|
+
<div class="dashboard-card-header">
|
|
189
|
+
<h3 class="dashboard-card-title">
|
|
190
|
+
<span class="dashboard-card-icon">🎯</span>
|
|
191
|
+
Goal Progress Chart
|
|
192
|
+
</h3>
|
|
193
|
+
<p class="dashboard-card-subtitle">Track your reading goals and projected completion dates</p>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<div class="goal-progress-grid">
|
|
197
|
+
<!-- Reading Hours Goal -->
|
|
198
|
+
<div class="goal-progress-item">
|
|
199
|
+
<div class="goal-progress-header">
|
|
200
|
+
<div class="goal-progress-label">
|
|
201
|
+
<span class="goal-icon">⏱️</span>
|
|
202
|
+
Reading Hours
|
|
203
|
+
</div>
|
|
204
|
+
<div class="goal-progress-values">
|
|
205
|
+
<span class="goal-current" id="goalHoursCurrent">-</span>
|
|
206
|
+
<span class="goal-separator">/</span>
|
|
207
|
+
<span class="goal-target" id="goalHoursTarget">-</span>
|
|
208
|
+
</div>
|
|
201
209
|
</div>
|
|
202
|
-
<div class="goal-progress-
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
<div class="goal-progress-bar">
|
|
211
|
+
<div class="goal-progress-fill" id="goalHoursProgress" data-percentage="0"></div>
|
|
212
|
+
</div>
|
|
213
|
+
<div class="goal-progress-info">
|
|
214
|
+
<span class="goal-percentage" id="goalHoursPercentage">0%</span>
|
|
215
|
+
<span class="goal-projection" id="goalHoursProjection">-</span>
|
|
206
216
|
</div>
|
|
207
217
|
</div>
|
|
208
|
-
<div class="goal-progress-bar">
|
|
209
|
-
<div class="goal-progress-fill" id="goalHoursProgress" data-percentage="0"></div>
|
|
210
|
-
</div>
|
|
211
|
-
<div class="goal-progress-info">
|
|
212
|
-
<span class="goal-percentage" id="goalHoursPercentage">0%</span>
|
|
213
|
-
<span class="goal-projection" id="goalHoursProjection">-</span>
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
216
218
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
219
|
+
<!-- Character Count Goal -->
|
|
220
|
+
<div class="goal-progress-item">
|
|
221
|
+
<div class="goal-progress-header">
|
|
222
|
+
<div class="goal-progress-label">
|
|
223
|
+
<span class="goal-icon">📖</span>
|
|
224
|
+
Characters Read
|
|
225
|
+
</div>
|
|
226
|
+
<div class="goal-progress-values">
|
|
227
|
+
<span class="goal-current" id="goalCharsCurrent">-</span>
|
|
228
|
+
<span class="goal-separator">/</span>
|
|
229
|
+
<span class="goal-target" id="goalCharsTarget">-</span>
|
|
230
|
+
</div>
|
|
223
231
|
</div>
|
|
224
|
-
<div class="goal-progress-
|
|
225
|
-
<
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
<div class="goal-progress-bar">
|
|
233
|
+
<div class="goal-progress-fill" id="goalCharsProgress" data-percentage="0"></div>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="goal-progress-info">
|
|
236
|
+
<span class="goal-percentage" id="goalCharsPercentage">0%</span>
|
|
237
|
+
<span class="goal-projection" id="goalCharsProjection">-</span>
|
|
228
238
|
</div>
|
|
229
239
|
</div>
|
|
230
|
-
<div class="goal-progress-bar">
|
|
231
|
-
<div class="goal-progress-fill" id="goalCharsProgress" data-percentage="0"></div>
|
|
232
|
-
</div>
|
|
233
|
-
<div class="goal-progress-info">
|
|
234
|
-
<span class="goal-percentage" id="goalCharsPercentage">0%</span>
|
|
235
|
-
<span class="goal-projection" id="goalCharsProjection">-</span>
|
|
236
|
-
</div>
|
|
237
|
-
</div>
|
|
238
240
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
<!-- Games Goal -->
|
|
242
|
+
<div class="goal-progress-item">
|
|
243
|
+
<div class="goal-progress-header">
|
|
244
|
+
<div class="goal-progress-label">
|
|
245
|
+
<span class="goal-icon">🎮</span>
|
|
246
|
+
Games
|
|
247
|
+
</div>
|
|
248
|
+
<div class="goal-progress-values">
|
|
249
|
+
<span class="goal-current" id="goalGamesCurrent">-</span>
|
|
250
|
+
<span class="goal-separator">/</span>
|
|
251
|
+
<span class="goal-target" id="goalGamesTarget">-</span>
|
|
252
|
+
</div>
|
|
245
253
|
</div>
|
|
246
|
-
<div class="goal-progress-
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
<div class="goal-progress-bar">
|
|
255
|
+
<div class="goal-progress-fill" id="goalGamesProgress" data-percentage="0"></div>
|
|
256
|
+
</div>
|
|
257
|
+
<div class="goal-progress-info">
|
|
258
|
+
<span class="goal-percentage" id="goalGamesPercentage">0%</span>
|
|
259
|
+
<span class="goal-projection" id="goalGamesProjection">-</span>
|
|
250
260
|
</div>
|
|
251
|
-
</div>
|
|
252
|
-
<div class="goal-progress-bar">
|
|
253
|
-
<div class="goal-progress-fill" id="goalGamesProgress" data-percentage="0"></div>
|
|
254
|
-
</div>
|
|
255
|
-
<div class="goal-progress-info">
|
|
256
|
-
<span class="goal-percentage" id="goalGamesPercentage">0%</span>
|
|
257
|
-
<span class="goal-projection" id="goalGamesProjection">-</span>
|
|
258
261
|
</div>
|
|
259
262
|
</div>
|
|
260
|
-
</div>
|
|
261
263
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
<!-- Loading/Error states -->
|
|
265
|
+
<div class="goal-progress-loading" id="goalProgressLoading" style="display: none;">
|
|
266
|
+
<div class="spinner"></div>
|
|
267
|
+
<span>Loading goal progress...</span>
|
|
268
|
+
</div>
|
|
267
269
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
<div class="goal-progress-error" id="goalProgressError" style="display: none;">
|
|
271
|
+
<div class="goal-progress-error-icon">⚠️</div>
|
|
272
|
+
<div class="goal-progress-error-message">Failed to load goal progress</div>
|
|
273
|
+
<button class="retry-btn" onclick="loadGoalProgress()">Retry</button>
|
|
274
|
+
</div>
|
|
272
275
|
</div>
|
|
273
|
-
</div>
|
|
274
|
-
|
|
275
|
-
<div class="chart-container">
|
|
276
|
-
<h2>Activity Heatmap</h2>
|
|
277
|
-
<div id="heatmapContainer"></div>
|
|
278
|
-
</div>
|
|
279
|
-
|
|
280
|
-
<div class="chart-container">
|
|
281
|
-
<h2>Lines Received Over Time</h2>
|
|
282
|
-
<canvas id="linesChart"></canvas>
|
|
283
|
-
</div>
|
|
284
276
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
277
|
+
<div class="chart-container">
|
|
278
|
+
<h2>Activity Heatmap</h2>
|
|
279
|
+
<div id="heatmapContainer"></div>
|
|
280
|
+
</div>
|
|
289
281
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
282
|
+
<div class="chart-container">
|
|
283
|
+
<h2>Lines Received Over Time</h2>
|
|
284
|
+
<canvas id="linesChart"></canvas>
|
|
285
|
+
</div>
|
|
294
286
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
287
|
+
<div class="chart-container">
|
|
288
|
+
<h2>Characters Read Over Time</h2>
|
|
289
|
+
<canvas id="charsChart"></canvas>
|
|
290
|
+
</div>
|
|
299
291
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
292
|
+
<div class="chart-container">
|
|
293
|
+
<h2>Reading Chars Quantity</h2>
|
|
294
|
+
<canvas id="readingCharsChart"></canvas>
|
|
295
|
+
</div>
|
|
304
296
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
<div id="kanjiCounter" class="kanji-counter">
|
|
309
|
-
Unique Kanji Seen: <span id="kanjiCount">0</span>
|
|
310
|
-
</div>
|
|
311
|
-
<div id="kanjiGrid" class="kanji-grid"></div>
|
|
312
|
-
<div class="kanji-legend">
|
|
313
|
-
<span>Rarely Seen</span>
|
|
314
|
-
<div class="kanji-legend-item" style="background-color: #ebedf0;" title="No encounters"></div>
|
|
315
|
-
<div class="kanji-legend-item" style="background-color: #e6342e;" title="Seen once"></div>
|
|
316
|
-
<div class="kanji-legend-item" style="background-color: #e6dc2e;" title="Occasionally seen"></div>
|
|
317
|
-
<div class="kanji-legend-item" style="background-color: #3be62f;" title="Frequently seen"></div>
|
|
318
|
-
<div class="kanji-legend-item" style="background-color: #2ee6e0;" title="Most frequently seen"></div>
|
|
319
|
-
<span>Frequently Seen</span>
|
|
320
|
-
</div>
|
|
297
|
+
<div class="chart-container">
|
|
298
|
+
<h2>Reading Time Quantity</h2>
|
|
299
|
+
<canvas id="readingTimeChart"></canvas>
|
|
321
300
|
</div>
|
|
322
|
-
</div>
|
|
323
301
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<h3>Statistics Settings</h3>
|
|
329
|
-
<span class="close-btn" id="closeSettingsModal">×</span>
|
|
330
|
-
</div>
|
|
331
|
-
<div class="modal-body">
|
|
332
|
-
<p style="color: var(--text-secondary); margin-bottom: 20px;">
|
|
333
|
-
Configure how reading time and sessions are calculated for your statistics.
|
|
334
|
-
</p>
|
|
335
|
-
|
|
336
|
-
<form id="settingsForm">
|
|
337
|
-
<div style="margin-bottom: 20px;">
|
|
338
|
-
<label for="afkTimer" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
339
|
-
AFK Timer (seconds)
|
|
340
|
-
</label>
|
|
341
|
-
<input
|
|
342
|
-
type="number"
|
|
343
|
-
id="afkTimer"
|
|
344
|
-
name="afk_timer_seconds"
|
|
345
|
-
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
346
|
-
placeholder="120"
|
|
347
|
-
>
|
|
348
|
-
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
349
|
-
Maximum time between activities that still counts as active reading
|
|
350
|
-
</small>
|
|
351
|
-
</div>
|
|
352
|
-
|
|
353
|
-
<div style="margin-bottom: 20px;">
|
|
354
|
-
<label for="sessionGap" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
355
|
-
Session Gap (seconds)
|
|
356
|
-
</label>
|
|
357
|
-
<input
|
|
358
|
-
type="number"
|
|
359
|
-
id="sessionGap"
|
|
360
|
-
name="session_gap_seconds"
|
|
361
|
-
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
362
|
-
placeholder="3600"
|
|
363
|
-
>
|
|
364
|
-
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
365
|
-
Time gap that triggers a new reading session
|
|
366
|
-
</small>
|
|
367
|
-
</div>
|
|
302
|
+
<div class="chart-container">
|
|
303
|
+
<h2>Reading Speed Improvement</h2>
|
|
304
|
+
<canvas id="readingSpeedPerGameChart"></canvas>
|
|
305
|
+
</div>
|
|
368
306
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
307
|
+
<div class="chart-container">
|
|
308
|
+
<h2>Kanji Grid</h2>
|
|
309
|
+
<div id="kanjiGridContainer">
|
|
310
|
+
<div id="kanjiCounter" class="kanji-counter">
|
|
311
|
+
Unique Kanji Seen: <span id="kanjiCount">0</span>
|
|
312
|
+
</div>
|
|
313
|
+
<div id="kanjiGrid" class="kanji-grid"></div>
|
|
314
|
+
<div class="kanji-legend">
|
|
315
|
+
<span>Rarely Seen</span>
|
|
316
|
+
<div class="kanji-legend-item" style="background-color: #ebedf0;" title="No encounters"></div>
|
|
317
|
+
<div class="kanji-legend-item" style="background-color: #e6342e;" title="Seen once"></div>
|
|
318
|
+
<div class="kanji-legend-item" style="background-color: #e6dc2e;" title="Occasionally seen"></div>
|
|
319
|
+
<div class="kanji-legend-item" style="background-color: #3be62f;" title="Frequently seen"></div>
|
|
320
|
+
<div class="kanji-legend-item" style="background-color: #2ee6e0;" title="Most frequently seen">
|
|
383
321
|
</div>
|
|
322
|
+
<span>Frequently Seen</span>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
384
326
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
327
|
+
<!-- Settings Modal -->
|
|
328
|
+
<div id="settingsModal" class="modal">
|
|
329
|
+
<div class="modal-content">
|
|
330
|
+
<div class="modal-header">
|
|
331
|
+
<h3>Statistics Settings</h3>
|
|
332
|
+
<span class="close-btn" id="closeSettingsModal">×</span>
|
|
333
|
+
</div>
|
|
334
|
+
<div class="modal-body">
|
|
335
|
+
<p style="color: var(--text-secondary); margin-bottom: 20px;">
|
|
336
|
+
Configure how reading time and sessions are calculated for your statistics.
|
|
337
|
+
</p>
|
|
338
|
+
<form id="settingsForm">
|
|
339
|
+
<!-- <div style="margin-bottom: 20px;">
|
|
340
|
+
<label for="timezone-select"
|
|
341
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
342
|
+
Timezone
|
|
343
|
+
</label>
|
|
344
|
+
<div style="display: flex; gap: 8px;">
|
|
345
|
+
<select id="timezone-select" name="timezone"
|
|
346
|
+
style="flex-grow: 1; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
|
|
347
|
+
</select>
|
|
348
|
+
<button id="set-local-timezone-btn"
|
|
349
|
+
style="padding: 10px; border: none; border-radius: 5px; background: var(--primary-color); color: white; font-size: 14px; cursor: pointer;">
|
|
350
|
+
Set to Local
|
|
351
|
+
</button>
|
|
352
|
+
</div>
|
|
353
|
+
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
354
|
+
Select the timezone to base your statistics on
|
|
355
|
+
</small>
|
|
356
|
+
</div> -->
|
|
403
357
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
</label>
|
|
409
|
-
<p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 14px;">
|
|
410
|
-
Set your long-term reading targets for tracking progress and projections.
|
|
411
|
-
</p>
|
|
412
|
-
|
|
413
|
-
<div style="margin-bottom: 15px;">
|
|
414
|
-
<label for="readingHoursTarget" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
415
|
-
Reading Hours Target
|
|
358
|
+
<div style="margin-bottom: 20px;">
|
|
359
|
+
<label for="afkTimer"
|
|
360
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
361
|
+
AFK Timer (seconds)
|
|
416
362
|
</label>
|
|
417
|
-
<input
|
|
418
|
-
type="number"
|
|
419
|
-
id="readingHoursTarget"
|
|
420
|
-
name="reading_hours_target"
|
|
421
|
-
min="1"
|
|
422
|
-
max="10000"
|
|
363
|
+
<input type="number" id="afkTimer" name="afk_timer_seconds"
|
|
423
364
|
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
424
|
-
placeholder="
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
365
|
+
placeholder="120">
|
|
366
|
+
<small
|
|
367
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
368
|
+
Maximum time between activities that still counts as active reading
|
|
428
369
|
</small>
|
|
429
370
|
</div>
|
|
430
|
-
|
|
431
|
-
<div style="margin-bottom:
|
|
432
|
-
<label for="
|
|
433
|
-
|
|
371
|
+
|
|
372
|
+
<div style="margin-bottom: 20px;">
|
|
373
|
+
<label for="sessionGap"
|
|
374
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
375
|
+
Session Gap (seconds)
|
|
434
376
|
</label>
|
|
435
|
-
<input
|
|
436
|
-
type="number"
|
|
437
|
-
id="characterCountTarget"
|
|
438
|
-
name="character_count_target"
|
|
439
|
-
min="1000"
|
|
440
|
-
max="1000000000"
|
|
377
|
+
<input type="number" id="sessionGap" name="session_gap_seconds"
|
|
441
378
|
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
442
|
-
placeholder="
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
379
|
+
placeholder="3600">
|
|
380
|
+
<small
|
|
381
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
382
|
+
Time gap that triggers a new reading session
|
|
446
383
|
</small>
|
|
447
384
|
</div>
|
|
448
|
-
|
|
449
|
-
<div style="margin-bottom:
|
|
450
|
-
<label for="
|
|
451
|
-
|
|
385
|
+
|
|
386
|
+
<div style="margin-bottom: 20px;">
|
|
387
|
+
<label for="heatmapYear"
|
|
388
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
389
|
+
Heatmap Display Year
|
|
452
390
|
</label>
|
|
453
|
-
<
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
placeholder="100"
|
|
461
|
-
>
|
|
462
|
-
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
463
|
-
Number of games/visual novels to complete (1-1,000) - Default: 100 based on Refold standards
|
|
391
|
+
<select id="heatmapYear" name="heatmap_year"
|
|
392
|
+
style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
|
|
393
|
+
<option value="all">All Years</option>
|
|
394
|
+
</select>
|
|
395
|
+
<small
|
|
396
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
397
|
+
Select which year to display in the reading activity heatmap
|
|
464
398
|
</small>
|
|
465
399
|
</div>
|
|
466
|
-
</div>
|
|
467
400
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
type="file"
|
|
476
|
-
id="exstaticFile"
|
|
477
|
-
accept=".csv"
|
|
401
|
+
<div style="margin-bottom: 20px;">
|
|
402
|
+
<label for="streakRequirement"
|
|
403
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
404
|
+
Streak Requirement (hours)
|
|
405
|
+
</label>
|
|
406
|
+
<input type="number" id="streakRequirement" name="streak_requirement_hours" min="0.01"
|
|
407
|
+
max="24" step="0.01"
|
|
478
408
|
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
479
|
-
|
|
480
|
-
<small
|
|
481
|
-
|
|
409
|
+
placeholder="1.0">
|
|
410
|
+
<small
|
|
411
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
412
|
+
Minimum hours of reading activity required to maintain streak (0.01-24 hours)
|
|
482
413
|
</small>
|
|
483
414
|
</div>
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
415
|
+
|
|
416
|
+
<!-- Reading Goals Section -->
|
|
417
|
+
<div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
|
|
418
|
+
<label
|
|
419
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
420
|
+
Reading Goals Configuration
|
|
421
|
+
</label>
|
|
422
|
+
<p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 14px;">
|
|
423
|
+
Set your long-term reading targets for tracking progress and projections.
|
|
424
|
+
</p>
|
|
425
|
+
|
|
426
|
+
<div style="margin-bottom: 15px;">
|
|
427
|
+
<label for="readingHoursTarget"
|
|
428
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
429
|
+
Reading Hours Target
|
|
430
|
+
</label>
|
|
431
|
+
<input type="number" id="readingHoursTarget" name="reading_hours_target" min="1"
|
|
432
|
+
max="10000"
|
|
433
|
+
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
434
|
+
placeholder="1500">
|
|
435
|
+
<small
|
|
436
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
437
|
+
Total reading hours goal (1-10,000 hours) - Default: 1500 hours based on TMW N1
|
|
438
|
+
achievement
|
|
439
|
+
</small>
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<div style="margin-bottom: 15px;">
|
|
443
|
+
<label for="characterCountTarget"
|
|
444
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
445
|
+
Character Count Target
|
|
446
|
+
</label>
|
|
447
|
+
<input type="number" id="characterCountTarget" name="character_count_target" min="1000"
|
|
448
|
+
max="1000000000"
|
|
449
|
+
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
450
|
+
placeholder="25000000">
|
|
451
|
+
<small
|
|
452
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
453
|
+
Total characters read goal (1,000-1,000,000,000) - Default: 25 million characters
|
|
454
|
+
</small>
|
|
496
455
|
</div>
|
|
456
|
+
|
|
457
|
+
<div style="margin-bottom: 15px;">
|
|
458
|
+
<label for="gamesTarget"
|
|
459
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
460
|
+
Games/Visual Novels Target
|
|
461
|
+
</label>
|
|
462
|
+
<input type="number" id="gamesTarget" name="games_target" min="1" max="1000"
|
|
463
|
+
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
|
464
|
+
placeholder="100">
|
|
465
|
+
<small
|
|
466
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
467
|
+
Number of games/visual novels to complete (1-1,000) - Default: 100 based on Refold
|
|
468
|
+
standards
|
|
469
|
+
</small>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
|
|
473
|
+
<!-- Import ExStatic Lines Section -->
|
|
474
|
+
<div style="margin-bottom: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
|
|
475
|
+
<label
|
|
476
|
+
style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
|
477
|
+
Import ExStatic Lines
|
|
478
|
+
</label>
|
|
479
|
+
<div style="margin-bottom: 10px;">
|
|
480
|
+
<input type="file" id="exstaticFile" accept=".csv"
|
|
481
|
+
style="width: 90%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;">
|
|
482
|
+
<small
|
|
483
|
+
style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
|
484
|
+
Select an ExStatic CSV file to import reading data into GSM
|
|
485
|
+
</small>
|
|
486
|
+
</div>
|
|
487
|
+
<button type="button" id="importExstaticBtn"
|
|
488
|
+
style="width: 90%; padding: 10px; background: #666; color: white; border: none; border-radius: 5px; font-size: 14px; cursor: not-allowed; margin-bottom: 10px;"
|
|
489
|
+
disabled>
|
|
490
|
+
Import ExStatic Lines
|
|
491
|
+
</button>
|
|
492
|
+
<div id="importProgress" style="display: none; margin-bottom: 10px;">
|
|
493
|
+
<div
|
|
494
|
+
style="background: var(--bg-tertiary); border-radius: 5px; overflow: hidden; height: 20px; position: relative;">
|
|
495
|
+
<div id="importProgressBar"
|
|
496
|
+
style="background: var(--primary-color); height: 100%; width: 0%; transition: width 0.3s ease;">
|
|
497
|
+
</div>
|
|
498
|
+
<span id="importProgressText"
|
|
499
|
+
style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 12px; color: var(--text-primary);">0%</span>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
<div id="importStatus"
|
|
503
|
+
style="display: none; padding: 10px; border-radius: 5px; font-size: 14px;"></div>
|
|
497
504
|
</div>
|
|
498
|
-
|
|
505
|
+
</form>
|
|
506
|
+
|
|
507
|
+
<div id="settingsError"
|
|
508
|
+
style="display: none; background: var(--danger-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
|
|
499
509
|
</div>
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
510
|
+
<div id="settingsSuccess"
|
|
511
|
+
style="display: none; background: var(--success-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;">
|
|
512
|
+
</div>
|
|
513
|
+
</div>
|
|
514
|
+
<div class="modal-footer">
|
|
515
|
+
<button id="cancelSettingsBtn" class="cancel-btn">Cancel</button>
|
|
516
|
+
<button id="saveSettingsBtn" class="confirm-delete-btn">Save Settings</button>
|
|
517
|
+
</div>
|
|
508
518
|
</div>
|
|
509
519
|
</div>
|
|
510
520
|
</div>
|
|
511
|
-
</div>
|
|
512
521
|
|
|
513
522
|
|
|
514
|
-
<!-- Include shared JavaScript first (required dependency for stats.js) -->
|
|
515
|
-
<script src="/static/js/shared.js"></script>
|
|
516
|
-
<script src="/static/js/kanji-grid.js"></script>
|
|
517
|
-
<script src="/static/js/stats.js"></script>
|
|
523
|
+
<!-- Include shared JavaScript first (required dependency for stats.js) -->
|
|
524
|
+
<script src="/static/js/shared.js"></script>
|
|
525
|
+
<script src="/static/js/kanji-grid.js"></script>
|
|
526
|
+
<script src="/static/js/stats.js"></script>
|
|
527
|
+
<!-- <script>
|
|
528
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
529
|
+
const timezoneSelect = document.getElementById('timezone-select');
|
|
530
|
+
const setLocalTimezoneBtn = document.getElementById('set-local-timezone-btn');
|
|
531
|
+
|
|
532
|
+
function populateTimezoneSelect() {
|
|
533
|
+
const timezones = Intl.supportedValuesOf('timeZone');
|
|
534
|
+
const fragment = document.createDocumentFragment();
|
|
535
|
+
|
|
536
|
+
timezones.forEach(tz => {
|
|
537
|
+
const option = document.createElement('option');
|
|
538
|
+
option.value = tz;
|
|
539
|
+
option.textContent = tz.replace(/_/g, ' '); // Improve readability
|
|
540
|
+
fragment.appendChild(option);
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
timezoneSelect.appendChild(fragment);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function setLocalTimezone() {
|
|
547
|
+
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
548
|
+
timezoneSelect.value = localTimezone;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
populateTimezoneSelect();
|
|
552
|
+
setLocalTimezone();
|
|
553
|
+
|
|
554
|
+
setLocalTimezoneBtn.addEventListener('click', () => {
|
|
555
|
+
setLocalTimezone();
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
</script> -->
|
|
518
559
|
|
|
519
560
|
</body>
|
|
561
|
+
|
|
520
562
|
</html>
|