Skip to content

Commit 5ce1a32

Browse files
committed
Ability to configure auto bust and auto leg finish from frontend
1 parent 36ee2b3 commit 5ce1a32

File tree

10 files changed

+202
-36
lines changed

10 files changed

+202
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ A preview of major changes can be found in the Wiki ([Latest Changes](https://gi
88
- New "Explore" tab on player statistics, to explore darts thrown
99
- Support for `ANY` and `MASTER` outs for `x01` legs
1010
- Simplified input for `x01` legs
11-
- Ability to configure volume of announcer from frontend
11+
- Ability to configure: "Announcement Volume", "Auto Busting" and "Auto Leg Finish" from frontend
1212

1313
#### Changed
1414
- Updated to use `Node.js v18`

src/components/navbar/components/configure-kcapp-modal/configure-kcapp-modal.component.js

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ module.exports = {
44
onCreate(input) {
55
this.state = {
66
buttonLayout: "wide",
7-
volume: 100
7+
volume: 100,
8+
confirmBusts: true,
9+
autoFinishLegs: false,
10+
autoFinishTime: 10
811
}
912
},
1013
onMount() {
@@ -17,13 +20,40 @@ module.exports = {
1720
if (volume) {
1821
this.state.volume = Math.min(Math.max(parseInt(volume * 100), 0), 100);
1922
}
23+
24+
const confirmBusts = localStorage.get("confirm-busts");
25+
if (confirmBusts !== null) {
26+
this.state.confirmBusts = confirmBusts === 'true';
27+
}
28+
29+
const autoFinishLegs = localStorage.get("auto-finish-legs");
30+
if (autoFinishLegs !== null) {
31+
this.state.autoFinishLegs = autoFinishLegs === 'true';
32+
}
33+
34+
const autoFinishTime = localStorage.get("auto-finish-time");
35+
if (autoFinishTime !== null) {
36+
this.state.autoFinishTime = parseInt(autoFinishTime, 10) || 10;
37+
}
38+
},
39+
updateVolume(event, selected) {
40+
this.state.volume = selected.value;
41+
},
42+
toggleConfirmBusts(event) {
43+
this.state.confirmBusts = event.target.checked;
44+
},
45+
toggleAutoFinishLegs(event) {
46+
this.state.autoFinishLegs = event.target.checked;
47+
},
48+
updateAutoFinishTime(event) {
49+
this.state.autoFinishTime = parseInt(event.target.value, 10);
2050
},
2151
onSave() {
2252
this.state.buttonLayout = document.getElementById("buttonLayout").value;
2353
localStorage.set('button-layout', this.state.buttonLayout);
24-
},
25-
updateVolume(event, selected) {
26-
this.state.volume = selected.value;
54+
localStorage.set('confirm-busts', this.state.confirmBusts);
55+
localStorage.set('auto-finish-legs', this.state.autoFinishLegs);
56+
localStorage.set('auto-finish-time', this.state.autoFinishTime);
2757
localStorage.set('volume', this.state.volume / 100);
2858
},
2959
}

src/components/navbar/components/configure-kcapp-modal/configure-kcapp-modal.marko

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
</div>
1212
<div class="block-container-with-header">
1313
<div class="form-group form-check">
14-
<select id="buttonLayout" class="form-select" style="width: 100%" name="button-layout">
15-
<for|layout| of=[ "Wide", "Compact" ]>
16-
<option style="text-transform: capitalize;" value=layout.toLowerCase() selected=(layout.toLowerCase() === state.buttonLayout)>${layout}</option>
17-
</for>
18-
</select>
14+
<select id="buttonLayout" class="form-select" style="width: 100%" name="button-layout">
15+
<for|layout| of=[ "Wide", "Compact" ]>
16+
<option style="text-transform: capitalize;" value=layout.toLowerCase() selected=(layout.toLowerCase() === state.buttonLayout)>${layout}</option>
17+
</for>
18+
</select>
1919
</div>
2020
</div>
2121
</div>
@@ -30,11 +30,40 @@
3030
</div>
3131
</div>
3232
</div>
33+
<div>
34+
<div class="block-container-header">
35+
<span>Leg Options</span>
36+
</div>
37+
<div class="block-container-with-header" style="display: flex; align-items: center; min-height: 81px;">
38+
<div class="form-group form-check mr-2">
39+
<input type="checkbox" id="autoFinishLegs" class="form-check-input" checked=state.autoFinishLegs on-change("toggleAutoFinishLegs")>
40+
<label class="toggle-button" for="autoFinishLegs">
41+
<span class="toggle-slider"></span>
42+
</label>
43+
<span style="margin-left: 8px;">Auto Finish Legs</span>
44+
</div>
45+
<if(state.autoFinishLegs)>
46+
<div class="form-group" style="margin-left: 10px; margin-top: 5px; display: flex; align-items: center;">
47+
<input type="number" id="autoFinishTime" class="form-control" min="0" value=state.autoFinishTime on-input("updateAutoFinishTime") style="width: 70px; margin-right: 5px;">
48+
<span>seconds</span>
49+
</div>
50+
</if>
51+
</div>
52+
<div class="block-container-with-header" style="margin-top: -30px;">
53+
<div class="form-group form-check">
54+
<input type="checkbox" id="confirmBusts" class="form-check-input" checked=state.confirmBusts on-change("toggleConfirmBusts")>
55+
<label class="toggle-button" for="confirmBusts">
56+
<span class="toggle-slider"></span>
57+
</label>
58+
<span style="margin-left: 8px;">Confirm Busts?</span>
59+
</div>
60+
</div>
61+
</div>
3362
</div>
3463
<div class="modal-footer">
3564
<button class="btn btn-primary" type="button" on-click("onSave") data-dismiss="modal">Save</button>
3665
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
3766
</div>
3867
</div>
3968
</div>
40-
</div>
69+
</div>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
.block-container-header > span {
2+
font-weight: 700;
3+
}
4+
5+
.form-check-input {
6+
display: none;
7+
}
8+
9+
.toggle-button {
10+
width: 50px;
11+
height: 24px;
12+
background-color: #ccc;
13+
border-radius: 12px;
14+
position: relative;
15+
cursor: pointer;
16+
transition: background-color 0.3s;
17+
margin-bottom: -5px;
18+
}
19+
20+
.toggle-button .toggle-slider {
21+
position: absolute;
22+
top: 2px;
23+
left: 2px;
24+
width: 20px;
25+
height: 20px;
26+
background-color: white;
27+
border-radius: 50%;
28+
transition: transform 0.3s;
29+
}
30+
31+
.form-check-input:checked + .toggle-button {
32+
background-color: #4caf50;
33+
}
34+
35+
.form-check-input:checked + .toggle-button .toggle-slider {
36+
transform: translateX(26px);
37+
}
38+
39+
.block-container-with-header {
40+
display: flex;
41+
align-items: center;
42+
margin-bottom: 0px;
43+
margin-top: 0px;
44+
}
45+
46+
.form-group {
47+
margin-bottom: 0;
48+
}
49+
50+
.toggle-button {
51+
display: inline-block;
52+
}

src/components/scorecard-header/scorecard-header.marko

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
$ const types = require("../scorecard/components/match_types");
22

33
<td>
4-
<div style=`position: relative; opacity: ${state.player.lives !== null && state.player.lives <= 0 ? "35%" : "100%"};` class=(input.player.is_current_player ? "scorecard scorecard-active" : "scorecard scorecard-inactive")>
4+
<div style=`position: relative; opacity: ${state.player.lives !== null && state.player.lives <= 0 ? "35%" : "100%"};` class=`${(input.player.is_current_player ? "scorecard scorecard-active" : "scorecard scorecard-inactive")} scorecard-header`>
55
<if(state.player.player.board_stream_url)>
66
<i style="position: absolute; top: 5px; right: 5px; cursor: pointer;" class="fas fa-video fa-2x" title="Toggle Camera" on-click("toggleCamera")></i>
77
</if>

src/components/scorecard-header/scorecard-header.style.less

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/*@media (max-width: 1340px) {
2+
.scorecard-header {
3+
overflow: hidden;
4+
transform: scaleY(0.75);
5+
transform-origin: top left;
6+
margin-bottom: -40px !important;
7+
}
8+
9+
.label-player-name {
10+
font-size: 14pt;
11+
}
12+
13+
.label-player-score {
14+
font-size: 24pt;
15+
}
16+
}*/
17+
118
table {
219
width: 100%;
320
table-layout: fixed;
@@ -35,7 +52,7 @@ table {
3552
}
3653

3754
.label-player-name {
38-
font-size: 10pt;
55+
font-size: 18pt;
3956
padding: 0px;
4057
margin: 0px;
4158
color: #ffffff;
@@ -50,7 +67,7 @@ table {
5067
.label-player-score {
5168
font-weight: 700;
5269
padding: 10px 0px 0px 0px;
53-
font-size: 40pt;
70+
font-size: 32pt;
5471
}
5572

5673
.player-legs {

src/components/scorecard/components/x01.js

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const alertify = require("../../../util/alertify");
2+
const localStorage = require("../../../util/localstorage");
23
const types = require("./match_types");
34

45
exports.removeLast = function(dart, external) {
@@ -66,26 +67,27 @@ exports.confirmThrow = function (external) {
6667
const isBust = module.exports.isBust(this.state.player, dart, this.state.totalScore, this.state.leg);
6768
if (isCheckout) {
6869
submitting = true;
69-
alertify.confirm('Leg will be finished.',
70-
() => {
71-
this.emit('leg-finished', true);
72-
}, () => {
73-
this.removeLast();
74-
this.emit('leg-finished', false);
75-
});
76-
} else if (isBust) {
70+
}
71+
else if (isBust) {
7772
submitting = true;
7873
this.state.isBusted = true;
79-
alertify.confirm('Player busted',
80-
() => {
81-
alertify.success('Player busted');
82-
this.emit('player-busted', true);
83-
},
84-
() => {
85-
this.removeLast();
86-
this.state.isBusted = false;
87-
this.emit('player-busted', false);
88-
});
74+
const isConfirmBust = localStorage.getBool('confirm-busts');
75+
76+
if (isConfirmBust) {
77+
alertify.confirm('Player busted',
78+
() => {
79+
alertify.success('Player busted');
80+
this.emit('player-busted', true);
81+
},
82+
() => {
83+
this.removeLast();
84+
this.state.isBusted = false;
85+
this.emit('player-busted', false);
86+
});
87+
} else {
88+
alertify.success('Player busted');
89+
this.emit('player-busted', true);
90+
}
8991
}
9092
if (!this.state.player.player.options || this.state.player.player.options.subtract_per_dart) {
9193
this.state.player.current_score -= scored;
@@ -96,3 +98,4 @@ exports.confirmThrow = function (external) {
9698
}
9799
return submitting;
98100
}
101+

src/components/scorecard/scorecard.component.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const alertify = require("../../util/alertify");
2+
const localStorage = require("../../util/localstorage");
23

34
const x01 = require("./components/x01");
45
const shootout = require("./components/shootout");
@@ -253,12 +254,39 @@ module.exports = {
253254
},
254255

255256
confirmLegFinish() {
256-
alertify.confirm('Leg will be finished.',
257+
let countdown = localStorage.get('auto-finish-time') || 10;
258+
let confirmed = false;
259+
260+
const okFunction = () => {
261+
confirmed = true;
262+
this.emit('leg-finished', true);
263+
};
264+
265+
const confirmDialog = alertify.confirm(`Leg will be finished`,
266+
okFunction,
257267
() => {
258-
this.emit('leg-finished', true);
259-
}, () => {
260268
this.removeLast();
261269
this.emit('leg-finished', false);
270+
}
271+
);
272+
273+
const isAutoFinish = localStorage.getBool('auto-finish-legs');
274+
if (isAutoFinish) {
275+
confirmDialog.setContent(`Leg will be finished (<strong>${countdown}s</strong>)`);
276+
const countdownInterval = setInterval(() => {
277+
countdown--;
278+
confirmDialog.setContent(`Leg will be finished (<strong>${countdown}s</strong>)`);
279+
280+
if (countdown <= 0) {
281+
clearInterval(countdownInterval);
282+
if (!confirmed) {
283+
okFunction();
284+
}
285+
}
286+
}, 1000);
287+
confirmDialog.set('onclose', function() {
288+
clearInterval(countdownInterval);
262289
});
290+
}
263291
}
264292
};

src/util/alertify.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ exports.alert = (text, okFnc) => {
3232
.show();
3333
}
3434
exports.confirm = (text, okFnc, cancelFnc) => {
35-
bootstrap().confirm(text, okFnc, cancelFnc)
35+
return bootstrap().confirm(text, okFnc, cancelFnc)
3636
.setting({
3737
title: TITLE,
3838
defaultFocus: 'ok',

src/util/localstorage.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ function getKey(key) {
44

55
exports.get = key => localStorage.getItem(getKey(key));
66
exports.getInt = key => parseInt(localStorage.getItem(getKey(key)));
7+
exports.getBool = key => {
8+
const item = localStorage.getItem(getKey(key));
9+
if (!item) {
10+
return false;
11+
}
12+
return item === 'true';
13+
}
714
exports.set = (key, value) =>
815
localStorage.setItem(getKey(key), value);
916
exports.getKey = getKey;

0 commit comments

Comments
 (0)