Form filling from search result and unregitration

This commit is contained in:
Claude Brisson
2023-12-18 09:29:37 +01:00
parent 98192a1ebc
commit 47ceb8dbe7
7 changed files with 171 additions and 20 deletions

View File

@@ -74,7 +74,7 @@ class PlayerIndex {
.filter { !it.isEmpty() }
.map { "$it~" }
.joinToString(" ")
.let { if (it.isEmpty()) it else "$it ${it.substring(0, it.length - 1) + "*^5"}" }
.let { if (it.isEmpty()) it else "$it ${it.substring(0, it.length - 1) + "*^4"}" }
if (terms.isEmpty()) return emptyList()
logger.info("Search query: $terms")
val fuzzy = queryParser.parse(terms)

View File

@@ -50,11 +50,18 @@
/* registration section */
#player {
&.create .edition {
display: none;
&.create {
.edition {
display: none;
}
#unregister {
display: none;
}
}
&.edit .creation {
display: none;
&.edit {
.creation {
display: none;
}
}
}
@@ -117,9 +124,13 @@
}
.result-line {
cursor: pointer;
&:hover {
&:hover, &.highlighted {
background-color: rgba(100,200,255,200);
}
}
}
#player.popup {
min-width: 65vw;
}
}

View File

@@ -128,6 +128,27 @@ let api = {
.finally(() => {
spinner(false);
});
}
},
deleteJson: (path, body) => {
clearFeedback();
spinner(true);
return api.delete(path, body)
.then(resp => {
if (resp.ok) {
success();
return resp.json();
}
else throw resp;
})
.catch(err => {
error(err);
return 'error';
})
.finally(() => {
spinner(false);
});
}
};

View File

@@ -47,10 +47,15 @@ Element.prototype.toggleClass = function(className) {
return this;
}
NodeList.prototype.hasClass = function(className) {
console.log('nodelist.hasClass')
console.log(this.item(0));
return this.item(0).classList.contains(className);
}
Element.prototype.hasClass = function(className) {
this.classList.contains(className);
console.log('element.hasClass')
console.log(this.classList)
console.log(this.classList.contains(className))
return this.classList.contains(className);
}
Node.prototype.offset = function() {
let _x = 0;
@@ -142,3 +147,8 @@ Element.prototype.val = function(value) {
}
}
*/
NodeList.prototype.focus = function() {
let first = this.item(0);
if (first) first.focus();
}

View File

@@ -171,8 +171,57 @@ onLoad(() => {
$('body').removeClass('dimmed');
}
});
/* commented for now - do we want this?
$('#dimmer').on('click', e => $('.popup').removeClass('shown');
*/
// keyboard handling
document.on('keyup', e => {
switch (e.key) {
case 'Escape': {
if ($('#player').hasClass('shown')) {
if ($('#needle')[0].value) {
$('#needle')[0].value = '';
initSearch();
} else {
close_modal();
}
}
break;
}
case 'ArrowDown': {
if (searchResultShown()) {
let lines = $('.result-line');
if (typeof (searchHighlight) === 'undefined') searchHighlight = 0;
else ++searchHighlight;
searchHighlight = Math.min(searchHighlight, lines.length - 1);
lines.removeClass('highlighted');
lines[searchHighlight].addClass('highlighted');
}
break;
}
case 'ArrowUp': {
if (searchResultShown()) {
let lines = $('.result-line');
if (typeof (searchHighlight) === 'undefined') searchHighlight = 0;
else --searchHighlight;
searchHighlight = Math.max(searchHighlight, 0);
lines.removeClass('highlighted');
lines[searchHighlight].addClass('highlighted');
}
break;
}
case 'Enter': {
if (searchResultShown()) {
fillPlayer(searchResult[searchHighlight]);
} else {
$('#register')[0].click();
}
break;
}
}
});
});

View File

