Merge branch 'master' into v1.3
This commit is contained in:
revize
ff570cff4b
|
@ -5,6 +5,7 @@
|
||||||
import Tooltip from "$lib/Tooltip.svelte";
|
import Tooltip from "$lib/Tooltip.svelte";
|
||||||
import SvelteMarkdown from "svelte-markdown";
|
import SvelteMarkdown from "svelte-markdown";
|
||||||
import EventTypeLabel from "$lib/EventTypeLabel.svelte";
|
import EventTypeLabel from "$lib/EventTypeLabel.svelte";
|
||||||
|
import EventSchedule from '$lib/EventSchedule.svelte';
|
||||||
import { bundle, userData } from "$lib/stores.js";
|
import { bundle, userData } from "$lib/stores.js";
|
||||||
import { calcDuration, addFavorite } from "$lib/events.js";
|
import { calcDuration, addFavorite } from "$lib/events.js";
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
$: e = event;
|
$: e = event;
|
||||||
$: duration = calcDuration(e, $bundle);
|
$: duration = calcDuration(e, $bundle);
|
||||||
$: spoiler = makeSpoiler(e);
|
$: spoiler = makeSpoiler(e);
|
||||||
|
$: schedule = $bundle ? $bundle.spec.schedule.find(s => s.event === e.id) : null
|
||||||
|
|
||||||
function makeSpoiler(_e) {
|
function makeSpoiler(_e) {
|
||||||
if (!_e.description) {
|
if (!_e.description) {
|
||||||
|
@ -79,6 +81,9 @@
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="text-sm flex flex-wrap gap-3 flex-1">
|
<div class="text-sm flex flex-wrap gap-3 flex-1">
|
||||||
<div class="opacity-80"><EventTypeLabel event={e} /></div>
|
<div class="opacity-80"><EventTypeLabel event={e} /></div>
|
||||||
|
{#if schedule}
|
||||||
|
<EventSchedule item={schedule} event={e} bundle={$bundle} />
|
||||||
|
{/if}
|
||||||
{#if duration}<div class="text-xs my-auto">{duration}m</div>{/if}
|
{#if duration}<div class="text-xs my-auto">{duration}m</div>{/if}
|
||||||
{#if e.track}
|
{#if e.track}
|
||||||
<div class="text-sm my-auto">
|
<div class="text-sm my-auto">
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script>
|
||||||
|
import { format, formatDistanceToNow } from "date-fns";
|
||||||
|
import { cs } from "date-fns/locale/index.js";
|
||||||
|
|
||||||
|
export let item;
|
||||||
|
export let e;
|
||||||
|
export let bundle;
|
||||||
|
|
||||||
|
$: stage = bundle ? bundle.spec.stages.find(s => s.id === item.stage) : null
|
||||||
|
const start = new Date(item.period.start)
|
||||||
|
const end = new Date(item.period.end)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="font-semibold">{format(start, 'iiiii', { locale: cs }).toUpperCase()} {format(start, 'HH:mm')}-{format(end, 'HH:mm')} ({stage ? stage.name : 'n/a'})</div>
|
|
@ -50,6 +50,8 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex-1" />
|
||||||
{/if}
|
{/if}
|
||||||
<div
|
<div
|
||||||
class="flex lg:space-x-10 uppercase text-sm font-bold text-white flex-wrap gap-3"
|
class="flex lg:space-x-10 uppercase text-sm font-bold text-white flex-wrap gap-3"
|
||||||
|
@ -70,12 +72,12 @@
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $page.url.pathname !== '/tv'}
|
{#if $page.url.pathname !== '/tv'}
|
||||||
<a
|
<!--a
|
||||||
sveltekit:prefetch
|
sveltekit:prefetch
|
||||||
href="/tv"
|
href="/tv"
|
||||||
class="m-auto hover:text-[#E16A61] text-custom-green"
|
class="m-auto hover:text-[#E16A61] text-custom-green"
|
||||||
class:text-blue-400={$page.url.pathname === "/tv"}><i class="fa-solid fa-video mr-1.5"></i> Livestreamy</a
|
class:text-blue-400={$page.url.pathname === "/tv"}><i class="fa-solid fa-video mr-1.5"></i> Livestreamy</a
|
||||||
>
|
-->
|
||||||
{/if}
|
{/if}
|
||||||
<a
|
<a
|
||||||
sveltekit:prefetch
|
sveltekit:prefetch
|
||||||
|
@ -84,18 +86,18 @@
|
||||||
class:text-blue-400={$page.url.pathname === "/program"}>Program</a
|
class:text-blue-400={$page.url.pathname === "/program"}>Program</a
|
||||||
>
|
>
|
||||||
{#if $page.url.pathname !== '/tv'}
|
{#if $page.url.pathname !== '/tv'}
|
||||||
<a
|
<!--a
|
||||||
sveltekit:prefetch
|
sveltekit:prefetch
|
||||||
href="/mapa"
|
href="/mapa"
|
||||||
class="m-auto hover:text-[#E16A61]"
|
class="m-auto hover:text-[#E16A61]"
|
||||||
class:text-blue-400={$page.url.pathname === "/mapa"}>Mapa</a
|
class:text-blue-400={$page.url.pathname === "/mapa"}>Mapa</a
|
||||||
>
|
-->
|
||||||
<a
|
<!--a
|
||||||
sveltekit:prefetch
|
sveltekit:prefetch
|
||||||
href="/prakticke"
|
href="/prakticke"
|
||||||
class="m-auto hover:text-[#E16A61]"
|
class="m-auto hover:text-[#E16A61]"
|
||||||
class:text-blue-400={$page.url.pathname === "/prakticke"}>Praktické</a
|
class:text-blue-400={$page.url.pathname === "/prakticke"}>Praktické</a
|
||||||
>
|
-->
|
||||||
<a
|
<a
|
||||||
sveltekit:prefetch
|
sveltekit:prefetch
|
||||||
href="/vstupenky"
|
href="/vstupenky"
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const orderTicketForm = writable({
|
||||||
count: 1,
|
count: 1,
|
||||||
email: '',
|
email: '',
|
||||||
tickets: [],
|
tickets: [],
|
||||||
paymentMethod: 'btcpay',
|
paymentMethod: 'card',
|
||||||
tipPercent: 10,
|
tipPercent: 10,
|
||||||
tipCustom: '',
|
tipCustom: '',
|
||||||
__v: 2
|
__v: 2
|
||||||
|
|
|
@ -0,0 +1,355 @@
|
||||||
|
<script context="module">
|
||||||
|
export const prerender = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount, onDestroy } from "svelte";
|
||||||
|
import { format, compareAsc, compareDesc } from "date-fns";
|
||||||
|
import { bundle, userData, loadInfo, schedulePref } from "$lib/stores.js";
|
||||||
|
import { cs } from "date-fns/locale/index.js";
|
||||||
|
|
||||||
|
let planNumber = 0;
|
||||||
|
$: plan = $bundle ? $bundle.spec["schedule-candidates"][planNumber] : null;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
bundle.subscribe((bundle) => {
|
||||||
|
const pref = {};
|
||||||
|
pref.stages = bundle.spec.stages.map((s) => s.id);
|
||||||
|
pref.tracks = bundle.spec.tracks.map((s) => s.id);
|
||||||
|
schedulePref.set(pref);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function filterDateStage(arr, date, stageId) {
|
||||||
|
return arr
|
||||||
|
.filter((i) => i.date === date)
|
||||||
|
.filter((i) => i.stage === stageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSegment(bundle, stage, period) {
|
||||||
|
for (const st of stage.times) {
|
||||||
|
const p = parsePeriod(bundle, st);
|
||||||
|
if (
|
||||||
|
compareAsc(period.start, p.period.end) !== -1 &&
|
||||||
|
compareDesc(period.end, p.period.start) !== 1
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dateSlots(pl, period, bundle, schedulePref = null) {
|
||||||
|
let time = period.start;
|
||||||
|
const endTime = period.end;
|
||||||
|
const arr = [];
|
||||||
|
const rowspans = {};
|
||||||
|
|
||||||
|
while (compareAsc(time, endTime) === -1) {
|
||||||
|
const stages = {};
|
||||||
|
for (const stage of bundle.spec.stages) {
|
||||||
|
if (rowspans[stage.id] > 0) {
|
||||||
|
stages[stage.id] = null;
|
||||||
|
rowspans[stage.id]--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (schedulePref && !schedulePref.stages.includes(stage.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let si = pl.schedule.find(
|
||||||
|
(pi) =>
|
||||||
|
new Date(pi.period.start).getTime() === new Date(time).getTime() &&
|
||||||
|
pi.stage === stage.id
|
||||||
|
);
|
||||||
|
stages[stage.id] = si;
|
||||||
|
|
||||||
|
if (si) {
|
||||||
|
const span = Math.floor(
|
||||||
|
(new Date(si.period.end).getTime() -
|
||||||
|
new Date(si.period.start).getTime()) /
|
||||||
|
(1000 * 60) /
|
||||||
|
30
|
||||||
|
);
|
||||||
|
si.span = span;
|
||||||
|
if (span > 1) {
|
||||||
|
rowspans[stage.id] = span - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr.push({ title: format(time, "HH:mm"), stages });
|
||||||
|
time = new Date(time.getTime() + 30 * 60 * 1000);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSpeakers(bundle, ev) {
|
||||||
|
return ev.speakers
|
||||||
|
.map((sId) => {
|
||||||
|
const sp = bundle.spec.speakers.find((s) => s.id === sId);
|
||||||
|
return sp.name + (sp.nickname ? ` (${sp.nickname})` : "");
|
||||||
|
})
|
||||||
|
.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEventDetail(bundle, ev) {
|
||||||
|
if (ev.type === "lightning-series") {
|
||||||
|
return bundle.spec.events
|
||||||
|
.filter((e) => e.parent === ev.id)
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
`<span class="font-semibold"><a href="/udalosti?id=${e.id}">${
|
||||||
|
e.name
|
||||||
|
}</a></span> - ${showSpeakers(bundle, e) || "TBD"}`
|
||||||
|
)
|
||||||
|
.join("<br>");
|
||||||
|
}
|
||||||
|
return showSpeakers(bundle, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePeriod(bundle, str) {
|
||||||
|
const [dayNumber, times] = str.split("/");
|
||||||
|
const [start, end] = times.split("-");
|
||||||
|
const date = bundle.dates[dayNumber - 1];
|
||||||
|
return {
|
||||||
|
date,
|
||||||
|
period: {
|
||||||
|
start: new Date(`${date}T${start}`),
|
||||||
|
end: new Date(`${date}T${end}`),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleTimes(bundle) {
|
||||||
|
return bundle.scheduleTimes.map((item) => {
|
||||||
|
return parsePeriod(bundle, item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventTrackClasses(bundle, ev, selectedTracks) {
|
||||||
|
if (!selectedTracks.includes(ev.track || "")) {
|
||||||
|
return "opacity-20";
|
||||||
|
}
|
||||||
|
return "border border-blue-web/50";
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeStages (bundle, stages, day, pl) {
|
||||||
|
return stages.filter(stage => {
|
||||||
|
const dt = format(new Date(day), 'yyyy-MM-dd')
|
||||||
|
return Boolean(pl.schedule.filter(i => i.stage === stage.id).find(i => i.date === dt)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function findEvent(bundle, eventId) {
|
||||||
|
const ev = bundle.spec.events.find((ev) => ev.id === eventId);
|
||||||
|
if (!ev) {
|
||||||
|
console.log(`Event not found: ${eventId}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (ev.type) {
|
||||||
|
case "panel":
|
||||||
|
ev.color = "bg-orange-400/20 hover:bg-orange-400/40";
|
||||||
|
break;
|
||||||
|
case "talk":
|
||||||
|
ev.color = "bg-custom-green/20 hover:bg-custom-green/40";
|
||||||
|
break;
|
||||||
|
case "workshop":
|
||||||
|
ev.color = "bg-custom-blue/20 hover:bg-custom-blue/40";
|
||||||
|
break;
|
||||||
|
case "campfire":
|
||||||
|
ev.color = "bg-purple-400/20 hover:bg-purple-400/40";
|
||||||
|
break;
|
||||||
|
case "lightning-series":
|
||||||
|
ev.color = "bg-yellow-400/20 hover:bg-yellow-400/40";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ev.color = "bg-rose-400/20 hover:bg-rose-400/40";
|
||||||
|
}
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Časová osa | UTXO.22</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<section
|
||||||
|
class="relative mx-auto pt-6 sm:pt-10 pb-6 px-6 max-w-6xl text-blue-web"
|
||||||
|
>
|
||||||
|
<h1 class="uppercase text-2xl font-bold mb-6">Časová osa</h1>
|
||||||
|
{#if $bundle}
|
||||||
|
<div class="font-semibold uppercase mb-1">Plán (řešení)</div>
|
||||||
|
<div class="flex flex-wrap gap-1">
|
||||||
|
<select
|
||||||
|
class="border border-blue-web rounded-md p-1.5 text-blue-web bg-white"
|
||||||
|
bind:value={planNumber}
|
||||||
|
>
|
||||||
|
{#each $bundle.spec["schedule-candidates"] as p, i}
|
||||||
|
<option value={i}
|
||||||
|
>#{i} [{["score", "thc:themeCrossing", "tgc:tagsCrossing", "exd:exclusivityDev"]
|
||||||
|
.map((key) => {
|
||||||
|
const [title, rkey] = key.split(":");
|
||||||
|
return `${title}:${
|
||||||
|
Math.round(p.metrics[rkey || title] * 1000) / 1000
|
||||||
|
}`;
|
||||||
|
})
|
||||||
|
.join(", ")}]</option
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
<section class="relative mx-auto pb-6 sm:pb-10 px-0 text-blue-web">
|
||||||
|
{#if $bundle}
|
||||||
|
<div class="max-w-6xl mx-auto px-6 mb-10">
|
||||||
|
<div class="">
|
||||||
|
<div class="font-semibold uppercase mb-1">Sál / Místo</div>
|
||||||
|
<div class="flex gap-1 flex-wrap">
|
||||||
|
<div class="m-0.5">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:underline"
|
||||||
|
on:click={() =>
|
||||||
|
($schedulePref.stages = $bundle.spec.stages.map((s) => s.id))}
|
||||||
|
>Všechny sály</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{#each $bundle.spec.stages as et}
|
||||||
|
<div class="u-choose-div m-0.5">
|
||||||
|
<label class="cursor-pointer"
|
||||||
|
><input
|
||||||
|
type="checkbox"
|
||||||
|
bind:group={$schedulePref.stages}
|
||||||
|
value={et.id}
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cursor-pointer"
|
||||||
|
on:click={() => ($schedulePref.stages = [et.id])}
|
||||||
|
>{et.name}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<div class="font-semibold uppercase mb-1">Kategorie</div>
|
||||||
|
<div class="flex gap-2 flex-wrap">
|
||||||
|
<div class="m-0.5">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:underline"
|
||||||
|
on:click={() =>
|
||||||
|
($schedulePref.tracks = $bundle.spec.tracks.map((s) => s.id))}
|
||||||
|
>Všechny kategorie</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{#each $bundle.spec.tracks as et}
|
||||||
|
<div class="u-choose-div m-0.5">
|
||||||
|
<label class="cursor-pointer"
|
||||||
|
><input
|
||||||
|
type="checkbox"
|
||||||
|
bind:group={$schedulePref.tracks}
|
||||||
|
value={et.id}
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cursor-pointer"
|
||||||
|
on:click={() => ($schedulePref.tracks = [et.id])}
|
||||||
|
>
|
||||||
|
{et.shortname || et.name}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#each scheduleTimes($bundle) as st}
|
||||||
|
<div class="max-w-6xl mx-auto px-6 mb-4">
|
||||||
|
<h2 class="uppercase text-xl font-bold">
|
||||||
|
{format(new Date(st.date), "iiii d.M.y", { locale: cs })}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="mt-4 mb-10 overflow-scroll sm:overflow-clip">
|
||||||
|
<table width="100%" class="table table-auto xl:table-fixed relative">
|
||||||
|
<thead class="">
|
||||||
|
<tr>
|
||||||
|
<th class="xl:w-16" />
|
||||||
|
{#each activeStages($bundle, $bundle.spec.stages, st.date, plan) as stage}
|
||||||
|
{#if $schedulePref && $schedulePref.stages.includes(stage.id)}
|
||||||
|
<th class="text-md py-1.5 px-1 sticky top-0 bg-white align-bottom">
|
||||||
|
<div class="text-xs font-normal text-blue-web/60 mb-2.5">{stage.capacity.seat} <i class="fa-solid fa-chair"></i> + {stage.capacity.stand} <i class="fa-solid fa-person"></div>
|
||||||
|
<div>{stage.name}</div>
|
||||||
|
</th>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each dateSlots(plan, st.period, $bundle, $schedulePref) as ds}
|
||||||
|
<tr class="bg-gray-100">
|
||||||
|
<th
|
||||||
|
valign="top"
|
||||||
|
class="w-auto pl-2 pr-2 pt-1 text-sm sticky left-0 bg-white"
|
||||||
|
height="110">{ds.title}</th
|
||||||
|
>
|
||||||
|
{#each activeStages($bundle, $bundle.spec.stages, st.date, plan) as stage}
|
||||||
|
{#if $schedulePref && $schedulePref.stages.includes(stage.id)}
|
||||||
|
{#if ds.stages[stage.id] === undefined}
|
||||||
|
<td />
|
||||||
|
{:else if ds.stages[stage.id] !== null}
|
||||||
|
{#each [[ds.stages[stage.id], findEvent($bundle, ds.stages[stage.id].event)]] as [si, event]}
|
||||||
|
<td
|
||||||
|
class="text-sm h-full transition-all {event.color} {eventTrackClasses(
|
||||||
|
$bundle,
|
||||||
|
event,
|
||||||
|
$schedulePref.tracks
|
||||||
|
)}"
|
||||||
|
valign="top"
|
||||||
|
rowspan={ds.stages[stage.id].span}
|
||||||
|
>
|
||||||
|
<div class="px-2 py-1 mb-1 mt-1">
|
||||||
|
<div class="text-xs">
|
||||||
|
{format(
|
||||||
|
new Date(si.period.start),
|
||||||
|
"HH:mm"
|
||||||
|
)}-{format(new Date(si.period.end), "HH:mm")} <span class="opacity-70">@{si.id}</span>
|
||||||
|
{#if event.track}[{#each [$bundle.spec.tracks.find((t) => t.id === event.track)] as track}{track.shortname ||
|
||||||
|
track.name}{/each}]{/if}
|
||||||
|
</div>
|
||||||
|
<div class="font-semibold mt-1">
|
||||||
|
<a href="/udalosti?id={event.id}"
|
||||||
|
>{event.name}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs mt-1">
|
||||||
|
{@html showEventDetail($bundle, event)}
|
||||||
|
</div>
|
||||||
|
<div class="text-xs mt-2 text-blue-web/50">
|
||||||
|
{event.tags.map((t) => `#${t}`).join(", ")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
<!--th valign="top" class="pl-2 pt-1 text-sm" height="70">{ds.title}</th-->
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
Načítám ..
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
|
@ -0,0 +1,491 @@
|
||||||
|
<script context="module">
|
||||||
|
export const prerender = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount, onDestroy } from "svelte";
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { format, compareAsc, compareDesc } from "date-fns";
|
||||||
|
import { bundle, userData, loadInfo, schedulePref } from "$lib/stores.js";
|
||||||
|
import { cs } from "date-fns/locale/index.js";
|
||||||
|
import { parsePeriod } from '$lib/periods.js';
|
||||||
|
import SvelteMarkdown from "svelte-markdown";
|
||||||
|
const renderers = { link: Link };
|
||||||
|
import Link from "$lib/Link.svelte";
|
||||||
|
|
||||||
|
let scheduleTimesArr = null
|
||||||
|
let stagesArr = null
|
||||||
|
|
||||||
|
let planNumber = 0;
|
||||||
|
$: plan = $bundle ? $bundle.spec["schedule-candidates"][planNumber] : null;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
time: { key: 'time' },
|
||||||
|
stage: { key: 'stage' },
|
||||||
|
desc: { key: 'showDescriptions', type: 'boolean' }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let subs = []
|
||||||
|
|
||||||
|
subs.push(page.subscribe(() => {
|
||||||
|
|
||||||
|
schedulePref.update(sp => {
|
||||||
|
for (const upk of Object.keys(params)) {
|
||||||
|
const up = params[upk]
|
||||||
|
const _sp = $page.url.searchParams.get(upk)
|
||||||
|
if (up.type === 'boolean') {
|
||||||
|
if (_sp !== undefined) {
|
||||||
|
sp[up.key] = Boolean(_sp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sp[up.key] = _sp ? _sp : 'all'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sp
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
|
||||||
|
const bsub = bundle.subscribe((bundle) => {
|
||||||
|
|
||||||
|
scheduleTimesArr = scheduleTimes(bundle)
|
||||||
|
stagesArr = bundle.spec.stages
|
||||||
|
const pref = {};
|
||||||
|
//pref.stages = bundle.spec.stages.map((s) => s.id);
|
||||||
|
//pref.tracks = bundle.spec.tracks.map((s) => s.id);
|
||||||
|
//pref.times = scheduleTimesArr.map((s) => s.id);
|
||||||
|
//schedulePref.set(pref);
|
||||||
|
});
|
||||||
|
subs.push(bsub)
|
||||||
|
|
||||||
|
const pref = {}
|
||||||
|
let schedulePrefInicialized = null
|
||||||
|
|
||||||
|
const spsub = schedulePref.subscribe((sp) => {
|
||||||
|
const updates = []
|
||||||
|
updates.push([ 'time', sp.time === 'all' ? undefined : sp.time ])
|
||||||
|
updates.push([ 'stage', sp.stage === 'all' ? undefined : sp.stage ])
|
||||||
|
updates.push([ 'desc', sp.showDescriptions === null || sp.showDescriptions === false || sp.showDescriptions === undefined ? undefined : true ])
|
||||||
|
|
||||||
|
let target = '?'
|
||||||
|
if (updates.length > 0) {
|
||||||
|
for (const up of updates) {
|
||||||
|
if (up[1] === undefined && $page.url.searchParams.get(up[0]) !== undefined) {
|
||||||
|
$page.url.searchParams.delete(up[0])
|
||||||
|
} else {
|
||||||
|
$page.url.searchParams.set(up[0], up[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target = `?${$page.url.searchParams.toString()}`
|
||||||
|
}
|
||||||
|
goto(target);
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
subs.push(spsub)
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
for (const unsub of subs) {
|
||||||
|
unsub()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function filterDateStage(arr, date, stageId) {
|
||||||
|
return arr
|
||||||
|
.filter((i) => i.date === date)
|
||||||
|
.filter((i) => i.stage === stageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSegment(bundle, stage, period) {
|
||||||
|
for (const st of stage.times) {
|
||||||
|
const p = parsePeriod(bundle, st);
|
||||||
|
if (
|
||||||
|
compareAsc(period.start, p.period.end) !== -1 &&
|
||||||
|
compareDesc(period.end, p.period.start) !== 1
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dateSlots(pl, period, bundle, schedulePref = null) {
|
||||||
|
let time = period.start;
|
||||||
|
const endTime = period.end;
|
||||||
|
const arr = [];
|
||||||
|
const rowspans = {};
|
||||||
|
|
||||||
|
while (compareAsc(time, endTime) === -1) {
|
||||||
|
const stages = {};
|
||||||
|
for (const stage of bundle.spec.stages) {
|
||||||
|
if (rowspans[stage.id] > 0) {
|
||||||
|
stages[stage.id] = null;
|
||||||
|
rowspans[stage.id]--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (schedulePref && (schedulePref.stage !== stage.id && schedulePref.stage !== 'all')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let si = pl.schedule.find(
|
||||||
|
(pi) =>
|
||||||
|
new Date(pi.period.start).getTime() === new Date(time).getTime() &&
|
||||||
|
pi.stage === stage.id
|
||||||
|
);
|
||||||
|
stages[stage.id] = si;
|
||||||
|
|
||||||
|
if (si) {
|
||||||
|
const span = Math.floor(
|
||||||
|
(new Date(si.period.end).getTime() -
|
||||||
|
new Date(si.period.start).getTime()) /
|
||||||
|
(1000 * 60) /
|
||||||
|
30
|
||||||
|
);
|
||||||
|
si.span = span;
|
||||||
|
if (span > 1) {
|
||||||
|
rowspans[stage.id] = span - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr.push({ title: format(time, "HH:mm"), stages });
|
||||||
|
time = new Date(time.getTime() + 30 * 60 * 1000);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSpeakers(bundle, ev) {
|
||||||
|
return ev.speakers
|
||||||
|
.map((sId) => {
|
||||||
|
const sp = bundle.spec.speakers.find((s) => s.id === sId);
|
||||||
|
return sp.name + (sp.nickname ? ` (${sp.nickname})` : "");
|
||||||
|
})
|
||||||
|
.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEventDetail(bundle, ev) {
|
||||||
|
if (ev.type === "lightning-series") {
|
||||||
|
return bundle.spec.events
|
||||||
|
.filter((e) => e.parent === ev.id)
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
`<span class="font-semibold"><a href="/udalosti?id=${e.id}">${
|
||||||
|
e.name
|
||||||
|
}</a></span> - ${showSpeakers(bundle, e) || "TBD"}`
|
||||||
|
)
|
||||||
|
.join("<br>");
|
||||||
|
}
|
||||||
|
return showSpeakers(bundle, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleTimes(bundle, filter = false) {
|
||||||
|
let arr = bundle.scheduleTimes.map((item, i) => {
|
||||||
|
const out = parsePeriod(bundle, item);
|
||||||
|
out.id = String(i)
|
||||||
|
return out
|
||||||
|
});
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
arr = arr.filter(st => st.id === filter || filter === 'all')
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
function eventTrackClasses(bundle, ev, selectedTracks) {
|
||||||
|
/*if (!selectedTracks.includes(ev.track || "")) {
|
||||||
|
return "opacity-20";
|
||||||
|
}*/
|
||||||
|
return "border border-blue-web/50";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPeriodOverlap(x, y) {
|
||||||
|
const xstart = new Date(x.start)
|
||||||
|
const xend = new Date(x.end)
|
||||||
|
const ystart = new Date(y.start)
|
||||||
|
const yend = new Date(y.end)
|
||||||
|
return (xstart.getTime() < yend.getTime() &&
|
||||||
|
xend.getTime() > ystart.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeStages (bundle, stages, st, pl) {
|
||||||
|
return stages.filter(stage => {
|
||||||
|
return Boolean(pl.schedule.filter(i => i.stage === stage.id).find(i => isPeriodOverlap(st.period, i.period))
|
||||||
|
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function allScheduleTimes (bundle) {
|
||||||
|
return [
|
||||||
|
{ id: 'all', name: 'Všechny dny' },
|
||||||
|
...scheduleTimes(bundle)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function allStages (bundle) {
|
||||||
|
return [
|
||||||
|
{ id: 'all', name: 'Všechny sály' },
|
||||||
|
...bundle.spec.stages
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSpoiler(_e) {
|
||||||
|
if (!_e.description) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const parts = _e.description.split("\n\n");
|
||||||
|
const stripped = parts.length > 1;
|
||||||
|
return {
|
||||||
|
md: parts[0], // + ` ([Zobrazit celý popis](/udalosti?id=${_e.id}))`,
|
||||||
|
stripped,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function findEvent(bundle, eventId) {
|
||||||
|
const ev = bundle.spec.events.find((ev) => ev.id === eventId);
|
||||||
|
if (!ev) {
|
||||||
|
console.log(`Event not found: ${eventId}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (ev.type) {
|
||||||
|
case "panel":
|
||||||
|
ev.color = "bg-orange-400/20 hover:bg-orange-400/40";
|
||||||
|
break;
|
||||||
|
case "talk":
|
||||||
|
ev.color = "bg-custom-green/20 hover:bg-custom-green/40";
|
||||||
|
break;
|
||||||
|
case "workshop":
|
||||||
|
ev.color = "bg-custom-blue/20 hover:bg-custom-blue/40";
|
||||||
|
break;
|
||||||
|
case "campfire":
|
||||||
|
ev.color = "bg-purple-400/20 hover:bg-purple-400/40";
|
||||||
|
break;
|
||||||
|
case "lightning-series":
|
||||||
|
ev.color = "bg-yellow-400/20 hover:bg-yellow-400/40";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ev.color = "bg-rose-400/20 hover:bg-rose-400/40";
|
||||||
|
}
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Program | UTXO.22</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<section
|
||||||
|
class="relative mx-auto pt-6 sm:pt-10 pb-6 px-6 max-w-6xl text-blue-web print:hidden"
|
||||||
|
>
|
||||||
|
<div class="mb-6">
|
||||||
|
{#if $bundle}
|
||||||
|
<div class="font-semibold uppercase mb-1">Plán (řešení)</div>
|
||||||
|
<div class="flex flex-wrap gap-1">
|
||||||
|
<select
|
||||||
|
class="border border-blue-web rounded-md p-1.5 text-blue-web bg-white"
|
||||||
|
bind:value={planNumber}
|
||||||
|
>
|
||||||
|
{#each $bundle.spec["schedule-candidates"] as p, i}
|
||||||
|
<option value={i}
|
||||||
|
>#{i} | {p.hash.substring(0,8)} [{["score", "thc:themeCrossing", "tgc:tagsCrossing", "exd:exclusivityDev"]
|
||||||
|
.map((key) => {
|
||||||
|
const [title, rkey] = key.split(":");
|
||||||
|
return `${title}:${
|
||||||
|
Math.round(p.metrics[rkey || title] * 1000) / 1000
|
||||||
|
}`;
|
||||||
|
})
|
||||||
|
.join(", ")}]</option
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<h1 class="uppercase text-2xl font-bold mb-2">Program</h1>
|
||||||
|
<div class="mb-4">
|
||||||
|
<a href="/seznam-udalosti" class="underline hover:no-underline">Seznam všech událostí</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{#if $bundle}
|
||||||
|
<div class="mb-4">
|
||||||
|
<div class="flex gap-1 flex-wrap">
|
||||||
|
<div class="font-semibold uppercase my-auto mx-3">Den</div>
|
||||||
|
{#each allScheduleTimes($bundle) as st}
|
||||||
|
<button class="{($schedulePref.time === st.id) ? 'bg-utxo-gradient text-white' : 'text-blue-web bg-blue-web-light hover:text-[#E16A61] hover:bg-[#E16A61]/20'} font-bold py-2 px-4 rounded-full"
|
||||||
|
on:click={() => $schedulePref.time = st.id}
|
||||||
|
>{st.name}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<div class="flex gap-1 flex-wrap">
|
||||||
|
<div class="font-semibold uppercase my-auto mx-3">Sál</div>
|
||||||
|
{#each allStages($bundle) as et}
|
||||||
|
<button class="{($schedulePref.stage === et.id) ? 'bg-utxo-gradient text-white' : 'text-blue-web bg-blue-web-light hover:text-[#E16A61] hover:bg-[#E16A61]/20'} font-bold py-1.5 px-3 rounded-full text-sm"
|
||||||
|
on:click={() => $schedulePref.stage = et.id}
|
||||||
|
>{et.name}</button>
|
||||||
|
<!--div class="u-choose-div m-0.5">
|
||||||
|
<label class="cursor-pointer"
|
||||||
|
><input
|
||||||
|
type="checkbox"
|
||||||
|
bind:group={$schedulePref.stages}
|
||||||
|
value={et.id}
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cursor-pointer"
|
||||||
|
on:click={() => ($schedulePref.stages = [et.id])}
|
||||||
|
>{et.name}</span
|
||||||
|
>
|
||||||
|
</div-->
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label><input type="checkbox" bind:checked={$schedulePref.showDescriptions} /> Zobrazit popisy</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--div class="mb-4">
|
||||||
|
<div class="font-semibold uppercase mb-1">Kategorie</div>
|
||||||
|
<div class="flex gap-2 flex-wrap">
|
||||||
|
<div class="m-0.5">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:underline"
|
||||||
|
on:click={() =>
|
||||||
|
($schedulePref.tracks = $bundle.spec.tracks.map((s) => s.id))}
|
||||||
|
>Všechny kategorie</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{#each $bundle.spec.tracks as et}
|
||||||
|
<div class="u-choose-div m-0.5">
|
||||||
|
<label class="cursor-pointer"
|
||||||
|
><input
|
||||||
|
type="checkbox"
|
||||||
|
bind:group={$schedulePref.tracks}
|
||||||
|
value={et.id}
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cursor-pointer"
|
||||||
|
on:click={() => ($schedulePref.tracks = [et.id])}
|
||||||
|
>
|
||||||
|
{et.shortname || et.name}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div-->
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<section class="relative mx-auto pb-6 sm:pb-10 px-0 text-blue-web">
|
||||||
|
{#if $bundle}
|
||||||
|
{#each scheduleTimes($bundle, $schedulePref.time) as st}
|
||||||
|
<div class="max-w-6xl mx-auto px-6 mb-4 print:max-w-full">
|
||||||
|
<h2 class="uppercase text-xl font-bold">
|
||||||
|
{#if st.name}
|
||||||
|
{st.name}
|
||||||
|
{:else}
|
||||||
|
{format(new Date(st.date), "iiii d.M.y", { locale: cs })}
|
||||||
|
{/if}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="mt-4 mb-10 overflow-scroll sm:overflow-clip">
|
||||||
|
<table width="100%" class="table table-auto xl:table-fixed relative">
|
||||||
|
<thead class="">
|
||||||
|
<tr>
|
||||||
|
<th class="xl:w-16 top-0 sticky bg-white uppercase text-sm px-0.5 text-custom-blue">{format(new Date(st.date), "iiiiii", { locale: cs })}<br />{format(new Date(st.date), "d.M.")}</th>
|
||||||
|
{#each activeStages($bundle, $bundle.spec.stages, st, plan) as stage}
|
||||||
|
{#if $schedulePref && ($schedulePref.stage === stage.id || $schedulePref.stage === 'all')}
|
||||||
|
<th class="text-md py-1.5 px-1 sticky top-0 bg-white align-bottom">
|
||||||
|
<div class="text-xs font-normal text-blue-web/60 mb-2.5">{stage.capacity.seat} <i class="fa-solid fa-chair"></i> + {stage.capacity.stand} <i class="fa-solid fa-person"></div>
|
||||||
|
<div>{stage.name}</div>
|
||||||
|
</th>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each dateSlots(plan, st.period, $bundle, $schedulePref) as ds}
|
||||||
|
<tr class="bg-gray-100">
|
||||||
|
<th
|
||||||
|
valign="top"
|
||||||
|
class="w-auto pl-2 pr-2 pt-1 text-sm left-0 bg-white"
|
||||||
|
height="60">{ds.title}</th
|
||||||
|
>
|
||||||
|
{#each activeStages($bundle, $bundle.spec.stages, st, plan) as stage}
|
||||||
|
{#if $schedulePref && ($schedulePref.stage === stage.id || $schedulePref.stage === 'all')}
|
||||||
|
{#if ds.stages[stage.id] === undefined}
|
||||||
|
<td />
|
||||||
|
{:else if ds.stages[stage.id] !== null}
|
||||||
|
{#each [[ds.stages[stage.id], findEvent($bundle, ds.stages[stage.id].event)]] as [si, event]}
|
||||||
|
<td
|
||||||
|
class="text-sm h-full transition-all {event.color} {eventTrackClasses(
|
||||||
|
$bundle,
|
||||||
|
event,
|
||||||
|
$schedulePref.tracks
|
||||||
|
)}"
|
||||||
|
valign="top"
|
||||||
|
rowspan={ds.stages[stage.id].span}
|
||||||
|
>
|
||||||
|
<div class="px-2 py-1 mb-1 mt-1">
|
||||||
|
<div class="text-xs">
|
||||||
|
{format(
|
||||||
|
new Date(si.period.start),
|
||||||
|
"HH:mm"
|
||||||
|
)}-{format(new Date(si.period.end), "HH:mm")} <span class="text-blue-web/80">@{si.id}</span>
|
||||||
|
{#if event.track}[{#each [$bundle.spec.tracks.find((t) => t.id === event.track)] as track}{track.shortname ||
|
||||||
|
track.name}{/each}]{/if}
|
||||||
|
</div>
|
||||||
|
<div class="font-semibold mt-1">
|
||||||
|
<a href="/udalosti?id={event.id}" class="hover:underline"
|
||||||
|
>{event.name}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs mt-1">
|
||||||
|
{@html showEventDetail($bundle, event)}
|
||||||
|
</div>
|
||||||
|
<div class="text-xs mt-2 text-blue-web/50">
|
||||||
|
{event.tags.map((t) => `#${t}`).join(", ")}
|
||||||
|
</div>
|
||||||
|
{#if event.description && $schedulePref.showDescriptions}
|
||||||
|
{#each [makeSpoiler(event)] as spoiler}
|
||||||
|
<div class="mt-2 overflow-hidden text-sm text-blue-web/90">
|
||||||
|
<SvelteMarkdown source={spoiler.md} {renderers} />
|
||||||
|
{#if spoiler.stripped}
|
||||||
|
<div class="text-xs text-blue-web/60">
|
||||||
|
(<a href="/udalosti?id={event.id}">Zobrazit celý popis</a>)
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
<!--th valign="top" class="pl-2 pt-1 text-sm" height="70">{ds.title}</th-->
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
Načítám ..
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
|
@ -18,7 +18,7 @@
|
||||||
let stagesArr = null
|
let stagesArr = null
|
||||||
|
|
||||||
let planNumber = 0;
|
let planNumber = 0;
|
||||||
$: plan = $bundle ? $bundle.spec["schedule-candidates"][planNumber] : null;
|
$: plan = $bundle ? $bundle.spec.schedule : null;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
time: { key: 'time' },
|
time: { key: 'time' },
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
if (schedulePref && (schedulePref.stage !== stage.id && schedulePref.stage !== 'all')) {
|
if (schedulePref && (schedulePref.stage !== stage.id && schedulePref.stage !== 'all')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let si = pl.schedule.find(
|
let si = pl.find(
|
||||||
(pi) =>
|
(pi) =>
|
||||||
new Date(pi.period.start).getTime() === new Date(time).getTime() &&
|
new Date(pi.period.start).getTime() === new Date(time).getTime() &&
|
||||||
pi.stage === stage.id
|
pi.stage === stage.id
|
||||||
|
@ -214,7 +214,7 @@
|
||||||
|
|
||||||
function activeStages (bundle, stages, st, pl) {
|
function activeStages (bundle, stages, st, pl) {
|
||||||
return stages.filter(stage => {
|
return stages.filter(stage => {
|
||||||
return Boolean(pl.schedule.filter(i => i.stage === stage.id).find(i => isPeriodOverlap(st.period, i.period))
|
return Boolean(pl.filter(i => i.stage === stage.id).find(i => isPeriodOverlap(st.period, i.period))
|
||||||
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -282,30 +282,6 @@
|
||||||
<section
|
<section
|
||||||
class="relative mx-auto pt-6 sm:pt-10 pb-6 px-6 max-w-6xl text-blue-web print:hidden"
|
class="relative mx-auto pt-6 sm:pt-10 pb-6 px-6 max-w-6xl text-blue-web print:hidden"
|
||||||
>
|
>
|
||||||
<div class="mb-6">
|
|
||||||
{#if $bundle}
|
|
||||||
<div class="font-semibold uppercase mb-1">Plán (řešení)</div>
|
|
||||||
<div class="flex flex-wrap gap-1">
|
|
||||||
<select
|
|
||||||
class="border border-blue-web rounded-md p-1.5 text-blue-web bg-white"
|
|
||||||
bind:value={planNumber}
|
|
||||||
>
|
|
||||||
{#each $bundle.spec["schedule-candidates"] as p, i}
|
|
||||||
<option value={i}
|
|
||||||
>#{i} | {p.hash.substring(0,8)} [{["score", "thc:themeCrossing", "tgc:tagsCrossing", "exd:exclusivityDev"]
|
|
||||||
.map((key) => {
|
|
||||||
const [title, rkey] = key.split(":");
|
|
||||||
return `${title}:${
|
|
||||||
Math.round(p.metrics[rkey || title] * 1000) / 1000
|
|
||||||
}`;
|
|
||||||
})
|
|
||||||
.join(", ")}]</option
|
|
||||||
>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<h1 class="uppercase text-2xl font-bold mb-2">Program</h1>
|
<h1 class="uppercase text-2xl font-bold mb-2">Program</h1>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<a href="/seznam-udalosti" class="underline hover:no-underline">Seznam všech událostí</a>
|
<a href="/seznam-udalosti" class="underline hover:no-underline">Seznam všech událostí</a>
|
||||||
|
|
|
@ -163,9 +163,8 @@
|
||||||
<h1 class="uppercase text-2xl font-bold"><a href="/program">Program</a> → Seznam událostí</h1>
|
<h1 class="uppercase text-2xl font-bold"><a href="/program">Program</a> → Seznam událostí</h1>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<p>
|
<p>
|
||||||
Program <a href="/changelog" class="underline hover:no-underline"
|
<a href="/program" class="underline hover:no-underline">Časový rozpis (program)</a>
|
||||||
>stále připravujeme</a
|
| <a href="/changelog" class="underline hover:no-underline">Changelog</a>
|
||||||
>. Aktuálně finišujeme jeho přípravu a <span class="font-semibold">nejpozději ráno v pondělí 30. května zde najdete konkrétní časové rozpisy jednotlivých sálů</span>. Těšíme se na vás! 🙏❤️ - <span class="italic">UTXO.22 organizační team</span>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<!--div class="mt-6 flex flex-wrap gap-3 px-4 text-center">
|
<!--div class="mt-6 flex flex-wrap gap-3 px-4 text-center">
|
||||||
|
@ -183,10 +182,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div-->
|
</div-->
|
||||||
|
|
||||||
<div class="mt-6 bg-custom-green/30 rounded-lg px-4 py-3">
|
<!--div class="mt-6 bg-custom-green/30 rounded-lg px-4 py-3">
|
||||||
<span class="font-semibold">🔥 Chcete kryptokomunitě něco říct? prezentovat svůj projekt nebo nápad? nebo snad prodiskutovat nějaké krypto téma? Každopádně potkat nové lidi?</span> Uspořádejte <a href="https://docs.utxo.cz/hlavni-program/formaty-programu#campfire-taborovy-ohen" target="_blank" class="font-semibold">Campfire session</a>! Jde o náš nový formát, kterým chceme dát možnost doplnit obsah na UTXO.22 i široké komunitě.<br/>
|
<span class="font-semibold">🔥 Chcete kryptokomunitě něco říct? prezentovat svůj projekt nebo nápad? nebo snad prodiskutovat nějaké krypto téma? Každopádně potkat nové lidi?</span> Uspořádejte <a href="https://docs.utxo.cz/hlavni-program/formaty-programu#campfire-taborovy-ohen" target="_blank" class="font-semibold">Campfire session</a>! Jde o náš nový formát, kterým chceme dát možnost doplnit obsah na UTXO.22 i široké komunitě.<br/>
|
||||||
Detaily o Campfire formátu a přihlášku naleznete <a href="https://docs.google.com/forms/d/e/1FAIpQLScYh21d2z3sVDXyE9b15HxG0fabTiW5jJ8qJlAJT_w_j4v23w/viewform?usp=sf_link" target="_blank" class="underline hover:no-underline">na tomto odkazu</a>.
|
Detaily o Campfire formátu a přihlášku naleznete <a href="https://docs.google.com/forms/d/e/1FAIpQLScYh21d2z3sVDXyE9b15HxG0fabTiW5jJ8qJlAJT_w_j4v23w/viewform?usp=sf_link" target="_blank" class="underline hover:no-underline">na tomto odkazu</a>.
|
||||||
</div>
|
</div-->
|
||||||
|
|
||||||
{#if filters.length > 0}
|
{#if filters.length > 0}
|
||||||
<div class="mt-6 flex flex-wrap gap-3">
|
<div class="mt-6 flex flex-wrap gap-3">
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle.subscribe(_bundle => {
|
bundle.subscribe(_bundle => {
|
||||||
events = _bundle.spec['schedule-candidates'][0].schedule
|
events = _bundle.spec.schedule
|
||||||
cachedBundle = _bundle
|
cachedBundle = _bundle
|
||||||
genStatus(cachedBundle)
|
genStatus(cachedBundle)
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import SvelteMarkdown from "svelte-markdown";
|
import SvelteMarkdown from "svelte-markdown";
|
||||||
import Link from "$lib/Link.svelte";
|
import Link from "$lib/Link.svelte";
|
||||||
import Paragraph from "$lib/Paragraph.svelte";
|
import Paragraph from "$lib/Paragraph.svelte";
|
||||||
|
import EventSchedule from '$lib/EventSchedule.svelte';
|
||||||
|
|
||||||
const renderers = { link: Link, paragraph: Paragraph };
|
const renderers = { link: Link, paragraph: Paragraph };
|
||||||
|
|
||||||
|
@ -23,6 +24,8 @@
|
||||||
$: duration = e ? calcDuration(e, $bundle) : null;
|
$: duration = e ? calcDuration(e, $bundle) : null;
|
||||||
$: childrens = e ? $bundle.spec.events.filter((i) => i.parent === e.id) : []
|
$: childrens = e ? $bundle.spec.events.filter((i) => i.parent === e.id) : []
|
||||||
|
|
||||||
|
$: schedule = $bundle ? $bundle.spec.schedule.find(s => s.event === id) : null
|
||||||
|
|
||||||
function getId(search) {
|
function getId(search) {
|
||||||
const searchParams = new URLSearchParams(search);
|
const searchParams = new URLSearchParams(search);
|
||||||
const cid = searchParams.get("id");
|
const cid = searchParams.get("id");
|
||||||
|
@ -60,6 +63,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-6 flex flex-wrap gap-4">
|
<div class="mb-6 flex flex-wrap gap-4">
|
||||||
<div><EventTypeLabel event={e} size="big" /></div>
|
<div><EventTypeLabel event={e} size="big" /></div>
|
||||||
|
{#if schedule}
|
||||||
|
<EventSchedule item={schedule} event={e} bundle={$bundle} />
|
||||||
|
{/if}
|
||||||
{#if duration}
|
{#if duration}
|
||||||
<div class="text-sm my-auto">{duration}m</div>
|
<div class="text-sm my-auto">{duration}m</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -637,7 +637,9 @@
|
||||||
Platební metoda: <span class="font-bold"
|
Platební metoda: <span class="font-bold"
|
||||||
>{$apiStatus.config.paymentMethods.find(
|
>{$apiStatus.config.paymentMethods.find(
|
||||||
(pm) => pm.id === order.paymentMethod
|
(pm) => pm.id === order.paymentMethod
|
||||||
).shortname}</span
|
) ? $apiStatus.config.paymentMethods.find(
|
||||||
|
(pm) => pm.id === order.paymentMethod
|
||||||
|
).shortname : 'null (?)'}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -947,7 +949,11 @@
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<div class="uppercase text-sm font-bold">Platební metoda</div>
|
<div class="uppercase text-sm font-bold">Platební metoda</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
|
{#if $apiStatus.config.paymentMethods.find(pm => pm.id === 'btcpay') && ($apiStatus.config.paymentMethods.find(pm => pm.id === 'btcpay').hidden = true)}
|
||||||
|
<div class="mb-4 text-sm">Platba pomocí BTC není dočasně k dispozici, zkuste to prosím později. Omlouváme se :(</div>
|
||||||
|
{/if}
|
||||||
{#each $apiStatus.config.paymentMethods as pm}
|
{#each $apiStatus.config.paymentMethods as pm}
|
||||||
|
{#if !pm.hidden}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="cursor-pointer"
|
<label class="cursor-pointer"
|
||||||
><input
|
><input
|
||||||
|
@ -968,6 +974,7 @@
|
||||||
/>{/if}
|
/>{/if}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Načítá se…
Odkázat v novém úkolu