This commit is contained in:
tree 2022-04-26 06:39:46 +02:00
rodič fafa38863f
revize ab1dfbb174
10 změnil soubory, kde provedl 308 přidání a 257 odebrání

Zobrazit soubor

@ -34,5 +34,6 @@
})();
</script>
<!--End of Tawk.to Script-->
</body>
</html>

Zobrazit soubor

@ -13,18 +13,18 @@
$: e = event;
$: duration = calcDuration(e, $bundle);
$: spoiler = makeSpoiler(e)
$: spoiler = makeSpoiler(e);
function makeSpoiler(_e) {
if (!_e.description) {
return {}
return {};
}
const parts = _e.description.split("\n\n")
const stripped = parts.length > 1
const parts = _e.description.split("\n\n");
const stripped = parts.length > 1;
return {
md: parts[0], // + ` ([Zobrazit celý popis](/udalosti?id=${_e.id}))`,
stripped
}
stripped,
};
}
function speakersMap(arr) {
@ -77,7 +77,9 @@
<div><EventTypeLabel event={e} /></div>
{#if duration}<div class="text-xs my-auto">{duration}m</div>{/if}
{#if e.track}
<div class="text-sm my-auto"><a href="/program?track={e.track}">{trackRender(e.track)}</a></div>
<div class="text-sm my-auto">
<a href="/program?track={e.track}">{trackRender(e.track)}</a>
</div>
{/if}
{#if e.tags}
<div class="flex text-xs gap-1 my-auto text-blue-web/60">
@ -135,5 +137,4 @@
</div>
</div>
{/if}
</div>

Zobrazit soubor

@ -7,7 +7,11 @@
talk: { title: "Přednáška", style: "bg-custom-green text-white" },
workshop: { title: "Workshop", style: "bg-custom-blue text-white" },
other: { title: "Ostatní", style: "bg-custom-yellow" },
lightning: { title: "Lightning talk", style: "bg-pink-400" },
lightning: { title: "Blesková přednáška", style: "bg-pink-400" },
"lightning-series": {
title: "Pásmo bleskových přednášek",
style: "bg-pink-400",
},
};
$: current = config[event.type];

Zobrazit soubor

@ -55,7 +55,7 @@
const onWordMouseOut = (d) => dispatch("mouseout", d);
const onWordMouseMove = (d) => dispatch("mousemove", d);
let layout = null
let layout = null;
$: cwidth =
outerWidth > 1152
@ -66,7 +66,7 @@
$: cheight = cwidth < 800 ? 400 : cwidth < 500 ? 600 : 250;
async function makeLayout() {
const lid = [cwidth, cheight].join(':')
/*const lid = [cwidth, cheight].join(':')
let l = null
await layouts.update(larr => {
@ -94,11 +94,21 @@
//console.log(Object.keys(larr))
return larr
})
return l
return l*/
return cloud()
.size([cwidth, cheight])
.words(words)
.padding(padding)
.rotate(() => ~~(Math.random() * maxRotate) + minRotate)
.font(font)
.fontSize(
//(d) => Math.floor((d.count / maxWordCount) * maxFontSize)
(d) => d.count + 15
);
}
function draw(words) {
//select("#wordcloud").selectAll("*").remove();
select("#wordcloud").selectAll("*").remove();
select("#wordcloud")
.append("svg")
@ -147,7 +157,7 @@
fwidth = outerWidth;
}
}, 500);
}, 100);
}, 1);
setTimeout(() => {
drawAll();
fwidth = outerWidth;
@ -168,7 +178,7 @@
style="background-color: {backgroundColor}; width: {cwidth}px; height: {cheight}px;"
class="justify-end {show
? 'opacity-100'
: 'opacity-0'} transition transition-all"
: 'opacity-0'} transition transition-all transition-fast"
/>
</div>

Zobrazit soubor

