Coverage for ivatar / tools / templates / check.html: 97%
373 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:09 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:09 +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,
10div.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),
29div.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,
38div.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,
46div.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,
56div.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,
63div.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,
70div.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,
80div.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 *,
88div.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 */
106body .select-option.selected,
107html .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 select-option-none {% if form.default_opt.value == 'none' %}selected{% endif %}"
217 data-value="none">
218 <span class="select-option-text">None</span>
219 </div>
220 </div>
221 </div>
223 <div class="button-group">
224 <button type="submit" class="btn btn-primary">{% trans 'Check' %}</button>
225 </div>
226 </form>
227 </div>
228 </div>
230 {% if mailurl or openidurl %}
231 <div class="check-results-section" id="avatar-results">
232 <h2>{% trans 'Avatar Preview Results' %}</h2>
233 <p class="results-description">
234 {% trans 'This is what the avatars will look like depending on the hash and protocol you use:' %}
235 </p>
237 <div class="hash-info">
238 {% if mail_hash %}
239 <div class="hash-display">
240 <strong>MD5 hash (mail):</strong> <code>{{ mail_hash }}</code>
241 </div>
242 <div class="hash-display">
243 <strong>SHA256 hash (mail):</strong> <code>{{ mail_hash256 }}</code>
244 </div>
245 {% endif %}
246 {% if openid_hash %}
247 <div class="hash-display">
248 <strong>SHA256 hash (OpenID):</strong> <code>{{ openid_hash }}</code>
249 </div>
250 {% endif %}
251 </div>
253 <div class="avatar-results">
254 {% if mailurl %}
255 <div class="avatar-panel">
256 <div class="panel-heading">
257 <h3 class="panel-title">
258 <span class="hash-type">MD5</span>
259 <span class="connection-icons">
260 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
261 <i class="fa-solid fa-at" title="mail: {{ form.mail.value }}"></i>
262 </span>
263 </h3>
264 </div>
265 <div class="panel-body">
266 <a href="{{ mailurl_secure }}" target="_blank">
267 <img src="{{ mailurl_secure }}" class="avatar-image" alt="MD5 Avatar">
268 </a>
269 </div>
270 </div>
272 <div class="avatar-panel">
273 <div class="panel-heading">
274 <h3 class="panel-title">
275 <span class="hash-type">SHA256</span>
276 <span class="connection-icons">
277 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
278 <i class="fa-solid fa-at" title="mail: {{ form.mail.value }}"></i>
279 </span>
280 </h3>
281 </div>
282 <div class="panel-body">
283 <a href="{{ mailurl_secure_256 }}" target="_blank">
284 <img src="{{ mailurl_secure_256 }}" class="avatar-image" alt="SHA256 Avatar">
285 </a>
286 </div>
287 </div>
288 {% endif %}
290 {% if openidurl %}
291 <div class="avatar-panel">
292 <div class="panel-heading">
293 <h3 class="panel-title">
294 <span class="hash-type">SHA256</span>
295 <span class="connection-icons">
296 <i class="fa-solid fa-lock" title="Secure connection (https)"></i>
297 <i class="fa-solid fa-openid" title="openid: {{ form.openid.value }}"></i>
298 </span>
299 </h3>
300 </div>
301 <div class="panel-body">
302 <a href="{{ openidurl_secure }}" target="_blank">
303 <img src="{{ openidurl_secure }}" class="avatar-image" alt="OpenID Avatar">
304 </a>
305 </div>
306 </div>
307 {% endif %}
308 </div>
309 </div>
310 {% else %}
311 <div class="check-results-placeholder">
312 <div class="placeholder-content">
313 <h3>{% trans 'Avatar Preview' %}</h3>
314 <p>{% trans 'Submit the form to see your avatar previews here.' %}</p>
315 <div class="placeholder-icon">
316 <i class="fa-solid fa-user-circle" style="font-size: 4rem; color: #ccc;"></i>
317 </div>
318 </div>
319 </div>
320 {% endif %}
321</div>
323{% if mailurl or openidurl %}
324<script>
325 // Auto-scroll to results on mobile after form submission
326 document.addEventListener('DOMContentLoaded', function () {
327 // Check if we're on mobile and have results
328 if (window.innerWidth <= 768 && document.getElementById('avatar-results')) {
329 // Small delay to ensure page is fully rendered
330 setTimeout(function () {
331 document.getElementById('avatar-results').scrollIntoView({
332 behavior: 'smooth',
333 block: 'start'
334 });
335 }, 100);
336 }
337 });
338</script>
339{% endif %}
341<script>
342 // Custom select box functionality
343 document.addEventListener('DOMContentLoaded', function () {
344 const selectOptions = document.querySelectorAll('.select-option');
345 const hiddenInput = document.getElementById('id_default_opt');
347 selectOptions.forEach(function (option) {
348 option.addEventListener('click', function () {
349 // Remove selected class from all options
350 selectOptions.forEach(function (opt) {
351 opt.classList.remove('selected');
352 opt.removeAttribute('data-selected');
354 // Clear any inline styles that might interfere with CSS
355 opt.style.backgroundColor = '';
356 opt.style.borderColor = '';
357 opt.style.color = '';
358 opt.style.fontWeight = '';
359 opt.style.transform = '';
360 opt.style.boxShadow = '';
362 const textElement = opt.querySelector('.select-option-text');
363 if (textElement) {
364 textElement.style.color = '';
365 textElement.style.fontWeight = '';
366 }
367 });
369 // Add selected class to clicked option
370 this.classList.add('selected');
371 this.setAttribute('data-selected', 'true');
373 // Update hidden input value
374 hiddenInput.value = this.getAttribute('data-value');
376 // Force a reflow to ensure CSS is applied immediately
377 this.offsetHeight;
378 });
379 });
380 });
381</script>
383{% endblock content %}