svelte-migrate: updated files
This commit is contained in:
parent
ca12b3dde5
commit
3cf92b4798
37 changed files with 600 additions and 536 deletions
|
@ -16,6 +16,7 @@
|
||||||
import { blake2b } from 'hash-wasm';
|
import { blake2b } from 'hash-wasm';
|
||||||
|
|
||||||
import { my } from '../stores/my.js';
|
import { my } from '../stores/my.js';
|
||||||
|
import { teams } from '../stores/teams.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../stores/settings.js';
|
||||||
|
|
||||||
import DateFormat from './DateFormat.svelte';
|
import DateFormat from './DateFormat.svelte';
|
||||||
|
@ -25,14 +26,11 @@
|
||||||
export let exercice = { };
|
export let exercice = { };
|
||||||
export let flags = [];
|
export let flags = [];
|
||||||
|
|
||||||
export let refresh_my;
|
|
||||||
export let refresh_teams;
|
|
||||||
|
|
||||||
function waitDiff(i) {
|
function waitDiff(i) {
|
||||||
refresh_my((my) => {
|
my.refresh((my) => {
|
||||||
if (my && (my.exercices[exercice.id].tries != exercice.tries || my.exercices[exercice.id].solved_rank != exercice.solved_rank || my.exercices[exercice.id].solved_time != exercice.solved_time)) {
|
if (my && (my.exercices[exercice.id].tries != exercice.tries || my.exercices[exercice.id].solved_rank != exercice.solved_rank || my.exercices[exercice.id].solved_time != exercice.solved_time)) {
|
||||||
submitInProgress = false;
|
submitInProgress = false;
|
||||||
refresh_teams();
|
teams.refresh();
|
||||||
} else if (i > 0) {
|
} else if (i > 0) {
|
||||||
setTimeout(waitDiff, (12-i)*50+440, i-1);
|
setTimeout(waitDiff, (12-i)*50+440, i-1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,7 +206,6 @@
|
||||||
<FlagMCQ
|
<FlagMCQ
|
||||||
exercice_id={exercice.id}
|
exercice_id={exercice.id}
|
||||||
{flag}
|
{flag}
|
||||||
{refresh_my}
|
|
||||||
bind:values={responses.mcqs}
|
bind:values={responses.mcqs}
|
||||||
bind:justifications={responses.justifications}
|
bind:justifications={responses.justifications}
|
||||||
/>
|
/>
|
||||||
|
@ -216,7 +213,6 @@
|
||||||
<FlagKey
|
<FlagKey
|
||||||
exercice_id={exercice.id}
|
exercice_id={exercice.id}
|
||||||
{flag}
|
{flag}
|
||||||
{refresh_my}
|
|
||||||
bind:value={responses.flags[flag.id]}
|
bind:value={responses.flags[flag.id]}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
|
|
||||||
export let hints = [];
|
export let hints = [];
|
||||||
export let exercice = {};
|
export let exercice = {};
|
||||||
export let refresh_my = null;
|
|
||||||
|
|
||||||
let hints_submitted = {};
|
let hints_submitted = {};
|
||||||
|
|
||||||
function waitDiff(i, hint) {
|
function waitDiff(i, hint) {
|
||||||
refresh_my((my) => {
|
my.refresh((my) => {
|
||||||
let openedHint = false;
|
let openedHint = false;
|
||||||
|
|
||||||
if (my && my.exercices[exercice.id].hints) {
|
if (my && my.exercices[exercice.id].hints) {
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
|
|
||||||
|
import { my } from '../stores/my.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../stores/settings.js';
|
||||||
|
|
||||||
export let refresh_my = null;
|
|
||||||
export let exercice_id = 0;
|
export let exercice_id = 0;
|
||||||
export let flag = { };
|
export let flag = { };
|
||||||
export let value = "";
|
export let value = "";
|
||||||
let values = [""];
|
let values = [""];
|
||||||
|
|
||||||
function waitChoices(i) {
|
function waitChoices(i) {
|
||||||
refresh_my((my) => {
|
my.refresh((my) => {
|
||||||
let haveChoices = false;
|
let haveChoices = false;
|
||||||
|
|
||||||
if (my && my.exercices[exercice_id].flags) {
|
if (my && my.exercices[exercice_id].flags) {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import FlagKey from './FlagKey.svelte';
|
import FlagKey from './FlagKey.svelte';
|
||||||
|
|
||||||
export let refresh_my = null;
|
|
||||||
export let exercice_id = 0;
|
export let exercice_id = 0;
|
||||||
export let flag = { };
|
export let flag = { };
|
||||||
export let values = { };
|
export let values = { };
|
||||||
|
@ -36,7 +35,6 @@
|
||||||
<FlagKey
|
<FlagKey
|
||||||
{exercice_id}
|
{exercice_id}
|
||||||
flag={flag.choices[cid].justification}
|
flag={flag.choices[cid].justification}
|
||||||
{refresh_my}
|
|
||||||
bind:values={justifications[flag.choices[cid].justification.id]}
|
bind:values={justifications[flag.choices[cid].justification.id]}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -10,12 +10,10 @@
|
||||||
import { my } from '../stores/my.js';
|
import { my } from '../stores/my.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../stores/settings.js';
|
||||||
|
|
||||||
export let refresh_my;
|
|
||||||
|
|
||||||
let newTeamName = "";
|
let newTeamName = "";
|
||||||
|
|
||||||
function gotoHomeOnDiff(i) {
|
function gotoHomeOnDiff(i) {
|
||||||
refresh_my((my) => {
|
my.refresh((my) => {
|
||||||
if (my && my.name == newTeamName) {
|
if (my && my.name == newTeamName) {
|
||||||
newTeamName = "";
|
newTeamName = "";
|
||||||
messageClass = "info";
|
messageClass = "info";
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
export async function handle({ event, resolve }) {
|
|
||||||
const response = await resolve(event, {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
return response;
|
|
||||||
}
|
|
|
@ -1,15 +1,5 @@
|
||||||
<script context="module">
|
|
||||||
export function load({ error, status }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
title: `${status}: ${error.message}`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export let title;
|
import { page } from '$app/stores';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>{title}</h1>
|
<h1>{$page.status} : {$page.error.message}</h1>
|
||||||
|
|
21
frontend/ui/src/routes/+layout.js
Normal file
21
frontend/ui/src/routes/+layout.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { challengeInfo } from '../stores/challengeinfo.js';
|
||||||
|
import { issuesStore } from '../stores/issues.js';
|
||||||
|
import { my } from '../stores/my.js';
|
||||||
|
import { teamsStore } from '../stores/teams.js';
|
||||||
|
import { themesStore } from '../stores/themes.js';
|
||||||
|
import { settings, time } from '../stores/settings.js';
|
||||||
|
|
||||||
|
export const ssr = false;
|
||||||
|
|
||||||
|
export async function load() {
|
||||||
|
await challengeInfo.refresh();
|
||||||
|
await settings.refresh();
|
||||||
|
await themes.refresh();
|
||||||
|
teams.refresh();
|
||||||
|
my.refresh((my) => {
|
||||||
|
if (my && my.team_id === 0) {
|
||||||
|
stop_refresh = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
issues.refresh();
|
||||||
|
}
|
|
@ -1,137 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
import { challengeInfo } from '../stores/challengeinfo.js';
|
|
||||||
import { issuesStore } from '../stores/issues.js';
|
|
||||||
import { my } from '../stores/my.js';
|
|
||||||
import { teamsStore } from '../stores/teams.js';
|
|
||||||
import { themesStore } from '../stores/themes.js';
|
|
||||||
import { settings, time } from '../stores/settings.js';
|
|
||||||
|
|
||||||
let stop_refresh = false;
|
|
||||||
|
|
||||||
let refresh_interval_settings = null;
|
|
||||||
async function refresh_settings(cb=null, interval=null) {
|
|
||||||
if (refresh_interval_settings)
|
|
||||||
clearInterval(refresh_interval_settings);
|
|
||||||
if (interval === null) {
|
|
||||||
interval = Math.floor(Math.random() * 24000) + 32000;
|
|
||||||
}
|
|
||||||
if (stop_refresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh_interval_settings = setInterval(refresh_settings, interval);
|
|
||||||
|
|
||||||
if (!cb) {
|
|
||||||
// Before we start, update settings more frequently.
|
|
||||||
cb = function(stgs) {
|
|
||||||
const srv_cur = new Date(Date.now() + (stgs.currentTime - stgs.recvTime));
|
|
||||||
|
|
||||||
if (settings.start > srv_cur) {
|
|
||||||
const startIn = settings.start - srv_cur;
|
|
||||||
if (startIn > 15000) {
|
|
||||||
setTimeout(refresh_settings, Math.floor(Math.random() * 10000) + 2400)
|
|
||||||
} else if (startIn > 1500) {
|
|
||||||
setTimeout(refresh_settings, startIn - 1000 - Math.floor(Math.random() * 500))
|
|
||||||
} else {
|
|
||||||
// On scheduled start time, refresh my.json file
|
|
||||||
setTimeout(refresh_my, startIn + Math.floor(Math.random() * 200))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.update(await fetch('settings.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refresh_challengeInfo(cb=null) {
|
|
||||||
challengeInfo.update(await fetch('challenge.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
let refresh_interval_teams = null;
|
|
||||||
async function refresh_teams(cb=null, interval=null) {
|
|
||||||
if (refresh_interval_teams)
|
|
||||||
clearInterval(refresh_interval_teams);
|
|
||||||
if (interval === null) {
|
|
||||||
interval = Math.floor(Math.random() * 24000) + 32000;
|
|
||||||
}
|
|
||||||
if (stop_refresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh_interval_teams = setInterval(refresh_teams, interval);
|
|
||||||
|
|
||||||
teamsStore.update(await fetch('teams.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
let refresh_interval_themes = null;
|
|
||||||
async function refresh_themes(cb=null, interval=null) {
|
|
||||||
if (refresh_interval_themes)
|
|
||||||
clearInterval(refresh_interval_themes);
|
|
||||||
if (interval === null) {
|
|
||||||
interval = Math.floor(Math.random() * 24000) + 32000;
|
|
||||||
}
|
|
||||||
if (stop_refresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh_interval_themes = setInterval(refresh_themes, interval);
|
|
||||||
|
|
||||||
await themesStore.update(await fetch('themes.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
let refresh_interval_my = null;
|
|
||||||
async function refresh_my(cb=null, interval=null) {
|
|
||||||
if (refresh_interval_my)
|
|
||||||
clearInterval(refresh_interval_my);
|
|
||||||
if (interval === null) {
|
|
||||||
interval = Math.floor(Math.random() * 24000) + 24000;
|
|
||||||
}
|
|
||||||
if (stop_refresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh_interval_my = setInterval(refresh_my, interval);
|
|
||||||
|
|
||||||
my.update(await fetch('my.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
let refresh_interval_issues = null;
|
|
||||||
async function refresh_issues(cb=null, interval=null) {
|
|
||||||
if (refresh_interval_issues)
|
|
||||||
clearInterval(refresh_interval_issues);
|
|
||||||
if (interval === null) {
|
|
||||||
interval = Math.floor(Math.random() * 24000) + 32000;
|
|
||||||
}
|
|
||||||
if (stop_refresh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh_interval_issues = setInterval(refresh_issues, interval);
|
|
||||||
|
|
||||||
issuesStore.update(await fetch('issues.json', {headers: {'Accept': 'application/json'}}), cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function load({ stuff }) {
|
|
||||||
await refresh_challengeInfo();
|
|
||||||
await refresh_settings();
|
|
||||||
await refresh_themes();
|
|
||||||
refresh_teams();
|
|
||||||
refresh_my((my) => {
|
|
||||||
if (my && my.team_id === 0) {
|
|
||||||
stop_refresh = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
refresh_issues();
|
|
||||||
|
|
||||||
return {
|
|
||||||
stuff: {
|
|
||||||
...stuff,
|
|
||||||
refresh_challengeInfo,
|
|
||||||
refresh_settings,
|
|
||||||
refresh_teams,
|
|
||||||
refresh_themes,
|
|
||||||
refresh_my,
|
|
||||||
refresh_issues,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import '../fic.scss'
|
import '../fic.scss'
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||||
|
|
19
frontend/ui/src/routes/[theme]/+layout.js
Normal file
19
frontend/ui/src/routes/[theme]/+layout.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { get_store_value } from 'svelte/internal';
|
||||||
|
|
||||||
|
import { themes } from '../../stores/themes.js';
|
||||||
|
|
||||||
|
export async function load({ params }) {
|
||||||
|
const thms = get_store_value(themes);
|
||||||
|
|
||||||
|
let theme = null;
|
||||||
|
for (let th in thms) {
|
||||||
|
if (thms[th] && thms[th].urlid === params.theme) {
|
||||||
|
theme = thms[th];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
theme,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,30 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
import { get_store_value } from 'svelte/internal';
|
|
||||||
|
|
||||||
import { themes } from '../../stores/themes.js';
|
|
||||||
|
|
||||||
export async function load({ params, stuff }) {
|
|
||||||
const thms = get_store_value(themes);
|
|
||||||
|
|
||||||
let theme = null;
|
|
||||||
for (let th in thms) {
|
|
||||||
if (thms[th] && thms[th].urlid === params.theme) {
|
|
||||||
theme = thms[th];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
stuff: {
|
|
||||||
...stuff,
|
|
||||||
theme: theme,
|
|
||||||
}, props: {
|
|
||||||
theme: theme,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
|
|
7
frontend/ui/src/routes/[theme]/+page.js
Normal file
7
frontend/ui/src/routes/[theme]/+page.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export async function load({ parent }) {
|
||||||
|
const data = await parent();
|
||||||
|
|
||||||
|
return {
|
||||||
|
theme: data.theme,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,13 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
export async function load({ stuff }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
theme: stuff.theme,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -25,31 +15,31 @@
|
||||||
|
|
||||||
import { my } from '../../stores/my.js';
|
import { my } from '../../stores/my.js';
|
||||||
|
|
||||||
export let theme = null;
|
export let data;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if theme && theme.exercices}
|
{#if data.theme && data.theme.exercices}
|
||||||
<Card class="niceborder text-indent mt-2 mb-4">
|
<Card class="niceborder text-indent mt-2 mb-4">
|
||||||
|
|
||||||
<CardBody class="bg-dark text-light">
|
<CardBody class="bg-dark text-light">
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<p class="mt-4 mx-3 card-text lead text-justify">{@html theme.headline}</p>
|
<p class="mt-4 mx-3 card-text lead text-justify">{@html data.theme.headline}</p>
|
||||||
<p class="mb-4 mx-3 card-text text-justify">{@html theme.intro}</p>
|
<p class="mb-4 mx-3 card-text text-justify">{@html data.theme.intro}</p>
|
||||||
</Col>
|
</Col>
|
||||||
{#if theme.partner_txt || theme.partner_img || theme.partner_href}
|
{#if data.theme.partner_txt || data.theme.partner_img || data.theme.partner_href}
|
||||||
<Col md="2" lg="3" class="d-none d-md-block">
|
<Col md="2" lg="3" class="d-none d-md-block">
|
||||||
<Card class="pt-3 px-3">
|
<Card class="pt-3 px-3">
|
||||||
{#if theme.partner_img}
|
{#if data.theme.partner_img}
|
||||||
<img src="{theme.partner_img}" class="card-img-top">
|
<img src="{data.theme.partner_img}" class="card-img-top">
|
||||||
{/if}
|
{/if}
|
||||||
{#if theme.partner_txt || theme.partner_href}
|
{#if data.theme.partner_txt || data.theme.partner_href}
|
||||||
<CardBody class="p-0 mt-3">
|
<CardBody class="p-0 mt-3">
|
||||||
{#if theme.partner_txt}
|
{#if data.theme.partner_txt}
|
||||||
{@html theme.partner_txt}
|
{@html data.theme.partner_txt}
|
||||||
{/if}
|
{/if}
|
||||||
{#if theme.partner_href}
|
{#if data.theme.partner_href}
|
||||||
<Button tag="a" color="primary" href="{theme.partner_href}">
|
<Button tag="a" color="primary" href="{data.theme.partner_href}">
|
||||||
Visiter le site
|
Visiter le site
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -62,11 +52,11 @@
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{#each Object.keys(theme.exercices) as k, index}
|
{#each Object.keys(data.theme.exercices) as k, index}
|
||||||
<li
|
<li
|
||||||
class="list-group-item"
|
class="list-group-item"
|
||||||
class:list-group-item-action={$my && $my.exercices[k]}
|
class:list-group-item-action={$my && $my.exercices[k]}
|
||||||
on:click={goto(`${theme.urlid}/${theme.exercices[k].urlid}`)}
|
on:click={goto(`${data.theme.urlid}/${data.theme.exercices[k].urlid}`)}
|
||||||
>
|
>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-1" style="margin-top: -0.5rem; margin-bottom: -0.5rem; text-align: right; border-right: 5px solid #{$my && $my.exercices[k] && $my.exercices[k].solved_rank ? '62c462' : 'bbb'}">
|
<div class="col-1" style="margin-top: -0.5rem; margin-bottom: -0.5rem; text-align: right; border-right: 5px solid #{$my && $my.exercices[k] && $my.exercices[k].solved_rank ? '62c462' : 'bbb'}">
|
||||||
|
@ -75,37 +65,37 @@
|
||||||
<div style="position: absolute; margin-left: calc(var(--bs-gutter-x) * -.5 - 15px); margin-top: -0.5rem;">
|
<div style="position: absolute; margin-left: calc(var(--bs-gutter-x) * -.5 - 15px); margin-top: -0.5rem;">
|
||||||
<svg style="height: 50px; width: 23px;">
|
<svg style="height: 50px; width: 23px;">
|
||||||
<rect
|
<rect
|
||||||
style="fill:#{$my && $my.exercices[k] && (index < 1 || ($my.exercices[Object.keys(theme.exercices)[index-1]] && $my.exercices[Object.keys(theme.exercices)[index-1]].solved_rank)) ? '62c462' : 'bbb'}"
|
style="fill:#{$my && $my.exercices[k] && (index < 1 || ($my.exercices[Object.keys(data.data.theme.exercices)[index-1]] && $my.exercices[Object.keys(data.theme.exercices)[index-1]].solved_rank)) ? '62c462' : 'bbb'}"
|
||||||
width="5"
|
width="5"
|
||||||
height="30"
|
height="30"
|
||||||
x="10"
|
x="10"
|
||||||
y="0" />
|
y="0" />
|
||||||
<path
|
<path
|
||||||
style="fill:#{$my && $my.exercices[k] ? ($my.exercices[k].solved_rank ? '62c462' : (theme.exercices[k].curcoeff > 1.0 ? 'f89406' : '5bc0de')) : '555'}"
|
style="fill:#{$my && $my.exercices[k] ? ($my.exercices[k].solved_rank ? '62c462' : (data.theme.exercices[k].curcoeff > 1.0 ? 'f89406' : '5bc0de')) : '555'}"
|
||||||
d="m 22,20 a 9.5700617,9.5700617 0 0 1 -9.5690181,9.57006 9.5700617,9.5700617 0 0 1 -9.57110534,-9.56797 9.5700617,9.5700617 0 0 1 9.56692984,-9.57215 9.5700617,9.5700617 0 0 1 9.5731926,9.56588" />
|
d="m 22,20 a 9.5700617,9.5700617 0 0 1 -9.5690181,9.57006 9.5700617,9.5700617 0 0 1 -9.57110534,-9.56797 9.5700617,9.5700617 0 0 1 9.56692984,-9.57215 9.5700617,9.5700617 0 0 1 9.5731926,9.56588" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{#each theme.exercices[k].tags as tag, idx}
|
{#each data.theme.exercices[k].tags as tag, idx}
|
||||||
<Badge href="tags/{tag}" pill color="secondary" class="mx-1 float-end">#{tag}</Badge>
|
<Badge href="tags/{tag}" pill color="secondary" class="mx-1 float-end">#{tag}</Badge>
|
||||||
{/each}
|
{/each}
|
||||||
<h5 class="fw-bold">
|
<h5 class="fw-bold">
|
||||||
{#if $my && $my.exercices[k]}
|
{#if $my && $my.exercices[k]}
|
||||||
{theme.exercices[k].title}
|
{data.theme.exercices[k].title}
|
||||||
{:else}
|
{:else}
|
||||||
<span style="white-space: nowrap">
|
<span style="white-space: nowrap">
|
||||||
<Icon name="lock-fill" aria-hidden="true" title="Vous n'avez pas encore accès à ce défi" />
|
<Icon name="lock-fill" aria-hidden="true" title="Vous n'avez pas encore accès à ce défi" />
|
||||||
{theme.exercices[k].title}
|
{data.theme.exercices[k].title}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if theme.exercices[k].curcoeff > 1.0}
|
{#if data.theme.exercices[k].curcoeff > 1.0}
|
||||||
<Icon name="gift" aria-hidden="true" title="Un bonus est actuellement appliqué lors de la résolution de ce défi" />
|
<Icon name="gift" aria-hidden="true" title="Un bonus est actuellement appliqué lors de la résolution de ce défi" />
|
||||||
{/if}
|
{/if}
|
||||||
</h5>
|
</h5>
|
||||||
<p>{@html theme.exercices[k].headline}</p>
|
<p>{@html data.theme.exercices[k].headline}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-none d-md-block col-1">
|
<div class="d-none d-md-block col-1">
|
||||||
{#if $my && $my.exercices[k]}
|
{#if $my && $my.exercices[k]}
|
||||||
<a class="float-right" href="{theme.urlid}/{theme.exercices[k].urlid}" style="font-size: 3rem">
|
<a class="float-right" href="{data.theme.urlid}/{data.theme.exercices[k].urlid}" style="font-size: 3rem">
|
||||||
<Icon name="chevron-right" aria-hidden="true" />
|
<Icon name="chevron-right" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
22
frontend/ui/src/routes/[theme]/[exercice]/+page.js
Normal file
22
frontend/ui/src/routes/[theme]/[exercice]/+page.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { get_store_value } from 'svelte/internal';
|
||||||
|
|
||||||
|
import { themes } from '../../../stores/themes.js';
|
||||||
|
|
||||||
|
export async function load({ parent }) {
|
||||||
|
const stuff = await parent();
|
||||||
|
|
||||||
|
let exercice = null;
|
||||||
|
|
||||||
|
for (let ex in stuff.theme.exercices) {
|
||||||
|
if (stuff.theme.exercices[ex].urlid === params.exercice) {
|
||||||
|
exercice = stuff.theme.exercices[ex];
|
||||||
|
exercice.id = ex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
theme: stuff.theme,
|
||||||
|
exercice: exercice,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,30 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
import { get_store_value } from 'svelte/internal';
|
|
||||||
|
|
||||||
import { themes } from '../../stores/themes.js';
|
|
||||||
|
|
||||||
export async function load({ params, stuff }) {
|
|
||||||
let exercice = null;
|
|
||||||
|
|
||||||
for (let ex in stuff.theme.exercices) {
|
|
||||||
if (stuff.theme.exercices[ex].urlid === params.exercice) {
|
|
||||||
exercice = stuff.theme.exercices[ex];
|
|
||||||
exercice.id = ex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
theme: stuff.theme,
|
|
||||||
exercice: exercice,
|
|
||||||
refresh_my: stuff.refresh_my,
|
|
||||||
refresh_teams: stuff.refresh_teams,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -38,55 +11,51 @@
|
||||||
Row,
|
Row,
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
|
|
||||||
import ExerciceDownloads from '../../components/ExerciceDownloads.svelte';
|
import ExerciceDownloads from '../../../components/ExerciceDownloads.svelte';
|
||||||
import ExerciceFlags from '../../components/ExerciceFlags.svelte';
|
import ExerciceFlags from '../../../components/ExerciceFlags.svelte';
|
||||||
import ExerciceHints from '../../components/ExerciceHints.svelte';
|
import ExerciceHints from '../../../components/ExerciceHints.svelte';
|
||||||
import ExerciceSolved from '../../components/ExerciceSolved.svelte';
|
import ExerciceSolved from '../../../components/ExerciceSolved.svelte';
|
||||||
import ExerciceVideo from '../../components/ExerciceVideo.svelte';
|
import ExerciceVideo from '../../../components/ExerciceVideo.svelte';
|
||||||
import ThemeNav from '../../components/ThemeNav.svelte';
|
import ThemeNav from '../../../components/ThemeNav.svelte';
|
||||||
|
|
||||||
import { challengeInfo } from '../../stores/challengeinfo.js';
|
import { challengeInfo } from '../../../stores/challengeinfo.js';
|
||||||
import { my } from '../../stores/my.js';
|
import { my } from '../../../stores/my.js';
|
||||||
import { settings } from '../../stores/settings.js';
|
import { settings } from '../../../stores/settings.js';
|
||||||
|
|
||||||
export let theme;
|
export let data;
|
||||||
export let exercice;
|
|
||||||
let solved = {};
|
let solved = {};
|
||||||
|
|
||||||
export let refresh_my;
|
|
||||||
export let refresh_teams;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>{exercice?exercice.title+" - ":""}{$challengeInfo.title}</title>
|
<title>{data.exercice?data.exercice.title+" - ":""}{$challengeInfo.title}</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
{#if exercice}
|
{#if data.exercice}
|
||||||
<ThemeNav {theme} {exercice} />
|
<ThemeNav theme={data.theme} exercice={data.exercice} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !$my || !exercice || !$my.exercices[exercice.id]}
|
{#if !$my || !data.exercice || !$my.exercices[data.exercice.id]}
|
||||||
<Alert color="warning" class="mt-3" fade={false}>
|
<Alert color="warning" class="mt-3" fade={false}>
|
||||||
<Icon name="dash-circle-fill" />
|
<Icon name="dash-circle-fill" />
|
||||||
Vous n'avez pas encore accès à ce défi.
|
Vous n'avez pas encore accès à ce défi.
|
||||||
</Alert>
|
</Alert>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if exercice}
|
{#if data.exercice}
|
||||||
<Card body class="niceborder text-indent my-3">
|
<Card body class="niceborder text-indent my-3">
|
||||||
<h3 class="display-4">{exercice.title}</h3>
|
<h3 class="display-4">{data.exercice.title}</h3>
|
||||||
<div>
|
<div>
|
||||||
{#each exercice.tags as tag, index}
|
{#each data.exercice.tags as tag, index}
|
||||||
<Badge href="tags/{tag}" pill color="secondary" class="mx-1 mb-2" >#{tag}</Badge>
|
<Badge href="tags/{tag}" pill color="secondary" class="mx-1 mb-2" >#{tag}</Badge>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if !$my || !$my.exercices[exercice.id]}
|
{#if !$my || !$my.exercices[data.exercice.id]}
|
||||||
<p class="lead text-justify">{@html exercice.headline}</p>
|
<p class="lead text-justify">{@html data.exercice.headline}</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="lead text-justify">{@html $my.exercices[exercice.id].statement}</p>
|
<p class="lead text-justify">{@html $my.exercices[data.exercice.id].statement}</p>
|
||||||
{#if $my.exercices[exercice.id].issue}
|
{#if $my.exercices[data.exercice.id].issue}
|
||||||
<Alert color="{$my.exercices[exercice.id].issuekind}">
|
<Alert color="{$my.exercices[data.exercice.id].issuekind}">
|
||||||
{@html $my.exercices[exercice.id].issue}
|
{@html $my.exercices[data.exercice.id].issue}
|
||||||
</Alert>
|
</Alert>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -96,31 +65,31 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<strong>Gain :</strong>
|
<strong>Gain :</strong>
|
||||||
{exercice.gain} {exercice.gain==1?"point":"points"}
|
{data.exercice.gain} {data.exercice.gain==1?"point":"points"}
|
||||||
{#if $settings.firstBlood && exercice.solved < 1}
|
{#if $settings.firstBlood && data.exercice.solved < 1}
|
||||||
<em>+{$settings.firstBlood * 100}% (prem's)</em>
|
<em>+{$settings.firstBlood * 100}% (prem's)</em>
|
||||||
{/if}
|
{/if}
|
||||||
{#if exercice.curcoeff != 1.0 || $settings.exerciceCurrentCoefficient != 1.0}
|
{#if data.exercice.curcoeff != 1.0 || $settings.exerciceCurrentCoefficient != 1.0}
|
||||||
<em>{#if exercice.curcoeff * $settings.exerciceCurrentCoefficient > 1}+{Math.round((exercice.curcoeff * $settings.exerciceCurrentCoefficient - 1) * 100)}{:else}-{Math.round((1-(exercice.curcoeff * $settings.exerciceCurrentCoefficient)) * 100)}{/if}% (bonus)</em>
|
<em>{#if data.exercice.curcoeff * $settings.exerciceCurrentCoefficient > 1}+{Math.round((data.exercice.curcoeff * $settings.exerciceCurrentCoefficient - 1) * 100)}{:else}-{Math.round((1-(data.exercice.curcoeff * $settings.exerciceCurrentCoefficient)) * 100)}{/if}% (bonus)</em>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Tenté par :</strong>
|
<strong>Tenté par :</strong>
|
||||||
{#if !exercice.tried}
|
{#if !data.exercice.tried}
|
||||||
aucune équipe
|
aucune équipe
|
||||||
{:else}
|
{:else}
|
||||||
{exercice.tried} {exercice.tried == 1?"équipe":"équipes"}
|
{data.exercice.tried} {data.exercice.tried == 1?"équipe":"équipes"}
|
||||||
{#if $my && $my.exercices[exercice.id] && $my.exercices[exercice.id].total_tries}
|
{#if $my && $my.exercices[data.exercice.id] && $my.exercices[data.exercice.id].total_tries}
|
||||||
(cumulant {$my.exercices[exercice.id].total_tries} {$my.exercices[exercice.id].total_tries == 1?"tentative":"tentatives"})
|
(cumulant {$my.exercices[data.exercice.id].total_tries} {$my.exercices[data.exercice.id].total_tries == 1?"tentative":"tentatives"})
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Résolu par :</strong>
|
<strong>Résolu par :</strong>
|
||||||
{#if !exercice.solved}
|
{#if !data.exercice.solved}
|
||||||
aucune équipe
|
aucune équipe
|
||||||
{:else}
|
{:else}
|
||||||
{exercice.solved} {exercice.solved == 1?"équipe":"équipes"}
|
{data.exercice.solved} {data.exercice.solved == 1?"équipe":"équipes"}
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -128,13 +97,13 @@
|
||||||
{#if $my && $my.team_id}
|
{#if $my && $my.team_id}
|
||||||
<Col>
|
<Col>
|
||||||
{#if $settings.acceptNewIssue}
|
{#if $settings.acceptNewIssue}
|
||||||
<a href="issues/?eid={exercice.id}" class="float-end btn btn-sm btn-warning">
|
<a href="issues/?eid={data.exercice.id}" class="float-end btn btn-sm btn-warning">
|
||||||
<Icon name="bug" />
|
<Icon name="bug" />
|
||||||
Rapporter une anomalie sur ce défi
|
Rapporter une anomalie sur ce défi
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $settings.QAenabled}
|
{#if $settings.QAenabled}
|
||||||
<a href="qa/exercices/{exercice.id}" class="float-end btn btn-sm btn-info" target="_self">
|
<a href="qa/exercices/{data.exercice.id}" class="float-end btn btn-sm btn-info" target="_self">
|
||||||
<Icon name="bug" />
|
<Icon name="bug" />
|
||||||
Voir les éléments QA sur ce défi
|
Voir les éléments QA sur ce défi
|
||||||
</a>
|
</a>
|
||||||
|
@ -144,51 +113,48 @@
|
||||||
</Row>
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{#if $my && $my.exercices[exercice.id]}
|
{#if $my && $my.exercices[data.exercice.id]}
|
||||||
<Row class="mt-4">
|
<Row class="mt-4">
|
||||||
<Col lg="6" class="mb-5">
|
<Col lg="6" class="mb-5">
|
||||||
{#if $my.exercices[exercice.id].files}
|
{#if $my.exercices[data.exercice.id].files}
|
||||||
<ExerciceDownloads
|
<ExerciceDownloads
|
||||||
files={$my.exercices[exercice.id].files}
|
files={$my.exercices[data.exercice.id].files}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $my.exercices[exercice.id].hints}
|
{#if $my.exercices[data.exercice.id].hints}
|
||||||
<ExerciceHints
|
<ExerciceHints
|
||||||
{refresh_my}
|
exercice={$my.exercices[data.exercice.id]}
|
||||||
exercice={$my.exercices[exercice.id]}
|
hints={$my.exercices[data.exercice.id].hints}
|
||||||
hints={$my.exercices[exercice.id].hints}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg="6" class="mb-5">
|
<Col lg="6" class="mb-5">
|
||||||
{#if $my.exercices[exercice.id].flags && $my.exercices[exercice.id].non_found_flags > 0 && !solved[exercice.id]}
|
{#if $my.exercices[data.exercice.id].flags && $my.exercices[data.exercice.id].non_found_flags > 0 && !solved[data.exercice.id]}
|
||||||
<ExerciceFlags
|
<ExerciceFlags
|
||||||
{refresh_my}
|
exercice={$my.exercices[data.exercice.id]}
|
||||||
{refresh_teams}
|
bind:forcesolved={solved[data.exercice.id]}
|
||||||
exercice={$my.exercices[exercice.id]}
|
flags={$my.exercices[data.exercice.id].flags}
|
||||||
bind:forcesolved={solved[exercice.id]}
|
|
||||||
flags={$my.exercices[exercice.id].flags}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $my.exercices[exercice.id].solved_rank || solved[exercice.id]}
|
{#if $my.exercices[data.exercice.id].solved_rank || solved[data.exercice.id]}
|
||||||
<ExerciceSolved
|
<ExerciceSolved
|
||||||
{theme}
|
theme={data.theme}
|
||||||
exercice={$my.exercices[exercice.id]}
|
exercice={$my.exercices[data.exercice.id]}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $my.exercices[exercice.id].resolution || $my.exercices[exercice.id].video_uri}
|
{#if $my.exercices[data.exercice.id].resolution || $my.exercices[data.exercice.id].video_uri}
|
||||||
<Card class="border-success mb-2">
|
<Card class="border-success mb-2">
|
||||||
<CardHeader class="bg-success text-light">
|
<CardHeader class="bg-success text-light">
|
||||||
<Icon name="laptop-fill" />
|
<Icon name="laptop-fill" />
|
||||||
Solution du défi
|
Solution du défi
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
{#if $my.exercices[exercice.id].resolution}
|
{#if $my.exercices[data.exercice.id].resolution}
|
||||||
<CardBody>
|
<CardBody>
|
||||||
{@html $my.exercices[exercice.id].resolution}
|
{@html $my.exercices[data.exercice.id].resolution}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $my.exercices[exercice.id].video_uri}
|
{#if $my.exercices[data.exercice.id].video_uri}
|
||||||
<ExerciceVideo uri={$my.exercices[exercice.id].video_uri} />
|
<ExerciceVideo uri={$my.exercices[data.exercice.id].video_uri} />
|
||||||
{/if}
|
{/if}
|
||||||
</Card>
|
</Card>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
export async function load({ stuff }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
refresh_my: stuff.refresh_my,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -20,14 +10,12 @@
|
||||||
Row,
|
Row,
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
|
|
||||||
import ScoreGrid from '../components/ScoreGrid.svelte';
|
import ScoreGrid from '../../components/ScoreGrid.svelte';
|
||||||
import TeamChangeName from '../components/TeamChangeName.svelte';
|
import TeamChangeName from '../../components/TeamChangeName.svelte';
|
||||||
import TeamMembers from '../components/TeamMembers.svelte';
|
import TeamMembers from '../../components/TeamMembers.svelte';
|
||||||
|
|
||||||
import { my } from '../stores/my.js';
|
import { my } from '../../stores/my.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../../stores/settings.js';
|
||||||
|
|
||||||
export let refresh_my;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container class="my-3">
|
<Container class="my-3">
|
||||||
|
@ -43,7 +31,7 @@
|
||||||
<Col md>
|
<Col md>
|
||||||
<TeamMembers members={$my.members} />
|
<TeamMembers members={$my.members} />
|
||||||
{#if !$settings.denyNameChange}
|
{#if !$settings.denyNameChange}
|
||||||
<TeamChangeName {refresh_my} />
|
<TeamChangeName />
|
||||||
{/if}
|
{/if}
|
||||||
</Col>
|
</Col>
|
||||||
<Col md>
|
<Col md>
|
||||||
|
|
14
frontend/ui/src/routes/issues/+page.js
Normal file
14
frontend/ui/src/routes/issues/+page.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { get_store_value } from 'svelte/internal';
|
||||||
|
|
||||||
|
import { exercices_idx } from '../../stores/themes.js';
|
||||||
|
|
||||||
|
export async function load({ url }) {
|
||||||
|
const eidx = get_store_value(exercices_idx);
|
||||||
|
|
||||||
|
const exercice = eidx[url.searchParams.get("eid")]?eidx[url.searchParams.get("eid")]:null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
exercice: exercice,
|
||||||
|
fillIssue: exercice !== null || url.searchParams.get("fill-issue") !== null,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,23 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
import { get_store_value } from 'svelte/internal';
|
|
||||||
|
|
||||||
import { exercices_idx } from '../stores/themes.js';
|
|
||||||
|
|
||||||
export async function load({ url, stuff }) {
|
|
||||||
const eidx = get_store_value(exercices_idx);
|
|
||||||
|
|
||||||
const exercice = eidx[url.searchParams.get("eid")]?eidx[url.searchParams.get("eid")]:null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
refresh_issues: stuff.refresh_issues,
|
|
||||||
exercice: exercice,
|
|
||||||
fillIssue: exercice !== null || url.searchParams.get("fill-issue") !== null,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -30,22 +10,20 @@
|
||||||
Table,
|
Table,
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
|
|
||||||
import DateFormat from '../components/DateFormat.svelte';
|
import DateFormat from '../../components/DateFormat.svelte';
|
||||||
|
|
||||||
import { issues, issues_nb_responses, issues_known_responses } from '../stores/issues.js';
|
import { issues, issues_nb_responses, issues_known_responses } from '../../stores/issues.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../../stores/settings.js';
|
||||||
|
|
||||||
import FormIssue from '../components/FormIssue.svelte';
|
import FormIssue from '../../components/FormIssue.svelte';
|
||||||
|
|
||||||
export let refresh_issues = null;
|
export let data;
|
||||||
export let exercice = null;
|
|
||||||
export let fillIssue = false;
|
|
||||||
let issue = {};
|
let issue = {};
|
||||||
|
|
||||||
issues_known_responses.set($issues_nb_responses);
|
issues_known_responses.set($issues_nb_responses);
|
||||||
|
|
||||||
function newIssue() {
|
function newIssue() {
|
||||||
fillIssue = true;
|
data.fillIssue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sberr = "";
|
let sberr = "";
|
||||||
|
@ -53,7 +31,7 @@
|
||||||
let messageClass = "success";
|
let messageClass = "success";
|
||||||
|
|
||||||
function waitDiff(curissues, i) {
|
function waitDiff(curissues, i) {
|
||||||
refresh_issues((issues) => {
|
issues.refresh((issues) => {
|
||||||
if (i > 0 && (!issues || issues.length <= curissues)) {
|
if (i > 0 && (!issues || issues.length <= curissues)) {
|
||||||
setTimeout(waitDiff, 850, curissues, i-1);
|
setTimeout(waitDiff, 850, curissues, i-1);
|
||||||
}
|
}
|
||||||
|
@ -61,9 +39,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function respondTo(_issue) {
|
function respondTo(_issue) {
|
||||||
exercice = null;
|
data.exercice = null;
|
||||||
issue = {id: _issue.id, description: ''};
|
issue = {id: _issue.id, description: ''};
|
||||||
fillIssue = true;
|
data.fillIssue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit_issue(event) {
|
async function submit_issue(event) {
|
||||||
|
@ -85,8 +63,8 @@
|
||||||
messageClass = 'success';
|
messageClass = 'success';
|
||||||
message = data.errmsg;
|
message = data.errmsg;
|
||||||
issue = { };
|
issue = { };
|
||||||
exercice = null;
|
data.exercice = null;
|
||||||
fillIssue = false;
|
data.fillIssue = false;
|
||||||
|
|
||||||
const currentissues = get_store_value(issues);
|
const currentissues = get_store_value(issues);
|
||||||
waitDiff(currentissues.length, 7);
|
waitDiff(currentissues.length, 7);
|
||||||
|
@ -120,7 +98,7 @@
|
||||||
</Alert>
|
</Alert>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if fillIssue}
|
{#if data.fillIssue}
|
||||||
<Card class="border-warning mt-3 mb-5">
|
<Card class="border-warning mt-3 mb-5">
|
||||||
<CardHeader class="bg-warning text-light">
|
<CardHeader class="bg-warning text-light">
|
||||||
<Icon name="file-earmark-plus" />
|
<Icon name="file-earmark-plus" />
|
||||||
|
@ -135,7 +113,7 @@
|
||||||
<p class="card-text">Rapprochez-vous d'un membre de l'équipe afin d'obtenir de l'aide.</p>
|
<p class="card-text">Rapprochez-vous d'un membre de l'équipe afin d'obtenir de l'aide.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<FormIssue
|
<FormIssue
|
||||||
{exercice}
|
exercice={data.exercice}
|
||||||
bind:issue={issue}
|
bind:issue={issue}
|
||||||
on:submit={submit_issue}
|
on:submit={submit_issue}
|
||||||
/>
|
/>
|
||||||
|
@ -153,7 +131,7 @@
|
||||||
<th>Géré par</th>
|
<th>Géré par</th>
|
||||||
<th>Messages</th>
|
<th>Messages</th>
|
||||||
<th>
|
<th>
|
||||||
{#if !fillIssue}
|
{#if !data.fillIssue}
|
||||||
<Button sm color="warning" on:click={newIssue}>
|
<Button sm color="warning" on:click={newIssue}>
|
||||||
<Icon name="file-earmark-plus" />
|
<Icon name="file-earmark-plus" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
Row,
|
Row,
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
|
|
||||||
import { my } from '../stores/my.js';
|
import { my } from '../../stores/my.js';
|
||||||
import { rank } from '../stores/teams.js';
|
import { rank } from '../../stores/teams.js';
|
||||||
import { challengeInfo } from '../stores/challengeinfo.js';
|
import { challengeInfo } from '../../stores/challengeinfo.js';
|
||||||
|
|
||||||
import CardTheme from '../components/CardTheme.svelte';
|
import CardTheme from '../../components/CardTheme.svelte';
|
||||||
|
|
||||||
let search = "";
|
let search = "";
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
export async function load({ stuff }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
refresh_my: stuff.refresh_my,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -21,13 +11,11 @@
|
||||||
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
import { my } from '../stores/my.js';
|
import { my } from '../../stores/my.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../../stores/settings.js';
|
||||||
|
|
||||||
import RegistrationFormCreateTeam from '../components/RegistrationFormCreateTeam.svelte';
|
import RegistrationFormCreateTeam from '../../components/RegistrationFormCreateTeam.svelte';
|
||||||
import RegistrationFormJoinTeam from '../components/RegistrationFormJoinTeam.svelte';
|
import RegistrationFormJoinTeam from '../../components/RegistrationFormJoinTeam.svelte';
|
||||||
|
|
||||||
export let refresh_my;
|
|
||||||
|
|
||||||
let form = { };
|
let form = { };
|
||||||
let partR = false;
|
let partR = false;
|
||||||
|
@ -36,7 +24,7 @@
|
||||||
let message;
|
let message;
|
||||||
|
|
||||||
function gotoHomeOnDiff(i) {
|
function gotoHomeOnDiff(i) {
|
||||||
refresh_my((my) => {
|
my.refresh((my) => {
|
||||||
if (my && my.team_id) {
|
if (my && my.team_id) {
|
||||||
goto('.');
|
goto('.');
|
||||||
} else if (i > 0) {
|
} else if (i > 0) {
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
Icon,
|
Icon,
|
||||||
} from 'sveltestrap';
|
} from 'sveltestrap';
|
||||||
|
|
||||||
import { challengeInfo } from '../stores/challengeinfo.js';
|
import { challengeInfo } from '../../stores/challengeinfo.js';
|
||||||
import { settings } from '../stores/settings.js';
|
import { settings } from '../../stores/settings.js';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container class="my-3">
|
<Container class="my-3">
|
||||||
|
|
5
frontend/ui/src/routes/tags/[tag]/+page.js
Normal file
5
frontend/ui/src/routes/tags/[tag]/+page.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export async function load({ params }) {
|
||||||
|
return {
|
||||||
|
tag: params.tag,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,13 +1,3 @@
|
||||||
<script context="module">
|
|
||||||
export async function load({ params }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
tag: params.tag,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -22,11 +12,11 @@
|
||||||
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
import { themes } from '../../stores/themes.js';
|
import { themes } from '../../../stores/themes.js';
|
||||||
|
|
||||||
import CardTheme from '../../components/CardTheme.svelte';
|
import CardTheme from '../../../components/CardTheme.svelte';
|
||||||
|
|
||||||
export let tag = "";
|
export let data;
|
||||||
|
|
||||||
let exercices = [];
|
let exercices = [];
|
||||||
$: {
|
$: {
|
||||||
|
@ -34,7 +24,7 @@
|
||||||
|
|
||||||
for (let th in $themes) {
|
for (let th in $themes) {
|
||||||
for (let ex in $themes[th].exercices) {
|
for (let ex in $themes[th].exercices) {
|
||||||
if ($themes[th].exercices[ex].tags.indexOf(tag) >= 0) {
|
if ($themes[th].exercices[ex].tags.indexOf(data.tag) >= 0) {
|
||||||
tmp_exercices.push({theme: $themes[th], exercice: $themes[th].exercices[ex], index: th + "," + ex});
|
tmp_exercices.push({theme: $themes[th], exercice: $themes[th].exercices[ex], index: th + "," + ex});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +36,7 @@
|
||||||
|
|
||||||
<Container class="mt-3">
|
<Container class="mt-3">
|
||||||
<h1 class="text-dark">
|
<h1 class="text-dark">
|
||||||
Challenges <em>{tag}</em>
|
Challenges <em>{data.tag}</em>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{#if exercices.length}
|
{#if exercices.length}
|
||||||
|
|
|
@ -5,6 +5,11 @@ function createChallengeStore() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb) => {
|
||||||
|
challengeInfo.update(await fetch('challenge.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
|
},
|
||||||
|
|
||||||
update: (res_challenge, cb) => {
|
update: (res_challenge, cb) => {
|
||||||
if (res_challenge.status === 200) {
|
if (res_challenge.status === 200) {
|
||||||
res_challenge.json().then((challenge) => {
|
res_challenge.json().then((challenge) => {
|
||||||
|
|
1
frontend/ui/src/stores/common.js
Normal file
1
frontend/ui/src/stores/common.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export let stop_refresh = false;
|
|
@ -1,11 +1,13 @@
|
||||||
import { derived, writable } from 'svelte/store';
|
import { derived, writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import { stop_refresh } from './common';
|
||||||
|
|
||||||
|
let refresh_interval_issues = null;
|
||||||
|
|
||||||
function createIssuesStore() {
|
function createIssuesStore() {
|
||||||
const { subscribe, set, update } = writable({issues: [], issues_idx: {}, issues_nb_responses: 0, issues_need_info: 0});
|
const { subscribe, set, update } = writable({issues: [], issues_idx: {}, issues_nb_responses: 0, issues_need_info: 0});
|
||||||
|
|
||||||
return {
|
function updateFunc (res_issues, cb=null) {
|
||||||
subscribe,
|
|
||||||
update: (res_issues, cb=null) => {
|
|
||||||
if (res_issues.status === 200) {
|
if (res_issues.status === 200) {
|
||||||
res_issues.json().then((issues) => {
|
res_issues.json().then((issues) => {
|
||||||
const issues_idx = {};
|
const issues_idx = {};
|
||||||
|
@ -26,7 +28,26 @@ function createIssuesStore() {
|
||||||
} else if (res_issues.status === 404) {
|
} else if (res_issues.status === 404) {
|
||||||
update((i) => ({issues: [], issues_idx: {}, issues_nb_responses: 0, issues_need_info: 0}));
|
update((i) => ({issues: [], issues_idx: {}, issues_nb_responses: 0, issues_need_info: 0}));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb=null, interval=null) => {
|
||||||
|
if (refresh_interval_issues)
|
||||||
|
clearInterval(refresh_interval_issues);
|
||||||
|
if (interval === null) {
|
||||||
|
interval = Math.floor(Math.random() * 24000) + 32000;
|
||||||
|
}
|
||||||
|
if (stop_refresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refresh_interval_issues = setInterval(refresh_issues, interval);
|
||||||
|
|
||||||
|
updateFunc(await fetch('issues.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: updateFunc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import { stop_refresh } from './common';
|
||||||
|
|
||||||
|
let refresh_interval_my = null;
|
||||||
|
|
||||||
function createMyStore() {
|
function createMyStore() {
|
||||||
const { subscribe, set, update } = writable(null);
|
const { subscribe, set, update } = writable(null);
|
||||||
|
|
||||||
return {
|
function updateFunc(res_my, cb=null) {
|
||||||
subscribe,
|
|
||||||
update: (res_my, cb=null) => {
|
|
||||||
if (res_my.status === 200) {
|
if (res_my.status === 200) {
|
||||||
res_my.json().then((my) => {
|
res_my.json().then((my) => {
|
||||||
for (let k in my.exercices) {
|
for (let k in my.exercices) {
|
||||||
|
@ -36,7 +38,26 @@ function createMyStore() {
|
||||||
} else if (res_my.status === 404) {
|
} else if (res_my.status === 404) {
|
||||||
update((m) => (null));
|
update((m) => (null));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb=null, interval=null) => {
|
||||||
|
if (refresh_interval_my)
|
||||||
|
clearInterval(refresh_interval_my);
|
||||||
|
if (interval === null) {
|
||||||
|
interval = Math.floor(Math.random() * 24000) + 24000;
|
||||||
|
}
|
||||||
|
if (stop_refresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refresh_interval_my = setInterval(refresh_my, interval);
|
||||||
|
|
||||||
|
updateFunc(await fetch('my.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: updateFunc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
frontend/ui/src/stores/myresponses.js
Normal file
0
frontend/ui/src/stores/myresponses.js
Normal file
|
@ -1,11 +1,13 @@
|
||||||
import { readable, writable } from 'svelte/store';
|
import { readable, writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import { stop_refresh } from './common';
|
||||||
|
|
||||||
|
let refresh_interval_settings = null;
|
||||||
|
|
||||||
function createSettingsStore() {
|
function createSettingsStore() {
|
||||||
const { subscribe, set, update } = writable({});
|
const { subscribe, set, update } = writable({});
|
||||||
|
|
||||||
return {
|
function updateFunc(res_settings, cb) {
|
||||||
subscribe,
|
|
||||||
update: (res_settings, cb) => {
|
|
||||||
const recvTime = (new Date()).getTime();
|
const recvTime = (new Date()).getTime();
|
||||||
|
|
||||||
if (res_settings.status === 200) {
|
if (res_settings.status === 200) {
|
||||||
|
@ -36,7 +38,45 @@ function createSettingsStore() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb=null, interval=null) => {
|
||||||
|
if (refresh_interval_settings)
|
||||||
|
clearInterval(refresh_interval_settings);
|
||||||
|
if (interval === null) {
|
||||||
|
interval = Math.floor(Math.random() * 24000) + 32000;
|
||||||
|
}
|
||||||
|
if (stop_refresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refresh_interval_settings = setInterval(refresh_settings, interval);
|
||||||
|
|
||||||
|
if (!cb) {
|
||||||
|
// Before we start, update settings more frequently.
|
||||||
|
cb = function(stgs) {
|
||||||
|
const srv_cur = new Date(Date.now() + (stgs.currentTime - stgs.recvTime));
|
||||||
|
|
||||||
|
if (settings.start > srv_cur) {
|
||||||
|
const startIn = settings.start - srv_cur;
|
||||||
|
if (startIn > 15000) {
|
||||||
|
setTimeout(refresh_settings, Math.floor(Math.random() * 10000) + 2400)
|
||||||
|
} else if (startIn > 1500) {
|
||||||
|
setTimeout(refresh_settings, startIn - 1000 - Math.floor(Math.random() * 500))
|
||||||
|
} else {
|
||||||
|
// On scheduled start time, refresh my.json file
|
||||||
|
setTimeout(refresh_my, startIn + Math.floor(Math.random() * 200))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFunc(await fetch('settings.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: updateFunc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { derived, writable } from 'svelte/store';
|
import { derived, writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import { stop_refresh } from './common';
|
||||||
|
|
||||||
|
let refresh_interval_teams = null;
|
||||||
|
|
||||||
function createTeamsStore() {
|
function createTeamsStore() {
|
||||||
const { subscribe, set, update } = writable({teams:{}, teams_count: 0, rank: []});
|
const { subscribe, set, update } = writable({teams:{}, teams_count: 0, rank: []});
|
||||||
|
|
||||||
return {
|
function updateFunc(res_teams, cb=null) {
|
||||||
subscribe,
|
|
||||||
update: (res_teams, cb=null) => {
|
|
||||||
if (res_teams.status === 200) {
|
if (res_teams.status === 200) {
|
||||||
res_teams.json().then((teams) => {
|
res_teams.json().then((teams) => {
|
||||||
const teams_count = Object.keys(teams).length
|
const teams_count = Object.keys(teams).length
|
||||||
|
@ -24,7 +26,26 @@ function createTeamsStore() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb=null, interval=null) => {
|
||||||
|
if (refresh_interval_teams)
|
||||||
|
clearInterval(refresh_interval_teams);
|
||||||
|
if (interval === null) {
|
||||||
|
interval = Math.floor(Math.random() * 24000) + 32000;
|
||||||
|
}
|
||||||
|
if (stop_refresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refresh_interval_teams = setInterval(refresh_teams, interval);
|
||||||
|
|
||||||
|
updateFunc(await fetch('teams.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: updateFunc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { derived, writable } from 'svelte/store';
|
import { derived, writable } from 'svelte/store';
|
||||||
|
|
||||||
|
import { stop_refresh } from './common';
|
||||||
|
|
||||||
|
let refresh_interval_themes = null;
|
||||||
|
|
||||||
function createThemesStore() {
|
function createThemesStore() {
|
||||||
const { subscribe, set, update } = writable({themes: null, exercices_idx: {}, max_solved: 0});
|
const { subscribe, set, update } = writable({themes: null, exercices_idx: {}, max_solved: 0});
|
||||||
|
|
||||||
return {
|
async function updateFunc (res_themes, cb=null) {
|
||||||
subscribe,
|
|
||||||
update: async (res_themes, cb=null) => {
|
|
||||||
if (res_themes.status === 200) {
|
if (res_themes.status === 200) {
|
||||||
const themes = await res_themes.json();
|
const themes = await res_themes.json();
|
||||||
|
|
||||||
|
@ -46,7 +48,26 @@ function createThemesStore() {
|
||||||
cb(themes, exercices_idx, max_solved);
|
cb(themes, exercices_idx, max_solved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
|
||||||
|
refresh: async (cb=null, interval=null) => {
|
||||||
|
if (refresh_interval_themes)
|
||||||
|
clearInterval(refresh_interval_themes);
|
||||||
|
if (interval === null) {
|
||||||
|
interval = Math.floor(Math.random() * 24000) + 32000;
|
||||||
|
}
|
||||||
|
if (stop_refresh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refresh_interval_themes = setInterval(refresh_themes, interval);
|
||||||
|
|
||||||
|
await updateFunc(await fetch('themes.json', {headers: {'Accept': 'application/json'}}), cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: updateFunc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
frontend/ui/static/e404.html
Normal file
44
frontend/ui/static/e404.html
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Challenge Forensic</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
<meta name="author" content="EPITA Laboratoire SRS">
|
||||||
|
<meta name="robots" content="all">
|
||||||
|
<link href="../../static/main.css" rel="stylesheet">
|
||||||
|
<link href="../../theme/styles.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
.niceborder {
|
||||||
|
border-bottom-color: #ee5f5b !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="theme-body">
|
||||||
|
|
||||||
|
<div class="theme-navbar niceborder">
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||||
|
</div>
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/epita.png" alt="Épita">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container dex-container" style="margin-top:20px;">
|
||||||
|
<div class="jumbotron theme-panel niceborder">
|
||||||
|
<h1>Page introuvable <small>Erreur 404</small></h1>
|
||||||
|
<hr>
|
||||||
|
<p class="lead">
|
||||||
|
La page à laquelle vous tentez d'accéder n'existe pas ou l'adresse que vous avez tapée est incorrecte.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Si le problème persiste, <a href="mailto:root@srs.epita.fr">contactez un administrateur</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
1
frontend/ui/static/e404.json
Normal file
1
frontend/ui/static/e404.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"errmsg": "La page à laquelle vous tentez d'accéder n'existe pas ou l'adresse que vous avez tapée est incorrecte."}
|
41
frontend/ui/static/e413.html
Normal file
41
frontend/ui/static/e413.html
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Challenge Forensic</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
<meta name="author" content="EPITA Laboratoire SRS">
|
||||||
|
<meta name="robots" content="all">
|
||||||
|
<link href="../../static/main.css" rel="stylesheet">
|
||||||
|
<link href="../../theme/styles.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
.niceborder {
|
||||||
|
border-bottom-color: #ee5f5b !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="theme-body">
|
||||||
|
|
||||||
|
<div class="theme-navbar niceborder">
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||||
|
</div>
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/epita.png" alt="Épita">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container dex-container" style="margin-top:20px;">
|
||||||
|
<div class="jumbotron theme-panel niceborder">
|
||||||
|
<h1>Requête trop grosse <small>Erreur 413</small></h1>
|
||||||
|
<hr>
|
||||||
|
<p class="lead">
|
||||||
|
La quantité de données que vous souhaitez envoyer au serveur est trop importante pour qu'il accepte de la traiter.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
1
frontend/ui/static/e413.json
Normal file
1
frontend/ui/static/e413.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"errmsg": "La quantité de données que vous souhaitez envoyer au serveur est trop importante pour qu'il accepte de la traiter."}
|
44
frontend/ui/static/e500.html
Normal file
44
frontend/ui/static/e500.html
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Challenge Forensic</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
<meta name="author" content="EPITA Laboratoire SRS">
|
||||||
|
<meta name="robots" content="all">
|
||||||
|
<link href="../../static/main.css" rel="stylesheet">
|
||||||
|
<link href="../../theme/styles.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
.niceborder {
|
||||||
|
border-bottom-color: #ee5f5b !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="theme-body">
|
||||||
|
|
||||||
|
<div class="theme-navbar niceborder">
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/fic.png" alt="Forum International de la Cybersécurité">
|
||||||
|
</div>
|
||||||
|
<div class="theme-navbar__logo-wrap">
|
||||||
|
<img class="theme-navbar__logo" src="/img/epita.png" alt="Épita">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container dex-container" style="margin-top:20px;">
|
||||||
|
<div class="jumbotron theme-panel niceborder">
|
||||||
|
<h1>Erreur interne <small>Erreur 500</small></h1>
|
||||||
|
<hr>
|
||||||
|
<p class="lead">
|
||||||
|
Notre serveur est actuellement dans l'incapacité de répondre à votre requête.<br>Veuillez recommencer dans quelques instants.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Si le problème persiste, <a href="mailto:root@srs.epita.fr">contactez un administrateur</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
1
frontend/ui/static/e500.json
Normal file
1
frontend/ui/static/e500.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"errmsg": "Notre serveur est actuellement dans l'incapacité de répondre à votre requête. \nVeuillez recommencer dans quelques instants."}
|
Reference in a new issue