@ -27,3 +27,5 @@ export const userDataLocal = writable({
export const layouts = writable({ test: null })
export const loadInfo = writable({ loaded: false })

Zobrazit soubor

@ -4,7 +4,7 @@
import "../app.css";
import api from "$lib/api.js";
import { page } from "$app/stores";
import { userData, userDataLocal, apiStatus } from "$lib/stores";
import { userData, userDataLocal, apiStatus, loadInfo } from "$lib/stores";
import { loadOrders, loadApiStatus } from "$lib/orders";
import { onMount, onDestroy } from "svelte";
@ -23,6 +23,10 @@
localStorage.setItem("userData", JSON.stringify(ud));
});
setTimeout(() => {
loadInfo.set({ loaded: true });
}, 300);
await loadApiStatus();
await loadOrders($userData);
});

Zobrazit soubor

@ -4,19 +4,19 @@
<script>
import Event from "$lib/Event.svelte";
import { onMount, onDestroy } from 'svelte';
import { onMount, onDestroy } from "svelte";
import { page } from "$app/stores";
import { goto } from '$app/navigation';
import { bundle, userData } from "$lib/stores.js";
import { goto } from "$app/navigation";
import { bundle, userData, loadInfo } from "$lib/stores.js";
import { calcDuration } from "$lib/events.js";
import WordCloud from "$lib/WordCloud.svelte";
import Fuse from 'fuse.js';
import Fuse from "fuse.js";
$: tags = getTags($bundle);
$: totalDuration = calcTotalDuration($bundle);
let fuse = null
let searchText = ''
let fuse = null;
let searchText = "";
function getTags(data) {
let res = {};
@ -54,95 +54,104 @@
function wordClick(e) {
const tag = e.detail.path[0].innerHTML;
if (tag) {
goto(`/program?tag=${tag}`)
goto(`/program?tag=${tag}`);
}
return true
return true;
}
$: filters = makeFilters($page, $bundle)
$: events = applyFilters(filters, $page, $bundle)
$: ids = []
$: filters = makeFilters($page, $bundle);
$: events = applyFilters(filters, $page, $bundle);
$: ids = [];
function makeFilters(pg, bd) {
const search = pg.url.searchParams
let fl = []
const search = pg.url.searchParams;
let fl = [];
// tags
if (search.get('tag')) {
fl.push({ type: 'tag', title: `Tag: #${search.get('tag')}`, key: search.get('tag') })
if (search.get("tag")) {
fl.push({
type: "tag",
title: `Tag: #${search.get("tag")}`,
key: search.get("tag"),
});
}
// tracks
if (search.get('track')) {
const track = bd.spec.tracks.find(t => t.id === search.get('track'))
if (search.get("track")) {
const track = bd.spec.tracks.find((t) => t.id === search.get("track"));
if (!track) {
return goto('/program')
return goto("/program");
}
fl.push({ type: 'track', title: `Sekce: ${track.name}`, key: track.id })
fl.push({ type: "track", title: `Sekce: ${track.name}`, key: track.id });
}
if (searchText) {
fl.push({ type: 'text', title: `Text: "${searchText}"`, key: searchText })
fl.push({
type: "text",
title: `Text: "${searchText}"`,
key: searchText,
});
}
return fl
return fl;
}
function applyFilters(fl, pg, bd) {
if (!pg || !bd) {
return []
return [];
}
let arr = bd.spec.events
let arr = bd.spec.events;
for (const f of fl) {
if (f.type === 'tag') {
arr = arr.filter(e => e.tags && e.tags.includes(f.key))
if (f.type === "tag") {
arr = arr.filter((e) => e.tags && e.tags.includes(f.key));
}
if (f.type === 'track') {
arr = arr.filter(e => e.track === f.key)
if (f.type === "track") {
arr = arr.filter((e) => e.track === f.key);
}
if (f.type === 'text') {
const sr = fuse.search(f.key)
if (f.type === "text") {
const sr = fuse.search(f.key);
if (sr.length > 0) {
arr = sr.map(sr => arr.find(i => i.id === sr.item.id)).filter(sr => sr)
arr = sr
.map((sr) => arr.find((i) => i.id === sr.item.id))
.filter((sr) => sr);
} else {
arr = []
arr = [];
}
}
}
ids = arr.map(a => a.id)
return arr
ids = arr.map((a) => a.id);
return arr;
}
bundle.subscribe(bd => {
bundle.subscribe((bd) => {
fuse = new Fuse(bd.spec.events, {
//includeScore: true,
//minMatchCharLength: 1,
threshold: 0.4,
keys: [
{ name: 'name', weight: 10 },
{ name: 'description', weight: 7 },
{ name: 'speakers', weight: 5 },
{ name: 'speakersInfo.nickname', weight: 5 },
{ name: 'track', weight: 2 },
{ name: 'tags', weight: 2 },
{ name: 'speakersInfo.bio', weight: 1 },
{ name: 'speakersInfo.orgs', weight: 1 },
{ name: 'speakersInfo.description', weight: 1 },
]
})
})
{ name: "name", weight: 10 },
{ name: "description", weight: 7 },
{ name: "speakers", weight: 5 },
{ name: "speakersInfo.nickname", weight: 5 },
{ name: "track", weight: 2 },
{ name: "tags", weight: 2 },
{ name: "speakersInfo.bio", weight: 1 },
{ name: "speakersInfo.orgs", weight: 1 },
{ name: "speakersInfo.description", weight: 1 },
],
});
});
page.subscribe(() => {
searchText = ''
})
searchText = "";
});
function searchTextSubmit() {
filters = makeFilters($page, $bundle)
filters = makeFilters($page, $bundle);
}
function cancelFilter() {
searchText = ''
filters = makeFilters($page, $bundle)
goto('/program')
searchText = "";
filters = makeFilters($page, $bundle);
goto("/program");
}
</script>
<svelte:head>
@ -176,14 +185,18 @@
<div class="my-auto">Filtry:</div>
<div class="text-sm my-auto flex gap-1">
{#each filters as filter}
<div class="py-1 px-2 rounded bg-blue-web/60 text-white">{filter.title}</div>
<div class="py-1 px-2 rounded bg-blue-web/60 text-white">
{filter.title}
</div>
{/each}
</div>
<div class="ml-3 my-auto">
<a href="" on:click={cancelFilter}><i class="fa-solid fa-xmark text-red-500 mr-1" /> Zrušit filtr</a>
<a href="" on:click={cancelFilter}
><i class="fa-solid fa-xmark text-red-500 mr-1" /> Zrušit filtr</a
>
</div>
</div>
{:else}
{:else if $loadInfo.loaded}
<div class="mt-6 lg:mt-10 flex sm:justify-center overflow-auto">
<WordCloud words={tags} on:click={wordClick} />
</div>
@ -197,12 +210,19 @@
</div>
<div class="my-auto flex gap-2 mt-2 sm:mt-0">
<div class="my-auto">Hledat:</div>
<div><input type="text" bind:value={searchText} on:input={searchTextSubmit} class="border rounded border-blue-web/30 px-1.5 py-1" /></div>
<div>
<input
type="text"
bind:value={searchText}
on:input={searchTextSubmit}
class="border rounded border-blue-web/30 px-1.5 py-1"
/>
</div>
</div>
</div>
<div class="mt-4">
{#each ids as id}
<Event event={$bundle.spec.events.find(e => e.id === id)} />
<Event event={$bundle.spec.events.find((e) => e.id === id)} />
{/each}
</div>
<!--div class="mt-4">
@ -213,4 +233,3 @@
{/each}
</div-->
</section>

Zobrazit soubor

@ -64,7 +64,9 @@
<div class="text-sm my-auto">{duration}m</div>
{/if}
{#if e.track}
<div class="text-md my-auto"><a href="/program?track={e.track}">{trackRender(e.track)}</a></div>
<div class="text-md my-auto">
<a href="/program?track={e.track}">{trackRender(e.track)}</a>
</div>
{/if}
{#if e.tags}
<div class="flex text-xs gap-1 my-auto text-blue-web/60">

Zobrazit soubor

@ -33,12 +33,11 @@
}
const ticketTypes = {
public: 'Běžná vstupenka',
speaker: 'Přednášející',
organizator: 'Organizátor',
host: 'Doprovod',
}
public: "Běžná vstupenka",
speaker: "Přednášející",
organizator: "Organizátor",
host: "Doprovod",
};
let forceShow = false;
let loading = true;
@ -330,8 +329,15 @@
class="border-l border-b border-r p-4 rounded-b-md shadow-md border-blue-web"
>
<div class="flex gap-3 text-sm">
{#if ticket.type === 'speaker' && ticket.link && ticket.link.id}
<a href="/lide?id={ticket.link.id}"><Avatar speaker={$bundle.spec.speakers.find(s => s.id === ticket.link.id)} size="semi-small" /></a>
{#if ticket.type === "speaker" && ticket.link && ticket.link.id}
<a href="/lide?id={ticket.link.id}"
><Avatar
speaker={$bundle.spec.speakers.find(
(s) => s.id === ticket.link.id
)}
size="semi-small"
/></a
>
{:else}
<div
class="w-10 h-10 rounded-md"
@ -347,7 +353,9 @@
>#{ticket.id}</span
>
</div>
<div class="mt-1.5">{ticketTypes[ticket.type || 'public']}</div>
<div class="mt-1.5">
{ticketTypes[ticket.type || "public"]}
</div>
</div>
</div>
{#if ticket.data}

Zobrazit soubor

@ -10,54 +10,54 @@
import { faker } from "@faker-js/faker";
import api from "$lib/api.js";
import Avatar from "$lib/Avatar.svelte";
import removeMd from 'remove-markdown';
import removeMd from "remove-markdown";
import { userData } from "$lib/stores";
let claim = null
let claim = null;
let form = {
email: '',
name: '',
org: '',
twitter: ''
}
let formProcessing = false
let formError = null
email: "",
name: "",
org: "",
twitter: "",
};
let formProcessing = false;
let formError = null;
$: target = $bundle && claim ? findTarget(claim.link) : null
$: target = $bundle && claim ? findTarget(claim.link) : null;
function findTarget(link) {
if (link.type === 'speaker') {
return $bundle.spec.speakers.find(s => s.id === link.id)
if (link.type === "speaker") {
return $bundle.spec.speakers.find((s) => s.id === link.id);
}
return null
return null;
}
async function loadClaim(code) {
const resp = await api.apiCall("claimInfo", { method: 'post' }, { code })
return resp
const resp = await api.apiCall("claimInfo", { method: "post" }, { code });
return resp;
}
onMount(async () => {
const search = new URLSearchParams($page.url.search)
claim = await loadClaim(search.get('kod'))
const search = new URLSearchParams($page.url.search);
claim = await loadClaim(search.get("kod"));
if (!claim) {
goto('/')
goto("/");
}
if ($bundle && claim.link && claim.link.type === 'speaker') {
const sp = $bundle.spec.speakers.find(s => s.id === claim.link.id)
if ($bundle && claim.link && claim.link.type === "speaker") {
const sp = $bundle.spec.speakers.find((s) => s.id === claim.link.id);
if (sp) {
form.name = sp.name || ''
form.org = sp.orgs ? removeMd(sp.orgs).substring(0, 25) : ''
form.twitter = sp.twitter ? '@'+sp.twitter : ''
form.name = sp.name || "";
form.org = sp.orgs ? removeMd(sp.orgs).substring(0, 25) : "";
form.twitter = sp.twitter ? "@" + sp.twitter : "";
}
}
})
});
const linkTypes = {
speaker: {
title: 'Přednášející'
}
}
title: "Přednášející",
},
};
function processErrors(error) {
if (typeof error === "string") {
@ -75,9 +75,7 @@
(fe) => (ticket = fe.instancePath.match(/\/twitter/))
)
) {
suberrs.push(
`Neplatný Twitter účet.`
);
suberrs.push(`Neplatný Twitter účet.`);
}
out.title =
"Nesprávně vyplněný formulář: " +
@ -91,22 +89,26 @@
}
async function submitClaim() {
formProcessing = true
formProcessing = true;
let resp;
try {
resp = await api.apiCall('claim', { method: 'post' }, { code: claim.code, form })
resp = await api.apiCall(
"claim",
{ method: "post" },
{ code: claim.code, form }
);
} catch (e) {
console.error(e)
console.error(e);
}
if (resp.error) {
formError = processErrors(resp.error)
formProcessing = false
formError = processErrors(resp.error);
formProcessing = false;
return null;
}
if (!resp.ok || !resp.ticket) {
formError = { title: 'Neznámá chyba' }
formProcessing= false
formError = { title: "Neznámá chyba" };
formProcessing = false;
return null;
}
@ -115,13 +117,12 @@
if (!ud.tickets) {
ud.tickets = [];
}
ud.tickets.push([ resp.ticket.id, resp.ticket.secret ].join(':'));
ud.tickets.push([resp.ticket.id, resp.ticket.secret].join(":"));
return ud;
});
window.location.replace('/vstupenky');
window.location.replace("/vstupenky");
}
</script>
<svelte:head>
@ -132,8 +133,9 @@
<h1 class="uppercase text-2xl font-bold">Vyzvednutí vstupenky</h1>
<div class="mt-6 mb-10">
{#if claim && $bundle}
<div class="p-3 bg-blue-web-light rounded-md mt-6 text-blue-web shadow-md">
<div
class="p-3 bg-blue-web-light rounded-md mt-6 text-blue-web shadow-md"
>
<div class="p-2">
<div>
<div class="uppercase text-sm font-bold">Kód vyzvednutí</div>
@ -146,7 +148,8 @@
<div class="mt-2">
<span class="">{linkTypes[claim.link.type].title}</span>
{#if target}
- <Avatar speaker={target} size="extra-small" inline="true" /> <a href="/lide?id={target.id}">{target.name}</a>
- <Avatar speaker={target} size="extra-small" inline="true" />
<a href="/lide?id={target.id}">{target.name}</a>
{/if}
</div>
</div>
@ -169,23 +172,20 @@
</div>
</div>
<div class="mt-6">
<div class="uppercase text-sm font-bold">
Vstupenka
</div>
<div class="uppercase text-sm font-bold">Vstupenka</div>
<div class="mt-2 text-sm">
Informace, které budou vytištěné na Vaší konferenční
jmenovku. Tyto údaje jsou nepovinné a bude možné je změnit
později.
Informace, které budou vytištěné na Vaší konferenční jmenovku.
Tyto údaje jsou nepovinné a bude možné je změnit později.
</div>
</div>
<div class="mt-2">
<div class="p-4 bg-utxo-gradient text-white rounded-md mb-6 shadow-md">
<div
class="p-4 bg-utxo-gradient text-white rounded-md mb-6 shadow-md"
>
<div class="">
<div class="md:flex gap-2">
<div class="flex-1">
<div class="uppercase text-sm">
Jméno (Přezdívka)
</div>
<div class="uppercase text-sm">Jméno (Přezdívka)</div>
<div class="mt-2">
<input
type="text"
@ -197,9 +197,7 @@
</div>
</div>
<div class="flex-1">
<div class="uppercase text-sm">
Organizace (Firma)
</div>
<div class="uppercase text-sm">Organizace (Firma)</div>
<div class="mt-2">
<input
type="text"
@ -229,7 +227,11 @@
{#if !formProcessing}
<div>
<button
class="hover:bg-utxo-gradient bg-[#E16A61] text-white font-semibold rounded-full shadow-md" disabled={formProcessing} on:click={submitClaim} ><div class="py-2 px-4">Získat vstupenku</div></button>
class="hover:bg-utxo-gradient bg-[#E16A61] text-white font-semibold rounded-full shadow-md"
disabled={formProcessing}
on:click={submitClaim}
><div class="py-2 px-4">Získat vstupenku</div></button
>
</div>
{#if formError}
<div class="mt-4 text-red-500">
@ -251,8 +253,6 @@
{/if}
</div>
</div>
{:else}
<div>Načítám ...</div>
{/if}