Coverage for ivatar / tools / templates / check.html: 97%
378 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-23 00:08 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-23 00:08 +0000
1{% extends 'base.html' %}
2{% load i18n %}
3{% load static %}
5{% block header %}
6<style>
7 /* Base tile styles - highest specificity */
8 .custom-select-grid .select-option,
9 .form-group .custom-select-grid .select-option,
10 div.custom-select-grid div.select-option {
11 transition: all 0.3s ease !important;
12 cursor: pointer !important;
13 border: 2px solid #dee2e6 !important;
14 background-color: #fff !important;
15 color: #333 !important;
16 padding: 1rem !important;
17 border-radius: 12px !important;
18 display: flex !important;
19 flex-direction: column !important;
20 align-items: center !important;
21 gap: 0.75rem !important;
22 min-height: 100px !important;
23 justify-content: center !important;
24 }
26 /* Hover state for non-selected tiles */
27 .custom-select-grid .select-option:hover:not(.selected),
28 .form-group .custom-select-grid .select-option:hover:not(.selected),
29 div.custom-select-grid div.select-option:hover:not(.selected) {
30 border-color: #335ecf !important;
31 background-color: #e8f0ff !important;
32 color: #335ecf !important;
33 transform: translateY(-2px) !important;
34 }
36 .custom-select-grid .select-option:hover:not(.selected) .select-option-text,
37 .form-group .custom-select-grid .select-option:hover:not(.selected) .select-option-text,
38 div.custom-select-grid div.select-option:hover:not(.selected) .select-option-text {
39 color: #335ecf !important;
40 font-weight: 500 !important;
41 }
43 /* Selected state - always takes priority */
44 .custom-select-grid .select-option.selected,
45 .form-group .custom-select-grid .select-option.selected,
46 div.custom-select-grid div.select-option.selected {
47 background-color: #335ecf !important;
48 border-color: #335ecf !important;
49 color: #fff !important;
50 box-shadow: 0 4px 16px rgba(51, 94, 207, 0.4) !important;
51 transform: translateY(-1px) !important;
52 }
54 .custom-select-grid .select-option.selected .select-option-text,
55 .form-group .custom-select-grid .select-option.selected .select-option-text,
56 div.custom-select-grid div.select-option.selected .select-option-text {
57 color: #fff !important;
58 font-weight: 600 !important;
59 }
61 .custom-select-grid .select-option.selected .select-option-preview,
62 .form-group .custom-select-grid .select-option.selected .select-option-preview,
63 div.custom-select-grid div.select-option.selected .select-option-preview {
64 border-color: rgba(255, 255, 255, 0.5) !important;
65 }
67 /* Selected state hover - slightly different shade */
68 .custom-select-grid .select-option.selected:hover,
69 .form-group .custom-select-grid .select-option.selected:hover,
70 div.custom-select-grid div.select-option.selected:hover {
71 background-color: #2a4bb8 !important;
72 border-color: #2a4bb8 !important;
73 color: #fff !important;
74 transform: translateY(-2px) !important;
75 box-shadow: 0 6px 20px rgba(51, 94, 207, 0.5) !important;
76 }
78 .custom-select-grid .select-option.selected:hover .select-option-text,
79 .form-group .custom-select-grid .select-option.selected:hover .select-option-text,
80 div.custom-select-grid div.select-option.selected:hover .select-option-text {
81 color: #fff !important;
82 font-weight: 600 !important;
83 }
85 /* Force all child elements in selected state */
86 .custom-select-grid .select-option.selected *,
87 .form-group .custom-select-grid .select-option.selected *,
88 div.custom-select-grid div.select-option.selected * {
89 color: #fff !important;
90 }
92 /* Ensure selected state persists even with inline styles */
93 .select-option[data-selected="true"] {
94 background-color: #335ecf !important;
95 border-color: #335ecf !important;
96 color: #fff !important;
97 box-shadow: 0 4px 16px rgba(51, 94, 207, 0.4) !important;
98 }
100 .select-option[data-selected="true"] .select-option-text {
101 color: #fff !important;
102 font-weight: 600 !important;
103 }
105 /* Override any potential theme conflicts */
106 body .select-option.selected,
107 html .select-option.selected {
108 background-color: #335ecf !important;
109 border-color: #335ecf !important;
110 color: #fff !important;
111 }
112</style>
113{% endblock header %}
115{% block title %}{% trans 'Check e-mail or openid' %}{% endblock title %}
117{% block content %}
119<h1>{% trans 'Check e-mail or openid' %}</h1>
121<div class="check-layout">
122 <div class="check-form-section">
123 {% if form.errors %}
124 {% for error in form.non_field_errors %}
125 <div class="alert alert-danger" role="alert">{{ error|escape }}</div>
126 {% endfor %}
127 {% endif %}
129 <div class="form-container">
130 <form method="post" name="check">
131 {% csrf_token %}
132 <div class="form-group">
133 <label for="id_mail" class="form-label">{% trans 'E-Mail' %}</label>
134 {% if form.mail.value %}
135 <input type="email" name="mail" maxlength="254" minlength="6" class="form-control"
136 placeholder="{% trans 'E-Mail' %}" value="{{ form.mail.value }}" id="id_mail">
137 {% else %}
138 <input type="email" name="mail" maxlength="254" minlength="6" class="form-control"
139 placeholder="{% trans 'E-Mail' %}" id="id_mail">
140 {% endif %}
141 </div>
142 <div class="form-group">
143 <label for="id_openid" class="form-label">{% trans 'OpenID' %}</label>
144 {% if form.openid.value %}
145 <input type="text" name="openid" maxlength="255" minlength="11" class="form-control"
146 placeholder="{% trans 'OpenID' %}" value="{{ form.openid.value }}" id="id_openid">
147 {% else %}
148 <input type="text" name="openid" maxlength="255" minlength="11" class="form-control"
149 placeholder="{% trans 'OpenID' %}" id="id_openid">
150 {% endif %}
151 </div>
152 <div class="form-group">
153 <label for="id_size" class="form-label">{% trans 'Size' %}</label>
154 {% if form.size.value %}
155 <input type="number" name="size" min="5" max="512" class="form-control" placeholder="{% trans 'Size' %}"
156 value="{{ form.size.value }}" required id="id_size">
157 {% else %}
158 <input type="number" name="size" min="5" max="512" class="form-control" placeholder="{% trans 'Size' %}"
159 value="100" required id="id_size">
160 {% endif %}
161 </div>
162 <div class="form-group">
163 <label for="id_default_url" class="form-label">{% trans 'Default URL or special keyword' %}</label>
164 {% if form.default_url.value %}
165 <input type="text" name="default_url" class="form-control" placeholder="{% trans 'Default' %}"
166 value="{{ form.default_url.value }}" id="id_default_url">
167 {% else %}
168 <input type="text" name="default_url" class="form-control" placeholder="{% trans 'Default' %}"
169 id="id_default_url">
170 {% endif %}
171 </div>
172 <div class="form-group">
173 <label class="form-label">{% trans 'Default (special keyword)' %}</label>
174 <input type="hidden" name="default_opt" id="id_default_opt"
175 value="{% if form.default_opt.value %}{{ form.default_opt.value }}{% endif %}">
176 <div class="custom-select-grid">
177 <div class="select-option {% if form.default_opt.value == 'retro' %}selected{% endif %}" data-value="retro">
178 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=retro&forcedefault=y" alt="Retro preview"
179 class="select-option-preview">
180 <span class="select-option-text">Retro (d=retro)</span>
181 </div>
182 <div class="select-option {% if form.default_opt.value == 'robohash' %}selected{% endif %}"
183 data-value="robohash">
184 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=robohash&forcedefault=y" alt="Roboter preview"
185 class="select-option-preview">
186 <span class="select-option-text">Roboter (d=robohash)</span>
187 </div>
188 <div class="select-option {% if form.default_opt.value == 'wavatar' %}selected{% endif %}"
189 data-value="wavatar">
190 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=wavatar&forcedefault=y" alt="Wavatar preview"
191 class="select-option-preview">
192 <span class="select-option-text">Wavatar (d=wavatar)</span>
193 </div>
194 <div class="select-option {% if form.default_opt.value == 'monsterid' %}selected{% endif %}"
195 data-value="monsterid">
196 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=monsterid&forcedefault=y" alt="Monster preview"
197 class="select-option-preview">
198 <span class="select-option-text">Monster (d=monsterid)</span>
199 </div>
200 <div class="select-option {% if form.default_opt.value == 'identicon' %}selected{% endif %}"
201 data-value="identicon">
202 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=identicon&forcedefault=y"
203 alt="Identicon preview" class="select-option-preview">
204 <span class="select-option-text">Identicon (d=identicon)</span>
205 </div>
206 <div class="select-option {% if form.default_opt.value == 'mm' %}selected{% endif %}" data-value="mm">
207 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=mm&forcedefault=y" alt="Mystery man preview"
208 class="select-option-preview">
209 <span class="select-option-text">Mystery man (d=mm)</span>
210 </div>
211 <div class="select-option {% if form.default_opt.value == 'mmng' %}selected{% endif %}" data-value="mmng">
212 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=mmng&forcedefault=y"
213 alt="Mystery man NG preview" class="select-option-preview">
214 <span class="select-option-text">Mystery man NG (d=mmng)</span>
215 </div>
216 <div class="select-option {% if form.default_opt.value == 'pagan' %}selected{% endif %}" data-value="pagan">
217 <img src="/avatar/05b393e2a6942f3796524d634dcd8c0d?s=32&d=pagan&forcedefault=y"
218 alt="Retro adventure character" class="select-option-preview">
219 <span class="select-option-text">Retro adventure character (d=pagan)</span>
220 </div>
221 <div class="select-option select-option-none {% if form.default_opt.value == 'none' %}selected{% endif %}"
222 data-value="none">
223 <span class="select-option-text">None</span>
224 </div>
225 </div>
226 </div>
228 <div class="button-group">
229 <button type="submit" class="btn btn-primary">{% trans 'Check' %}</button>
230 </div>
231 </form>
232 </div>
233 </div>
235 {% if mailurl or openidurl %}
236 <div class="check-results-section" id="avatar-results">
237 <h2>{% trans 'Avatar Preview Results' %}</h2>
238 <p class="results-description">
239 {% trans 'This is what the avatars will look like depending on the hash and protocol you use:' %}
240 </p>
242 <div class="hash-info">
243 {% if mail_hash %}
244 <div class="hash-display">
245 <strong>MD5 hash (mail):</strong> <code>{{ mail_hash }}</code>
246 </div>
247 <div class="hash-display">
248 <strong>SHA256 hash (mail):</strong> <code>{{ mail_hash256 }}</code>
249 </div>
250 {% endif %}
251 {% if openid_hash %}
252 <div class="hash-display">
253 <strong>SHA256 hash (OpenID):</strong> <code>{{ openid_hash }}</code>
254 </div>
255 {% endif %}
256 </div>
258 <div class="avatar-results">
259 {% if mailurl %}
260 <div class="avatar-panel">
261 <div class="panel-heading">
262 <h3 class="panel-title">
263 <span class="hash-type">MD5</span>
264 <span class="connection-icons">
265 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
266 <i class="fa-solid fa-at" title="mail: {{ form.mail.value }}"></i>
267 </span>
268 </h3>
269 </div>
270 <div class="panel-body">
271 <a href="{{ mailurl_secure }}" target="_blank">
272 <img src="{{ mailurl_secure }}" class="avatar-image" alt="MD5 Avatar">
273 </a>
274 </div>
275 </div>
277 <div class="avatar-panel">
278 <div class="panel-heading">
279 <h3 class="panel-title">
280 <span class="hash-type">SHA256</span>
281 <span class="connection-icons">
282 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
283 <i class="fa-solid fa-at" title="mail: {{ form.mail.value }}"></i>
284 </span>
285 </h3>
286 </div>
287 <div class="panel-body">
288 <a href="{{ mailurl_secure_256 }}" target="_blank">
289 <img src="{{ mailurl_secure_256 }}" class="avatar-image" alt="SHA256 Avatar">
290 </a>
291 </div>
292 </div>
293 {% endif %}
295 {% if openidurl %}
296 <div class="avatar-panel">
297 <div class="panel-heading">
298 <h3 class="panel-title">
299 <span class="hash-type">SHA256</span>
300 <span class="connection-icons">
301 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
302 <i class="fa-solid fa-openid" title="openid: {{ form.openid.value }}"></i>
303 </span>
304 </h3>
305 </div>
306 <div class="panel-body">
307 <a href="{{ openidurl_secure }}" target="_blank">
308 <img src="{{ openidurl_secure }}" class="avatar-image" alt="OpenID Avatar">
309 </a>
310 </div>
311 </div>
312 {% endif %}
313 </div>
314 </div>
315 {% else %}
316 <div class="check-results-placeholder">
317 <div class="placeholder-content">
318 <h3>{% trans 'Avatar Preview' %}</h3>
319 <p>{% trans 'Submit the form to see your avatar previews here.' %}</p>
320 <div class="placeholder-icon">
321 <i class="fa-solid fa-user-circle" style="font-size: 4rem; color: #ccc;"></i>
322 </div>
323 </div>
324 </div>
325 {% endif %}
326</div>
328{% if mailurl or openidurl %}
329<script>
330 // Auto-scroll to results on mobile after form submission
331 document.addEventListener('DOMContentLoaded', function () {
332 // Check if we're on mobile and have results
333 if (window.innerWidth <= 768 && document.getElementById('avatar-results')) {
334 // Small delay to ensure page is fully rendered
335 setTimeout(function () {
336 document.getElementById('avatar-results').scrollIntoView({
337 behavior: 'smooth',
338 block: 'start'
339 });
340 }, 100);
341 }
342 });
343</script>
344{% endif %}
346<script>
347 // Custom select box functionality
348 document.addEventListener('DOMContentLoaded', function () {
349 const selectOptions = document.querySelectorAll('.select-option');
350 const hiddenInput = document.getElementById('id_default_opt');
352 selectOptions.forEach(function (option) {
353 option.addEventListener('click', function () {
354 // Remove selected class from all options
355 selectOptions.forEach(function (opt) {
356 opt.classList.remove('selected');
357 opt.removeAttribute('data-selected');
359 // Clear any inline styles that might interfere with CSS
360 opt.style.backgroundColor = '';
361 opt.style.borderColor = '';
362 opt.style.color = '';
363 opt.style.fontWeight = '';
364 opt.style.transform = '';
365 opt.style.boxShadow = '';
367 const textElement = opt.querySelector('.select-option-text');
368 if (textElement) {
369 textElement.style.color = '';
370 textElement.style.fontWeight = '';
371 }
372 });
374 // Add selected class to clicked option
375 this.classList.add('selected');
376 this.setAttribute('data-selected', 'true');
378 // Update hidden input value
379 hiddenInput.value = this.getAttribute('data-value');
381 // Force a reflow to ensure CSS is applied immediately
382 this.offsetHeight;
383 });
384 });
385 });
386</script>
388{% endblock content %}