Crippled version of task display
This commit is contained in:
parent
5298dae17f
commit
6ec2234ef9
5 changed files with 100 additions and 20 deletions
|
@ -2,10 +2,19 @@
|
|||
import Graph from "./Graph.svelte";
|
||||
import GraphNode from "./GraphNode.svelte";
|
||||
import { loadTasks } from "./task-loader";
|
||||
import type { TasksFile } from "./task-loader";
|
||||
import type { TasksFile, TaskDescriptor } from "./task-loader";
|
||||
import TasksLoader from "./TasksLoader.svelte";
|
||||
import TaskPanel from "./TaskPanel.svelte";
|
||||
|
||||
const tasksPromise: Promise<TasksFile> = loadTasks();
|
||||
|
||||
let selectedTask: string | null = null
|
||||
let finalSelect: boolean = false
|
||||
|
||||
function clickTask(e: CustomEvent<TaskDescriptor>) {
|
||||
finalSelect = true
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -37,6 +46,7 @@
|
|||
</svg>
|
||||
-->
|
||||
<TasksLoader promise={tasksPromise} let:data={t}>
|
||||
<Graph tasks={t} />
|
||||
<TaskPanel bind:finalSelect={finalSelect} selectedTask={selectedTask} />
|
||||
<Graph tasks={t} bind:selectedTask={selectedTask} on:selectTask={clickTask} />
|
||||
</TasksLoader>
|
||||
</main>
|
||||
|
|
|
@ -1,15 +1,32 @@
|
|||
<script type="ts">
|
||||
import GraphNode from "./GraphNode.svelte";
|
||||
import GraphEdge from "./GraphEdge.svelte";
|
||||
import { onMount } from "svelte";
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import * as d3 from "d3";
|
||||
import { createLinksFromTaskMap } from "./task-loader";
|
||||
import type { TasksFile } from "./task-loader";
|
||||
import type { TasksFile, TaskDescriptor } from "./task-loader";
|
||||
|
||||
const eventDispatcher = createEventDispatcher()
|
||||
|
||||
export let tasks: TasksFile;
|
||||
let nodes = tasks.tasks;
|
||||
let edges = createLinksFromTaskMap(tasks);
|
||||
|
||||
export let selectedTask: null | string = null
|
||||
const nodeClick = (task: TaskDescriptor) => (e: CustomEvent<MouseEvent>) => {
|
||||
selectedTask = task.id
|
||||
eventDispatcher("selectTask", task)
|
||||
}
|
||||
|
||||
const nodeHover = (task: TaskDescriptor) => (hovering: CustomEvent<boolean>) => {
|
||||
if (hovering.detail) {
|
||||
selectedTask = task.id
|
||||
} else {
|
||||
if (selectedTask == task.id)
|
||||
selectedTask = null
|
||||
}
|
||||
}
|
||||
|
||||
// Svelte automatically fills this with a reference
|
||||
let container: HTMLElement;
|
||||
|
||||
|
@ -69,7 +86,7 @@
|
|||
<GraphEdge {edge} />
|
||||
{/each}
|
||||
{#each nodes as task}
|
||||
<GraphNode {task} />
|
||||
<GraphNode {task} on:click={nodeClick(task)} on:hoveringChange={nodeHover(task)} />
|
||||
{/each}
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
|
||||
import type { TaskDescriptor } from "./task-loader";
|
||||
|
||||
|
@ -7,15 +7,23 @@
|
|||
let hovering: boolean = false;
|
||||
let text_element: SVGTextElement;
|
||||
|
||||
const eventDispatcher = createEventDispatcher()
|
||||
|
||||
$: cx = task === undefined || task.x === undefined ? 0 : task.x;
|
||||
$: cy = task === undefined || task.y === undefined ? 0 : task.y;
|
||||
|
||||
function enter() {
|
||||
hovering = true;
|
||||
eventDispatcher("hoveringChange", hovering)
|
||||
}
|
||||
|
||||
function leave() {
|
||||
hovering = false;
|
||||
eventDispatcher("hoveringChange", hovering)
|
||||
}
|
||||
|
||||
function click(e: MouseEvent) {
|
||||
eventDispatcher("click", e)
|
||||
}
|
||||
|
||||
let ellipse_rx = 20;
|
||||
|
@ -36,7 +44,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<g on:mouseenter={enter} on:mouseleave={leave}>
|
||||
<g on:mouseenter={enter} on:mouseleave={leave} on:click={click}>
|
||||
<ellipse rx={ellipse_rx} ry={ellipse_ry} {cx} {cy} />
|
||||
<text
|
||||
bind:this={text_element}
|
||||
|
|
42
frontend/src/TaskPanel.svelte
Normal file
42
frontend/src/TaskPanel.svelte
Normal file
|
@ -0,0 +1,42 @@
|
|||
<script lang="ts">
|
||||
import { grabAssignment } from "./ksp-task-grabber";
|
||||
import type { TasksFile, TaskDescriptor } from "./task-loader";
|
||||
|
||||
// export let tasks: TasksFile;
|
||||
export let selectedTask: string | null = null
|
||||
export let finalSelect: boolean = false
|
||||
let mouse: boolean = false
|
||||
|
||||
let height: string;
|
||||
$: height = selectedTask == null && !mouse ? "0" :
|
||||
finalSelect ? "100%" :
|
||||
"100px"
|
||||
|
||||
let taskPromise: Promise<string | null>
|
||||
$: {
|
||||
if (selectedTask != null)
|
||||
taskPromise = grabAssignment(selectedTask)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.panel {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
background-color: #222;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="panel" style="height: {height}" on:mouseover={() => mouse = false} on:mouseout={() => mouse = false}>
|
||||
{#if selectedTask != null}
|
||||
{#await taskPromise}
|
||||
Načítám úložku {selectedTask} ;)
|
||||
{:then task}
|
||||
{@html task}
|
||||
{/await}
|
||||
<button type=button on:click={() => finalSelect = false}>
|
||||
Zavřít
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
|
@ -12,28 +12,28 @@ type TaskLocation = {
|
|||
startElement: string
|
||||
}
|
||||
|
||||
function getLocation(id: string, solution: boolean): TaskLocation {
|
||||
function getLocation(id: string, solution: boolean): TaskLocation | null {
|
||||
const m = /^(\d+)-(Z?)(\d)-(\d)$/.exec(id)
|
||||
if (!m) throw new Error(`Invalid task id: ${m}`)
|
||||
const [_, rocnik, z, serie, uloha] = m[1]
|
||||
if (!m) return null
|
||||
const [_, rocnik, z, serie, uloha] = m
|
||||
if (z == 'Z') {
|
||||
const urlX = solution ? "reseni" : "zadani"
|
||||
return {
|
||||
url: `z/ulohy/${rocnik}/${urlX}${serie}.html`,
|
||||
startElement: `task${uloha}`
|
||||
startElement: `task-${id}`
|
||||
}
|
||||
} else {
|
||||
const urlX = solution ? "solution" : "tasks"
|
||||
return {
|
||||
url: `tasks/${rocnik}/${urlX}${serie}.html`,
|
||||
startElement: `task${uloha}`
|
||||
startElement: `task-${id}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseTask(startElementId: string, html: string, contentType: string): string {
|
||||
function parseTask(startElementId: string, html: string): string {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(html, contentType as any)
|
||||
const doc = parser.parseFromString(html, "text/html")
|
||||
|
||||
const titleElement = doc.getElementById(startElementId)
|
||||
if (!titleElement)
|
||||
|
@ -69,14 +69,17 @@ async function loadTask({ url, startElement }: TaskLocation) {
|
|||
throw Error("Bad request")
|
||||
}
|
||||
const rText = await r.text()
|
||||
const contentType = r.headers.get("Content-Type") || "text/html"
|
||||
return parseTask(startElement, rText, contentType)
|
||||
return parseTask(startElement, rText)
|
||||
}
|
||||
|
||||
export function loadAssignment(id: string) {
|
||||
return loadTask(getLocation(id, false))
|
||||
export async function grabAssignment(id: string) {
|
||||
const l = getLocation(id, false)
|
||||
if (!l) return "úloha je virtuální a neexistuje"
|
||||
return await loadTask(l)
|
||||
}
|
||||
|
||||
export function loadSolution(id: string) {
|
||||
return loadTask(getLocation(id, true))
|
||||
export async function grabSolution(id: string) {
|
||||
const l = getLocation(id, true)
|
||||
if (!l) return "úloha je virtuální a neexistuje"
|
||||
return await loadTask(l)
|
||||
}
|
||||
|
|
Reference in a new issue