qa: Refactor layout

This commit is contained in:
nemunaire 2023-07-26 15:15:49 +02:00
commit c13da8b574
19 changed files with 425 additions and 295 deletions

View file

@ -0,0 +1,13 @@
import { getExercice } from '$lib/exercices';
import { getExerciceQA } from '$lib/qa.js';
/** @type {import('./$types').PageLoad} */
export async function load({ depends, params }) {
const exercice = getExercice(params.eid)
depends(`api/exercices/${params.eid}`);
const qaitems = getExerciceQA(params.eid);
depends(`api/exercices/${params.eid}/qa`);
return { exercice, qaitems };
}

View file

@ -0,0 +1,20 @@
<script>
import { page } from '$app/stores';
import ExerciceLayout from '$lib/components/ExerciceLayout.svelte';
import { themes } from '$lib/stores/themes';
if ($themes.length == 0) {
themes.refresh();
}
export let data;
</script>
<ExerciceLayout
exercice={data.exercice}
qaitems={data.qaitems}
query_selected={$page.params.qid}
>
<slot></slot>
</ExerciceLayout>

View file

@ -1,26 +1,34 @@
<script>
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import {
Button,
Col,
Container,
Icon,
Spinner,
Row,
Table,
} from 'sveltestrap';
import { getExercice } from '$lib/exercices';
import ExerciceQA from '$lib/components/ExerciceQA.svelte';
import QANewItem from '$lib/components/QANewItem.svelte';
let exerciceP = getExercice($page.params.eid);
export let data;
</script>
{#await exerciceP}
<Container class="mt-2 mb-5">
<div class="d-flex justify-content-center">
<Spinner size="lg" />
</div>
</Container>
{:then exercice}
<ExerciceQA {exercice} />
{/await}
<Row class="mb-3">
<div
class="col-md-6"
style="overflow-y: auto; max-height: 40vh;"
>
{@html data.exercice.statement.replace("$FILES$", "../files")}
</div>
<div
class="col-md-6"
style="overflow-y: auto; max-height: 40vh;"
>
{@html data.exercice.overview.replace("$FILES$", "../files")}
</div>
</Row>
<QANewItem
theme={data.theme}
exercice={data.exercice}
/>

View file

@ -0,0 +1,21 @@
import { error } from '@sveltejs/kit';
/** @type {import('./$types').PageLoad} */
export async function load({ params, parent }) {
const { exercice, qaitems } = await parent();
let query_selected = null;
for (const qaitem of qaitems) {
if (qaitem.id == params.qid) {
query_selected = qaitem;
}
}
if (!query_selected) {
throw error(404, {
message: 'Not found'
});
}
return { exercice, qaitems, query_selected };
}

View file

@ -0,0 +1,10 @@
<script>
import QAItem from '$lib/components/QAItem.svelte';
export let data;
</script>
<QAItem
exercice={data.exercice}
query={data.query_selected}
/>

View file

@ -1 +0,0 @@
<slot></slot>

View file

@ -0,0 +1,9 @@
import { getTheme } from '$lib/themes';
/** @type {import('./$types').PageLoad} */
export async function load({ depends, params }) {
const theme = getTheme(params.tid)
depends(`api/themes/${params.tid}`);
return { theme };
}

View file

@ -10,9 +10,9 @@
Spinner,
} from 'sveltestrap';
import { getTheme } from '$lib/themes';
import { fieldsExercices, getThemedExercices } from '$lib/exercices';
export let data;
let query = "";
function show(id) {
@ -21,67 +21,61 @@
</script>
<Container class="mt-2 mb-5">
{#await getTheme($page.params.tid)}
<div class="d-flex justify-content-center">
<Spinner size="lg" />
</div>
{:then theme}
<div class="d-flex align-items-end">
<Button
class="align-self-center"
color="link"
on:click={() => goto('themes/')}
>
<Icon name="chevron-left" />
</Button>
<h2>
{theme.name}
</h2>
<small class="m-2 mb-3 text-muted text-truncate">{@html theme.authors}</small>
</div>
<div class="d-flex align-items-end">
<Button
class="align-self-center"
color="link"
on:click={() => goto('themes/')}
>
<Icon name="chevron-left" />
</Button>
<h2>
{data.theme.name}
</h2>
<small class="m-2 mb-3 text-muted text-truncate">{@html data.theme.authors}</small>
</div>
{#if theme.intro}
<Container class="text-muted" style="overflow-y: auto; max-height: 34vh">
{@html theme.intro.replace("$FILES$", "../files")}
</Container>
{/if}
{#if data.theme.intro}
<Container class="text-muted" style="overflow-y: auto; max-height: 34vh">
{@html data.theme.intro.replace("$FILES$", "../files")}
</Container>
{/if}
{#await getThemedExercices($page.params.tid)}
{:then exercices}
<h3 class="mt-2">
Défis ({exercices.length})
</h3>
{#await getThemedExercices($page.params.tid)}
{:then exercices}
<h3 class="mt-2">
Défis ({exercices.length})
</h3>
<p>
<input type="search" class="form-control form-control-sm" placeholder="Search" bind:value={query} autofocus>
</p>
<Table class="table-hover table-bordered table-striped table-sm">
<thead class="thead-dark">
<tr>
{#each fieldsExercices as field}
<th>
{field}
</th>
{/each}
</tr>
</thead>
<tbody>
{#each exercices as exercice (exercice.id)}
{#if exercice.title.indexOf(query) >= 0}
<tr on:click={() => show(exercice.id)}>
{#each fieldsExercices as field}
<td>
{@html exercice[field]}
{#if field == "title" && exercice.wip}
<Icon name="cone-striped" />
{/if}
</td>
{/each}
</tr>
{/if}
<p>
<input type="search" class="form-control form-control-sm" placeholder="Search" bind:value={query} autofocus>
</p>
<Table class="table-hover table-bordered table-striped table-sm">
<thead class="thead-dark">
<tr>
{#each fieldsExercices as field}
<th>
{field}
</th>
{/each}
</tbody>
</Table>
{/await}
</tr>
</thead>
<tbody>
{#each exercices as exercice (exercice.id)}
{#if exercice.title.indexOf(query) >= 0}
<tr on:click={() => show(exercice.id)}>
{#each fieldsExercices as field}
<td>
{@html exercice[field]}
{#if field == "title" && exercice.wip}
<Icon name="cone-striped" />
{/if}
</td>
{/each}
</tr>
{/if}
{/each}
</tbody>
</Table>
{/await}
</Container>

View file

@ -0,0 +1,15 @@
import { getExercice } from '$lib/exercices';
import { getExerciceQA } from '$lib/qa.js';
/** @type {import('./$types').PageLoad} */
export async function load({ depends, params, parent }) {
const { theme } = await parent();
const exercice = getExercice(params.eid)
depends(`api/exercices/${params.eid}`);
const qaitems = getExerciceQA(params.eid);
depends(`api/exercices/${params.eid}/qa`);
return { exercice, qaitems, theme };
}

View file

@ -0,0 +1,21 @@
<script>
import { page } from '$app/stores';
import ExerciceLayout from '$lib/components/ExerciceLayout.svelte';
import { themes } from '$lib/stores/themes';
if ($themes.length == 0) {
themes.refresh();
}
export let data;
</script>
<ExerciceLayout
exercice={data.exercice}
qaitems={data.qaitems}
query_selected={$page.params.qid}
theme={data.theme}
>
<slot></slot>
</ExerciceLayout>

View file

@ -1,26 +1,34 @@
<script>
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import {
Button,
Col,
Container,
Icon,
Spinner,
Row,
Table,
} from 'sveltestrap';
import { getThemedExercice } from '$lib/exercices';
import ExerciceQA from '$lib/components/ExerciceQA.svelte';
import QANewItem from '$lib/components/QANewItem.svelte';
let exerciceP = getThemedExercice($page.params.tid, $page.params.eid);
export let data;
</script>
{#await exerciceP}
<Container class="mt-2 mb-5">
<div class="d-flex justify-content-center">
<Spinner size="lg" />
</div>
</Container>
{:then exercice}
<ExerciceQA theme_id={$page.params.tid} {exercice} />
{/await}
<Row class="mb-3">
<div
class="col-md-6"
style="overflow-y: auto; max-height: 40vh;"
>
{@html data.exercice.statement.replace("$FILES$", "../files")}
</div>
<div
class="col-md-6"
style="overflow-y: auto; max-height: 40vh;"
>
{@html data.exercice.overview.replace("$FILES$", "../files")}
</div>
</Row>
<QANewItem
theme={data.theme}
exercice={data.exercice}
/>

View file

@ -0,0 +1,21 @@
import { error } from '@sveltejs/kit';
/** @type {import('./$types').PageLoad} */
export async function load({ params, parent }) {
const { exercice, qaitems, theme } = await parent();
let query_selected = null;
for (const qaitem of qaitems) {
if (qaitem.id == params.qid) {
query_selected = qaitem;
}
}
if (!query_selected) {
throw error(404, {
message: 'Not found'
});
}
return { exercice, qaitems, query_selected, theme };
}

View file

@ -0,0 +1,11 @@
<script>
import QAItem from '$lib/components/QAItem.svelte';
export let data;
</script>
<QAItem
exercice={data.exercice}
query={data.query_selected}
theme={data.theme}
/>