ui: Working flags
This commit is contained in:
parent
ef899ee99b
commit
1def2c97c1
8 changed files with 340 additions and 15 deletions
173
frontend/ui/src/components/FlagKey.svelte
Normal file
173
frontend/ui/src/components/FlagKey.svelte
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
<script>
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
Spinner,
|
||||
} from 'sveltestrap';
|
||||
|
||||
import { settings } from '../stores/settings.js';
|
||||
|
||||
export let refresh_my = null;
|
||||
export let exercice_id = 0;
|
||||
export let flag = { };
|
||||
export let value = "";
|
||||
let values = [""];
|
||||
|
||||
function waitChoices(i) {
|
||||
refresh_my((my) => {
|
||||
let haveChoices = false;
|
||||
|
||||
if (my && my.exercices[exercice_id].flags) {
|
||||
my.exercices[exercice_id].flags.forEach((f) => {
|
||||
if (f.id == flag.id && f.choices) {
|
||||
haveChoices = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (haveChoices) {
|
||||
wcsubmitted = false;
|
||||
} else if (i > 0) {
|
||||
setTimeout(waitChoices, 450, i-1);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let wcsubmitted = false;
|
||||
async function wantchoices() {
|
||||
wcsubmitted = true;
|
||||
|
||||
const response = await fetch(
|
||||
"/wantchoices/" + exercice_id,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({ id: Number(flag.id) }),
|
||||
}
|
||||
)
|
||||
|
||||
if (response.status < 300) {
|
||||
waitChoices(15);
|
||||
} else {
|
||||
wcsubmitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
function addItem() {
|
||||
values.push("");
|
||||
values = values;
|
||||
}
|
||||
|
||||
$: {
|
||||
let v = values.slice();
|
||||
|
||||
// Remove empty cells
|
||||
if (!flag.nb_lines) {
|
||||
for (let i = v.length - 1; i > 0; i--) {
|
||||
if (!v[i].length) {
|
||||
v.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort cells
|
||||
if (flag.ignore_order) {
|
||||
v = v.sort();
|
||||
}
|
||||
|
||||
value = v.join(flag.separator ? flag.separator : ',');
|
||||
if (flag.separator) {
|
||||
value += flag.separator;
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (flag.nb_lines) {
|
||||
while (values.length != flag.nb_lines) {
|
||||
if (values.length > flag.nb_lines) {
|
||||
values.pop();
|
||||
} else {
|
||||
values.push("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label for="sol_{flag.type}{flag.id}_0">{flag.label} :</label>
|
||||
{#if flag.found && flag.value}
|
||||
<span>{flag.value}</span>
|
||||
{/if}
|
||||
{#if !flag.found}
|
||||
{#each values as v, index}
|
||||
<div class="input-group" class:mt-1={index != 0}>
|
||||
{#if !flag.choices}
|
||||
{#if !flag.multiline}
|
||||
<input
|
||||
type="text"
|
||||
class="form-control flag"
|
||||
id="sol_{flag.type}{flag.id}_{index}"
|
||||
autocomplete="off"
|
||||
bind:value={values[index]}
|
||||
placeholder={flag.placeholder}
|
||||
title={flag.placeholder}
|
||||
>
|
||||
{:else}
|
||||
<textarea
|
||||
class="form-control flag"
|
||||
id="sol_{flag.type}{flag.id}_{index}"
|
||||
autocomplete="off"
|
||||
bind:value={values[index]}
|
||||
placeholder="{flag.placeholder}"
|
||||
title="{flag.placeholder}"
|
||||
></textarea>
|
||||
{/if}
|
||||
{:else}
|
||||
<select
|
||||
class="form-select"
|
||||
id="sol_{flag.type}{flag.id}_{index}"
|
||||
bind:value={values[index]}
|
||||
>
|
||||
{#each Object.keys(flag.choices) as l}
|
||||
<option value={l}>{flag.choices[l]}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{/if}
|
||||
{#if flag.choices_cost > 0}
|
||||
<Button
|
||||
color="success"
|
||||
type="button"
|
||||
on:click={wantchoices}
|
||||
disabled={wcsubmitted}
|
||||
title="Cliquez pour échanger ce champ de texte par une liste de choix. L'opération vous coûtera {flag.choices_cost * $settings.wchoiceCurrentCoefficient} points."
|
||||
>
|
||||
{#if wcsubmitted}
|
||||
<Spinner size="sm" class="me-2" />
|
||||
{/if}
|
||||
<Icon name="tasks" />
|
||||
Liste de propositions ({flag.choices_cost * $settings.wchoiceCurrentCoefficient} {flag.choices_cost * $settings.wchoiceCurrentCoefficient===1?"point":"points"})
|
||||
</Button>
|
||||
{:else if flag.separator && !flag.nb_lines && index == values.length - 1}
|
||||
<Button
|
||||
color="success"
|
||||
type="button"
|
||||
title="Ajouter un élément."
|
||||
on:click={addItem}
|
||||
>
|
||||
<Icon name="plus" />
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#if flag.help}
|
||||
<small class="form-text text-muted">{flag.help}</small>
|
||||
{/if}
|
||||
{:else}
|
||||
<Icon
|
||||
name="check"
|
||||
class="form-control-feedback text-success"
|
||||
aria-hidden="true"
|
||||
title="Flag trouvé à {flag.found}"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in a new issue