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

1{% extends 'base.html' %} 

2{% load i18n %} 

3{% load static %} 

4  

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 } 

25  

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 } 

35  

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 } 

42  

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 } 

53  

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 } 

60  

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 } 

66  

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 } 

77  

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 } 

84  

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 } 

91  

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 } 

99  

100 .select-option[data-selected="true"] .select-option-text { 

101 color: #fff !important; 

102 font-weight: 600 !important; 

103 } 

104  

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 %} 

114  

115{% block title %}{% trans 'Check e-mail or openid' %}{% endblock title %} 

116  

117{% block content %} 

118  

119<h1>{% trans 'Check e-mail or openid' %}</h1> 

120  

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 %} 

128  

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> 

227  

228 <div class="button-group"> 

229 <button type="submit" class="btn btn-primary">{% trans 'Check' %}</button> 

230 </div> 

231 </form> 

232 </div> 

233 </div> 

234  

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> 

241  

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> 

257  

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> 

276  

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 %} 

294  

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> 

327  

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 %} 

345  

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'); 

351  

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'); 

358  

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 = ''; 

366  

367 const textElement = opt.querySelector('.select-option-text'); 

368 if (textElement) { 

369 textElement.style.color = ''; 

370 textElement.style.fontWeight = ''; 

371 } 

372 }); 

373  

374 // Add selected class to clicked option 

375 this.classList.add('selected'); 

376 this.setAttribute('data-selected', 'true'); 

377  

378 // Update hidden input value 

379 hiddenInput.value = this.getAttribute('data-value'); 

380  

381 // Force a reflow to ensure CSS is applied immediately 

382 this.offsetHeight; 

383 }); 

384 }); 

385 }); 

386</script> 

387  

388{% endblock content %}