Merge branch 'master' into v1.3

This commit is contained in:
tree 2022-05-30 05:13:35 +02:00
revize ff570cff4b
11 změnil soubory, kde provedl 896 přidání a 41 odebrání

Zobrazit soubor

@ -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">

Zobrazit soubor

@ -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>

Zobrazit soubor

@ -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"

Zobrazit soubor

@ -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

Zobrazit soubor

@ -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>

Zobrazit soubor

@ -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>

Zobrazit soubor

@ -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>

Zobrazit soubor

@ -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">

Zobrazit soubor

@ -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)
}) })

Zobrazit soubor

@ -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}

Zobrazit soubor

@ -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>