@@ -1,9 +1,11 @@
const SEARCH_DELAY = 100;
let searchTimer = undefined;
let resultTemplate;
let searchResult;
let searchHighlight;
function initSearch() {
let needle = $('#needle')[0].value;
let needle = $('#needle')[0].value.trim();
if (searchTimer) {
clearTimeout(searchTimer);
}
@@ -12,9 +14,12 @@ function initSearch() {
}, SEARCH_DELAY);
}
function searchResultShown() {
return !(typeof(searchHighlight) === 'undefined' || !searchResult || !searchResult.length || typeof(searchResult[searchHighlight]) === 'undefined')
}
function search(needle) {
needle = needle.trim();
console.log(needle)
if (needle && needle.length > 2) {
let form = $('#player-form')[0];
let search = {
@@ -32,17 +37,46 @@ function search(needle) {
ffg: search.ffg
};
store('searchFormState', searchFormState);
console.log(search)
api.postJson('search', search)
.then(result => {
if (Array.isArray(result)) {
console.log(result)
searchResult = result
let html = resultTemplate.render(result);
$('#search-result')[0].innerHTML = html;
} else console.log(result);
})
} else $('#search-result').clear();
} else {
$('#search-result').clear();
searchTimer = undefined;
searchResult = undefined;
searchHighlight = undefined;
}
}
function parseRank(rank) {
let groups = /(\d+)([kd])/.exec(rank)
if (groups) {
let level = parseInt(groups[1]);
let letter = groups[2];
switch (letter) {
case 'k': return -level;
case 'd': return level - 1;
}
}
return '';
}
function fillPlayer(player) {
let form = $('#player-form')[0];
form.val('name', player.name);
form.val('firstname', player.firstname);
form.val('country', player.country.toLowerCase());
form.val('club', player.club);
form.val('rank', parseRank(player.rank));
form.val('rating', player.rating);
$('#needle')[0].value = '';
initSearch();
$('#register').focus();
}
onLoad(() => {
@@ -60,10 +94,12 @@ onLoad(() => {
form.reset();
$('#player').removeClass('edit').addClass('create');
modal('player');
$('#needle').focus();
});
$('#cancel-register').on('click', e => {
e.preventDefault();
close_modal();
searchHighlight = undefined;
return false;
});
@@ -82,10 +118,13 @@ onLoad(() => {
}
}
if (!valid) return;
// $('#player-form')[0].requestSubmit() not working?!
$('#player-form')[0].dispatchEvent(new CustomEvent('submit', {cancelable: true}));
});
$('#player-form').on('submit', e => {
("submitting!!")
e.preventDefault();
let form = e.target;
let form = $('#player-form')[0];
let player = {
name: form.val('name'),
firstname: form.val('firstname'),
@@ -95,11 +134,10 @@ onLoad(() => {
club: form.val('club'),
skip: form.find('input.participation').map((input,i) => [i+1, input.checked]).filter(arr => !arr[1]).map(arr => arr[0])
}
console.log(player);
if (form.hasClass('add')) {
("ADDING")
api.postJson(`tour/${tour_id}/part`, player)
.then(player => {
console.log(player)
if (player !== 'error') {
window.location.reload();
}
@@ -109,7 +147,6 @@ onLoad(() => {
player['id'] = id;
api.putJson(`tour/${tour_id}/part/${id}`, player)
.then(player => {
console.log(player)
if (player !== 'error') {
window.location.reload();
}
@@ -158,4 +195,21 @@ onLoad(() => {
checkbox.checked = !checkbox.checked;
initSearch();
});
document.on('click', e => {
let resultLine = e.target.closest('.result-line');
if (resultLine) {
let index = e.target.closest('.result-line').data('index');
fillPlayer(searchResult[index]);
}
});
$('#unregister').on('click', e => {
let form = $('#player-form')[0];
let id = form.val('id');
api.deleteJson(`tour/${tour_id}/part/${id}`)
.then(ret => {
if (ret !== 'error') {
window.location.reload();
}
});
});
});

View File

@@ -150,12 +150,16 @@
</div>
</div>
<div class="popup-footer">
<button id="cancel-register" class="ui gray right labeled icon floating close button">
<button id="cancel-register" type="button" class="ui gray right labeled icon floating close button">
<i class="times icon"></i>
<span class="edition">Close</span>
<span class="creation">Cancel</span>
</button>
<button id="register" class="ui green right labeled icon floating button">
<button id="unregister" type="button" class="ui red right labeled icon floating button">
<i class="trash icon"></i>
Unregister
</button>
<button id="register" type="button" class="ui green right labeled icon floating button">
<i class="plus icon"></i>
<span class="edition">Update</span>
<span class="creation">Register</span>
@@ -164,9 +168,11 @@
</form>
</div>
</div>
#[[
<script id="result" type="text/template">
{{for #data}}
<div class="result-line">[{{:origin}}] {{:country}} {{:name}} {{:firstname}} {{:rank}} ({{:club}})</div>
<div class="result-line" data-index="{{:#getIndex()}}">[{{:origin}}] {{:country}} - {{:name}} {{:firstname}} {{:rank}} ({{:club}})</div>
{{/for}}
</script>
<script type="text/javascript" src="/lib/jsrender-1.0.13/jsrender.min.js"></script>
]]#