Format code by "npm run format"

This commit is contained in:
tree 2023-01-30 04:04:13 +01:00
parent c1e019f065
commit d4862f096f
30 changed files with 1639 additions and 1265 deletions

View File

@ -1,15 +1,15 @@
module.exports = {
root: true,
extends: ["eslint:recommended", "prettier"],
plugins: ["svelte3"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true,
},
root: true,
extends: ['eslint:recommended', 'prettier'],
plugins: ['svelte3'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020
},
env: {
browser: true,
es2017: true,
node: true
}
};

View File

@ -3,7 +3,7 @@ name: GitHub Pages
on:
push:
branches:
- main # Set a branch name to trigger deployment
- main # Set a branch name to trigger deployment
jobs:
deploy:
@ -15,8 +15,8 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- uses: actions/setup-node@v3
with:
@ -29,9 +29,9 @@ jobs:
- name: Build
run: npm run build
- name: Add custom domain
run: "touch build/CNAME && echo \"explore.prgblockweek.com\" >> build/CNAME"
run: 'touch build/CNAME && echo "explore.prgblockweek.com" >> build/CNAME'
- name: Deploy
uses: peaceiris/actions-gh-pages@v3

View File

@ -17,8 +17,8 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- uses: actions/setup-node@v3
with:
@ -30,4 +30,4 @@ jobs:
- run: rm src/lib/data.json && wget -O src/lib/data.json https://data.prgblockweek.com/23/index.json
- name: Build
run: npm run build
run: npm run build

View File

@ -1,32 +1,32 @@
{
"name": "pbw-explore",
"version": "0.2.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"test": "playwright test",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
"@playwright/test": "^1.28.1",
"@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/adapter-static": "^1.0.1",
"@sveltejs/kit": "^1.0.0",
"autoprefixer": "^10.4.13",
"date-fns": "^2.29.3",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"ethereum-blockies-base64": "^1.0.2",
"postcss": "^8.4.21",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.8.1",
"svelte": "^3.54.0",
"svelte-markdown": "^0.2.3",
"tailwindcss": "^3.2.4",
"vite": "^4.0.0"
},
"type": "module"
"name": "pbw-explore",
"version": "0.2.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"test": "playwright test",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
"@playwright/test": "^1.28.1",
"@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/adapter-static": "^1.0.1",
"@sveltejs/kit": "^1.0.0",
"autoprefixer": "^10.4.13",
"date-fns": "^2.29.3",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"ethereum-blockies-base64": "^1.0.2",
"postcss": "^8.4.21",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.8.1",
"svelte": "^3.54.0",
"svelte-markdown": "^0.2.3",
"tailwindcss": "^3.2.4",
"vite": "^4.0.0"
},
"type": "module"
}

View File

@ -1,10 +1,10 @@
/** @type {import('@playwright/test').PlaywrightTestConfig} */
const config = {
webServer: {
command: "npm run build && npm run preview",
port: 4173,
},
testDir: "tests",
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'tests'
};
export default config;

View File

@ -1,6 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};

View File

@ -5,42 +5,42 @@
@tailwind utilities;
@layer components {
.link {
@apply underline hover:no-underline hover:text-red-200;
}
#footer a {
@apply underline hover:no-underline hover:text-pbw-white;
}
.separator {
@apply inline-block mx-3;
}
.button {
@apply border border-pbw-yellow py-3 px-4 rounded hover:bg-pbw-yellow hover:text-pbw-red;
}
.link {
@apply underline hover:no-underline hover:text-red-200;
}
#footer a {
@apply underline hover:no-underline hover:text-pbw-white;
}
.separator {
@apply inline-block mx-3;
}
.button {
@apply border border-pbw-yellow py-3 px-4 rounded hover:bg-pbw-yellow hover:text-pbw-red;
}
.cc0-license {
vertical-align: -0.1em;
margin-right: 0.3em;
width: 1em;
height: 1em;
background-size: 1em 1em;
background-position: center;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' width='64px' height='64px' viewBox='-0.5 0.5 64 64' enable-background='new -0.5 0.5 64 64' xml:space='preserve'%3E%3Cg%3E%3Ccircle fill='%23FFFFFF' cx='31.325' cy='32.873' r='30.096'/%3E%3Cpath id='text2809_1_' d='M31.5,14.08c-10.565,0-13.222,9.969-13.222,18.42c0,8.452,2.656,18.42,13.222,18.42 c10.564,0,13.221-9.968,13.221-18.42C44.721,24.049,42.064,14.08,31.5,14.08z M31.5,21.026c0.429,0,0.82,0.066,1.188,0.157 c0.761,0.656,1.133,1.561,0.403,2.823l-7.036,12.93c-0.216-1.636-0.247-3.24-0.247-4.437C25.808,28.777,26.066,21.026,31.5,21.026z M36.766,26.987c0.373,1.984,0.426,4.056,0.426,5.513c0,3.723-0.258,11.475-5.69,11.475c-0.428,0-0.822-0.045-1.188-0.136 c-0.07-0.021-0.134-0.043-0.202-0.067c-0.112-0.032-0.23-0.068-0.336-0.11c-1.21-0.515-1.972-1.446-0.874-3.093L36.766,26.987z'/%3E%3Cpath id='path2815_1_' d='M31.433,0.5c-8.877,0-16.359,3.09-22.454,9.3c-3.087,3.087-5.443,6.607-7.082,10.532 C0.297,24.219-0.5,28.271-0.5,32.5c0,4.268,0.797,8.32,2.397,12.168c1.6,3.85,3.921,7.312,6.969,10.396 c3.085,3.049,6.549,5.399,10.398,7.037c3.886,1.602,7.939,2.398,12.169,2.398c4.229,0,8.34-0.826,12.303-2.465 c3.962-1.639,7.496-3.994,10.621-7.081c3.011-2.933,5.289-6.297,6.812-10.106C62.73,41,63.5,36.883,63.5,32.5 c0-4.343-0.77-8.454-2.33-12.303c-1.562-3.885-3.848-7.32-6.857-10.33C48.025,3.619,40.385,0.5,31.433,0.5z M31.567,6.259 c7.238,0,13.412,2.566,18.554,7.709c2.477,2.477,4.375,5.31,5.67,8.471c1.296,3.162,1.949,6.518,1.949,10.061 c0,7.354-2.516,13.454-7.506,18.33c-2.592,2.516-5.502,4.447-8.74,5.781c-3.2,1.334-6.498,1.994-9.927,1.994 c-3.468,0-6.788-0.653-9.949-1.948c-3.163-1.334-6.001-3.238-8.516-5.716c-2.515-2.514-4.455-5.353-5.826-8.516 c-1.333-3.199-2.017-6.498-2.017-9.927c0-3.467,0.684-6.787,2.017-9.949c1.371-3.2,3.312-6.074,5.826-8.628 C18.092,8.818,24.252,6.259,31.567,6.259z'/%3E%3C/g%3E%3C/svg%3E");
}
.cc0-license {
vertical-align: -0.1em;
margin-right: 0.3em;
width: 1em;
height: 1em;
background-size: 1em 1em;
background-position: center;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' width='64px' height='64px' viewBox='-0.5 0.5 64 64' enable-background='new -0.5 0.5 64 64' xml:space='preserve'%3E%3Cg%3E%3Ccircle fill='%23FFFFFF' cx='31.325' cy='32.873' r='30.096'/%3E%3Cpath id='text2809_1_' d='M31.5,14.08c-10.565,0-13.222,9.969-13.222,18.42c0,8.452,2.656,18.42,13.222,18.42 c10.564,0,13.221-9.968,13.221-18.42C44.721,24.049,42.064,14.08,31.5,14.08z M31.5,21.026c0.429,0,0.82,0.066,1.188,0.157 c0.761,0.656,1.133,1.561,0.403,2.823l-7.036,12.93c-0.216-1.636-0.247-3.24-0.247-4.437C25.808,28.777,26.066,21.026,31.5,21.026z M36.766,26.987c0.373,1.984,0.426,4.056,0.426,5.513c0,3.723-0.258,11.475-5.69,11.475c-0.428,0-0.822-0.045-1.188-0.136 c-0.07-0.021-0.134-0.043-0.202-0.067c-0.112-0.032-0.23-0.068-0.336-0.11c-1.21-0.515-1.972-1.446-0.874-3.093L36.766,26.987z'/%3E%3Cpath id='path2815_1_' d='M31.433,0.5c-8.877,0-16.359,3.09-22.454,9.3c-3.087,3.087-5.443,6.607-7.082,10.532 C0.297,24.219-0.5,28.271-0.5,32.5c0,4.268,0.797,8.32,2.397,12.168c1.6,3.85,3.921,7.312,6.969,10.396 c3.085,3.049,6.549,5.399,10.398,7.037c3.886,1.602,7.939,2.398,12.169,2.398c4.229,0,8.34-0.826,12.303-2.465 c3.962-1.639,7.496-3.994,10.621-7.081c3.011-2.933,5.289-6.297,6.812-10.106C62.73,41,63.5,36.883,63.5,32.5 c0-4.343-0.77-8.454-2.33-12.303c-1.562-3.885-3.848-7.32-6.857-10.33C48.025,3.619,40.385,0.5,31.433,0.5z M31.567,6.259 c7.238,0,13.412,2.566,18.554,7.709c2.477,2.477,4.375,5.31,5.67,8.471c1.296,3.162,1.949,6.518,1.949,10.061 c0,7.354-2.516,13.454-7.506,18.33c-2.592,2.516-5.502,4.447-8.74,5.781c-3.2,1.334-6.498,1.994-9.927,1.994 c-3.468,0-6.788-0.653-9.949-1.948c-3.163-1.334-6.001-3.238-8.516-5.716c-2.515-2.514-4.455-5.353-5.826-8.516 c-1.333-3.199-2.017-6.498-2.017-9.927c0-3.467,0.684-6.787,2.017-9.949c1.371-3.2,3.312-6.074,5.826-8.628 C18.092,8.818,24.252,6.259,31.567,6.259z'/%3E%3C/g%3E%3C/svg%3E");
}
.markdown p a {
text-decoration: underline;
}
.markdown p a:hover {
text-decoration: none;
}
.markdown p a {
text-decoration: underline;
}
.markdown p a:hover {
text-decoration: none;
}
.external::after {
padding-left: 0.5rem;
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.5' height='13.5' aria-hidden='true' viewBox='0 0 24 24' class='iconExternalLink_nPIU'%3E%3Cpath fill='currentColor' d='M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z'%3E%3C/path%3E%3C/svg%3E");
}
.external::after {
padding-left: 0.5rem;
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.5' height='13.5' aria-hidden='true' viewBox='0 0 24 24' class='iconExternalLink_nPIU'%3E%3Cpath fill='currentColor' d='M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z'%3E%3C/path%3E%3C/svg%3E");
}
.external.text-white::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.5' height='13.5' aria-hidden='true' viewBox='0 0 24 24' class='iconExternalLink_nPIU'%3E%3Cpath fill='white' d='M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z'%3E%3C/path%3E%3C/svg%3E");
}
}
.external.text-white::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.5' height='13.5' aria-hidden='true' viewBox='0 0 24 24' class='iconExternalLink_nPIU'%3E%3Cpath fill='white' d='M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z'%3E%3C/path%3E%3C/svg%3E");
}
}

View File

@ -6,7 +6,11 @@
<meta name="viewport" content="width=device-width" />
<!-- Plausible -->
<script defer data-domain="explore.prgblockweek.com" src="https://x.gwei.cz/js/script.js"></script>
<script
defer
data-domain="explore.prgblockweek.com"
src="https://x.gwei.cz/js/script.js"
></script>
%sveltekit.head%
</head>

View File

@ -1,67 +1,82 @@
<script>
import { format } from 'date-fns';
import ItemLogo from '$lib/components/ItemLogo.svelte';
import EventTypeBadge from '$lib/components/EventTypeBadge.svelte';
import { format } from 'date-fns';
import ItemLogo from '$lib/components/ItemLogo.svelte';
import EventTypeBadge from '$lib/components/EventTypeBadge.svelte';
export let segments;
export let date;
export let entry;
export let bundle;
export let event = null;
export let segments;
export let date;
export let entry;
export let bundle;
export let event = null;
</script>
<div class="text-2xl">
{#each segments as segment}
<div class="md:flex flex-wrap mb-2 gap-3 items-center text-gray-800 border border-gray-300 rounded-lg md:border-none px-3 py-2 md:px-0 md:py-0">
<div class="flex gap-2">
<div class="text-xl md:w-32 md:text-right">{format(new Date(segment.startTime), "HH:mm")} - {format(new Date(segment.endTime), "HH:mm")}</div>
{#if !event}
<div class="gap-1 items-center md:ml-2 inline-flex md:hidden text-xs">
{#each (segment.event || event).types as type}
<EventTypeBadge {type} />
{/each}
</div>
{/if}
</div>
<div class="md:flex gap-2 items-center mb-6 md:mb-0">
<div class="flex gap-2 items-center my-2 md:my-0">
<a href="/{entry}/event/{(segment.event || event).id}">
<ItemLogo item={segment.event || event} width={event ? 'w-8' : 'w-10'}/>
</a>
<div>
{#if !event}
<a href="/{entry}/event/{(segment.event || event).id}" class="text-pbw-red hover:underline">{(segment.event || event)[event && event.shortname ? 'shortname' : 'name']}</a>
{:else}
<span class="">{event.shortname || event.name}</span>
{/if}
{#if segment.title}
- {segment.title}
{/if}
</div>
</div>
<div class="flex flex-wrap gap-2">
{#if !event}
<div class="gap-1 items-center md:ml-2 hidden md:inline-flex text-xs">
{#each (segment.event || event).types as type}
<EventTypeBadge {type} />
{/each}
</div>
{/if}
<div class="text-xl">
{#if segment.venues || event?.venues}
๐Ÿ“ {@html ((segment.venues || event.venues).map(vId => {
const place = bundle.places.find(p => p.id === vId)
return `<a href="/${entry}/place/${place.id}" class=\"underline hover:no-underline\">${place.name}</a>`
})).join("<span>, </span>")}
{:else if (segment.event?.venueName || event?.venueName)}
๐Ÿ“ {(segment.event?.venueName || event?.venueName)}
{/if}
</div>
{#if segment.ecap || event?.attendees || segment.event?.attendees }
<div class="text-lg">๐Ÿ‘ฅ {segment.ecap || event?.attendees || segment.event?.attendees}</div>
{/if}
</div>
</div>
</div>
{/each}
</div>
{#each segments as segment}
<div
class="md:flex flex-wrap mb-2 gap-3 items-center text-gray-800 border border-gray-300 rounded-lg md:border-none px-3 py-2 md:px-0 md:py-0"
>
<div class="flex gap-2">
<div class="text-xl md:w-32 md:text-right">
{format(new Date(segment.startTime), 'HH:mm')} - {format(
new Date(segment.endTime),
'HH:mm'
)}
</div>
{#if !event}
<div class="gap-1 items-center md:ml-2 inline-flex md:hidden text-xs">
{#each (segment.event || event).types as type}
<EventTypeBadge {type} />
{/each}
</div>
{/if}
</div>
<div class="md:flex gap-2 items-center mb-6 md:mb-0">
<div class="flex gap-2 items-center my-2 md:my-0">
<a href="/{entry}/event/{(segment.event || event).id}">
<ItemLogo item={segment.event || event} width={event ? 'w-8' : 'w-10'} />
</a>
<div>
{#if !event}
<a
href="/{entry}/event/{(segment.event || event).id}"
class="text-pbw-red hover:underline"
>{(segment.event || event)[event && event.shortname ? 'shortname' : 'name']}</a
>
{:else}
<span class="">{event.shortname || event.name}</span>
{/if}
{#if segment.title}
- {segment.title}
{/if}
</div>
</div>
<div class="flex flex-wrap gap-2">
{#if !event}
<div class="gap-1 items-center md:ml-2 hidden md:inline-flex text-xs">
{#each (segment.event || event).types as type}
<EventTypeBadge {type} />
{/each}
</div>
{/if}
<div class="text-xl">
{#if segment.venues || event?.venues}
๐Ÿ“ {@html (segment.venues || event.venues)
.map((vId) => {
const place = bundle.places.find((p) => p.id === vId);
return `<a href="/${entry}/place/${place.id}" class=\"underline hover:no-underline\">${place.name}</a>`;
})
.join('<span>, </span>')}
{:else if segment.event?.venueName || event?.venueName}
๐Ÿ“ {segment.event?.venueName || event?.venueName}
{/if}
</div>
{#if segment.ecap || event?.attendees || segment.event?.attendees}
<div class="text-lg">
๐Ÿ‘ฅ {segment.ecap || event?.attendees || segment.event?.attendees}
</div>
{/if}
</div>
</div>
</div>
{/each}
</div>

View File

@ -1,84 +1,112 @@
<script>
import SvelteMarkdown from 'svelte-markdown';
import { formatItemDate } from '$lib/utils.js';
import ItemLogo from '$lib/components/ItemLogo.svelte';
import SvelteMarkdown from 'svelte-markdown';
import { formatItemDate } from '$lib/utils.js';
import ItemLogo from '$lib/components/ItemLogo.svelte';
export let arr;
export let entry = "23";
export let col = "speaker";
export let img = "photoUrl";
export let aspect = "aspect-square";
export let size = "normal";
export let offer = false;
export let bundle = null;
export let currentItem = null;
export let arr;
export let entry = '23';
export let col = 'speaker';
export let img = 'photoUrl';
export let aspect = 'aspect-square';
export let size = 'normal';
export let offer = false;
export let bundle = null;
export let currentItem = null;
function findObject (it) {
if (!bundle) {
return it
}
if (col === "speaker" && !it.name) {
let found = null
for (const e of bundle.events) {
if (!e.speakers) continue;
found = e.speakers.find(s => {
return s.id === it.id && s.name
})
if (found) break;
}
Object.assign(it, found || {})
}
return it
}
function findObject(it) {
if (!bundle) {
return it;
}
if (col === 'speaker' && !it.name) {
let found = null;
for (const e of bundle.events) {
if (!e.speakers) continue;
found = e.speakers.find((s) => {
return s.id === it.id && s.name;
});
if (found) break;
}
Object.assign(it, found || {});
}
return it;
}
const _url = (col, item) => `/${entry}/${col}/${item.id}`
const _url = (col, item) => `/${entry}/${col}/${item.id}`;
</script>
{#each arr.map((k) => findObject(k)) as item}
<div class="{size === "small" ? "p-0.5 lg:p-1" : "p-1 lg:p-1.5"} hover:bg-pbw-yellow/20 dark:hover:bg-pbw-white/10 {size==="small" ? "rounded-lg" : "rounded-2xl"}">
<div class="w-full relative">
{#if col === "benefit"}
<div class="absolute top-3 -left-4">
<div class="bg-pbw-red py-0.5 px-1.5 rounded-md text-white uppercase text-base">{item.slogan}</div>
</div>
{/if}
<a href={_url(col, item)}>
<ItemLogo {item} width="w-full" {aspect} {img} rounded={size === "small" ? "rounded-lg" : "rounded-2xl"} />
</a>
</div>
{#if col !== "media-partner"}
<div class="mt-2">
<h3 class=" text-pbw-red"><a href={_url(col, item)} class="hover:underline">{item.shortname || item.name}</a></h3>
{#if col === "event"}
<div class="text-xl text-gray-500 dark:text-gray-400 my-2">
<span class="font-bold">{formatItemDate(item)}</span>
{#if item.attendees}<br />{item.attendees} ppl{/if}
</div>
{/if}
{#if col === "media-partner"}
<div class="text-base text-gray-500 dark:text-gray-400 my-2">{item.description}</div>
{/if}
{#if col === "speaker"}
<div class="text-base text-gray-500 dark:text-gray-400 my-2"><SvelteMarkdown source={item.caption} /></div>
{/if}
{#if col === "union"}
<div class="text-base text-gray-500 dark:text-gray-400 my-2"><SvelteMarkdown source={item.description} /></div>
{/if}
{#if col === "place"}
<div class="text-xl text-gray-500 dark:text-gray-400 my-2">{item.capacity} ppl</div>
{/if}
</div>
{/if}
</div>
<div
class="{size === 'small'
? 'p-0.5 lg:p-1'
: 'p-1 lg:p-1.5'} hover:bg-pbw-yellow/20 dark:hover:bg-pbw-white/10 {size === 'small'
? 'rounded-lg'
: 'rounded-2xl'}"
>
<div class="w-full relative">
{#if col === 'benefit'}
<div class="absolute top-3 -left-4">
<div class="bg-pbw-red py-0.5 px-1.5 rounded-md text-white uppercase text-base">
{item.slogan}
</div>
</div>
{/if}
<a href={_url(col, item)}>
<ItemLogo
{item}
width="w-full"
{aspect}
{img}
rounded={size === 'small' ? 'rounded-lg' : 'rounded-2xl'}
/>
</a>
</div>
{#if col !== 'media-partner'}
<div class="mt-2">
<h3 class=" text-pbw-red">
<a href={_url(col, item)} class="hover:underline">{item.shortname || item.name}</a>
</h3>
{#if col === 'event'}
<div class="text-xl text-gray-500 dark:text-gray-400 my-2">
<span class="font-bold">{formatItemDate(item)}</span>
{#if item.attendees}<br />{item.attendees} ppl{/if}
</div>
{/if}
{#if col === 'media-partner'}
<div class="text-base text-gray-500 dark:text-gray-400 my-2">{item.description}</div>
{/if}
{#if col === 'speaker'}
<div class="text-base text-gray-500 dark:text-gray-400 my-2">
<SvelteMarkdown source={item.caption} />
</div>
{/if}
{#if col === 'union'}
<div class="text-base text-gray-500 dark:text-gray-400 my-2">
<SvelteMarkdown source={item.description} />
</div>
{/if}
{#if col === 'place'}
<div class="text-xl text-gray-500 dark:text-gray-400 my-2">{item.capacity} ppl</div>
{/if}
</div>
{/if}
</div>
{/each}
{#if offer}
<div class="flex text-gray-400 self-start {col==="event" ? "mt-8" : ""}">
<div class="p-4">
<div class="text-6xl">+</div>
<div>
{#if col === 'event'}<a href="https://guide.prgblockweek.com/event-host-guide" target="_blank" class="underline hover:no-underline">Host your own event!</a>{/if}
{#if col === 'benefit'}<a href="https://guide.prgblockweek.com/event-host-guide" target="_blank" class="underline hover:no-underline">Offer visitors your own benefit!</a>{/if}
</div>
</div>
</div>
{/if}
<div class="flex text-gray-400 self-start {col === 'event' ? 'mt-8' : ''}">
<div class="p-4">
<div class="text-6xl">+</div>
<div>
{#if col === 'event'}<a
href="https://guide.prgblockweek.com/event-host-guide"
target="_blank"
class="underline hover:no-underline">Host your own event!</a
>{/if}
{#if col === 'benefit'}<a
href="https://guide.prgblockweek.com/event-host-guide"
target="_blank"
class="underline hover:no-underline">Offer visitors your own benefit!</a
>{/if}
</div>
</div>
</div>
{/if}

View File

@ -1,9 +1,11 @@
<script>
import { config } from '$lib/pbw.js';
export let type = "conference";
import { config } from '$lib/pbw.js';
export let type = 'conference';
</script>
<div class="text-sm uppercase rounded px-1.5 py-0.5 text-black" style="background-color: {config.eventTypeColors[type]};">
{type}
<div
class="text-sm uppercase rounded px-1.5 py-0.5 text-black"
style="background-color: {config.eventTypeColors[type]};"
>
{type}
</div>

View File

@ -1,40 +1,77 @@
<script>
import { config } from '$lib/pbw';
import { formatDistanceToNow } from "date-fns";
import { config } from '$lib/pbw';
import { formatDistanceToNow } from 'date-fns';
export let item;
export let col;
export let bundle;
export let item;
export let col;
export let bundle;
const cc = Object.keys(config.collections).find(c => config.collections[c].model === col)
const cc = Object.keys(config.collections).find((c) => config.collections[c].model === col);
let showSource = false;
let showSource = false;
</script>
<div class="mt-20">
<div class="bg-gray-100 p-4 text-lg text-gray-600">
<div>โš™ This page is automatically generated using the structured dataset which can be consumed as a single JSON file โ†’ <a href="https://data.prgblockweek.com/23/index.json" class="underline hover:no-underline" target="_blank">data.prgblockweek.com/23/index.json</a>.
<div class="h-4"></div>
๐Ÿ“– The source data GitHub repository โ†’ <a href="https://github.com/utxo-foundation/prague-blockchain-week" class="underline hover:no-underline" target="_blank">utxo-foundation/prague-blockchain-week</a>.
Go ahead and do PRs!
</div>
</div>
{#if bundle}
<div class="mt-4 text-gray-400">
<div class="mt-2">
Last update: <a href="https://github.com/utxo-foundation/prague-blockchain-week/commits/main" target="_blank" class="underline hover:no-underline">{formatDistanceToNow(new Date(bundle.time))} ago</a>
&nbsp;|&nbsp; <a href="https://analytics.gwei.cz/explore.prgblockweek.com" class="underline hover:no-underline" target="_blank">Analytics</a>
&nbsp;|&nbsp; <a href="https://github.com/utxo-foundation/pbw-explore" class="underline hover:no-underline" target="_blank">pbw-explore {__VERSION__}</a>
{#if item}
&nbsp;|&nbsp; ID: <a href="https://github.com/utxo-foundation/prague-blockchain-week/tree/main/data/23/{cc}/{item.id}" class="underline hover:no-underline" target="_blank">{item.id}</a> [{cc}]
&nbsp;|&nbsp; <button class="cursor-pointer underline hover:no-underline" on:click={() => { showSource = !showSource; return false; }}>Toggle JSON source</button>
{/if}
</div>
{#if showSource}
<h2 class="text-2xl uppercase font-bold mt-10 text-gray-500">JSON source-code</h2>
<div class="mt-4 font-mono whitespace-pre-wrap p-4 rounded-md bg-slate-200 text-sm text-black">{JSON.stringify(item, null, 2)}</div>
{/if}
</div>
{/if}
</div>
<div class="bg-gray-100 p-4 text-lg text-gray-600">
<div>
โš™ This page is automatically generated using the structured dataset which can be consumed as a
single JSON file โ†’ <a
href="https://data.prgblockweek.com/23/index.json"
class="underline hover:no-underline"
target="_blank">data.prgblockweek.com/23/index.json</a
>.
<div class="h-4" />
๐Ÿ“– The source data GitHub repository โ†’<a
href="https://github.com/utxo-foundation/prague-blockchain-week"
class="underline hover:no-underline"
target="_blank">utxo-foundation/prague-blockchain-week</a
>. Go ahead and do PRs!
</div>
</div>
{#if bundle}
<div class="mt-4 text-gray-400">
<div class="mt-2">
Last update: <a
href="https://github.com/utxo-foundation/prague-blockchain-week/commits/main"
target="_blank"
class="underline hover:no-underline">{formatDistanceToNow(new Date(bundle.time))} ago</a
>
&nbsp;|&nbsp;
<a
href="https://analytics.gwei.cz/explore.prgblockweek.com"
class="underline hover:no-underline"
target="_blank">Analytics</a
>
&nbsp;|&nbsp;
<a
href="https://github.com/utxo-foundation/pbw-explore"
class="underline hover:no-underline"
target="_blank">pbw-explore {__VERSION__}</a
>
{#if item}
&nbsp;|&nbsp; ID: <a
href="https://github.com/utxo-foundation/prague-blockchain-week/tree/main/data/23/{cc}/{item.id}"
class="underline hover:no-underline"
target="_blank">{item.id}</a
>
[{cc}] &nbsp;|&nbsp;
<button
class="cursor-pointer underline hover:no-underline"
on:click={() => {
showSource = !showSource;
return false;
}}>Toggle JSON source</button
>
{/if}
</div>
{#if showSource}
<h2 class="text-2xl uppercase font-bold mt-10 text-gray-500">JSON source-code</h2>
<div
class="mt-4 font-mono whitespace-pre-wrap p-4 rounded-md bg-slate-200 text-sm text-black"
>
{JSON.stringify(item, null, 2)}
</div>
{/if}
</div>
{/if}
</div>

View File

@ -1,17 +1,24 @@
<script>
import makeBlockie from 'ethereum-blockies-base64';
export let item;
export let img = "logo";
export let width = "w-10";
export let aspect = "aspect-square";
export let rounded = "rounded";
$: blockie = !item[img] && item.hash ? makeBlockie('0x'+item.hash.substr(0,40)) : null
import makeBlockie from 'ethereum-blockies-base64';
export let item;
export let img = 'logo';
export let width = 'w-10';
export let aspect = 'aspect-square';
export let rounded = 'rounded';
$: blockie = !item[img] && item.hash ? makeBlockie('0x' + item.hash.substr(0, 40)) : null;
</script>
{#if item[img]}
<img src={item[img]} class="{width} {rounded} {aspect} object-cover dark:bg-white" alt={item.name} />
<img
src={item[img]}
class="{width} {rounded} {aspect} object-cover dark:bg-white"
alt={item.name}
/>
{:else if item.hash}
<div class="{width} {rounded} {aspect} object-cover dark:bg-white" style="background: url({blockie}); background-size: 100% 100%;"></div>
{/if}
<div
class="{width} {rounded} {aspect} object-cover dark:bg-white"
style="background: url({blockie}); background-size: 100% 100%;"
/>
{/if}

View File

@ -1,157 +1,196 @@
<script>
import { compareAsc, addDays, addMinutes, format } from 'date-fns';
import { goto } from '$app/navigation';
import ItemLogo from '$lib/components/ItemLogo.svelte';
export let data;
export let highlightDay = false;
import { compareAsc, addDays, addMinutes, format } from 'date-fns';
import { goto } from '$app/navigation';
import ItemLogo from '$lib/components/ItemLogo.svelte';
export let data;
export let highlightDay = false;
const startDate = "2023-06-02"
const endDate = "2023-06-11"
const segmentMinutes = 60
const bundle = data.bundle
const startDate = '2023-06-02';
const endDate = '2023-06-11';
const segmentMinutes = 60;
const bundle = data.bundle;
const days = []
let currentDate = startDate
while (compareAsc(new Date(currentDate), new Date(endDate)) <= 0) {
days.push(format(new Date(currentDate), 'yyyy-MM-dd'))
currentDate = addDays(new Date(currentDate), 1)
}
const days = [];
let currentDate = startDate;
while (compareAsc(new Date(currentDate), new Date(endDate)) <= 0) {
days.push(format(new Date(currentDate), 'yyyy-MM-dd'));
currentDate = addDays(new Date(currentDate), 1);
}
const segments = []
let currentSegment = "00:00"
const endSegmentDate = addDays(new Date(startDate), 1)
while(!segments.includes(currentSegment)) {
segments.push(format(new Date(startDate+"T"+currentSegment), 'HH:mm'))
currentSegment = format(addMinutes(new Date(startDate+"T"+currentSegment), segmentMinutes), "HH:mm")
}
const segments = [];
let currentSegment = '00:00';
const endSegmentDate = addDays(new Date(startDate), 1);
while (!segments.includes(currentSegment)) {
segments.push(format(new Date(startDate + 'T' + currentSegment), 'HH:mm'));
currentSegment = format(
addMinutes(new Date(startDate + 'T' + currentSegment), segmentMinutes),
'HH:mm'
);
}
const timelineData = {}
for (const day of days) {
for (const segment of segments) {
const score = 0
timelineData[[day, segment].join(';')] = {
score,
events: []
}
}
}
const timelineData = {};
for (const day of days) {
for (const segment of segments) {
const score = 0;
timelineData[[day, segment].join(';')] = {
score,
events: []
};
}
}
function updateTimelineEvent(time, eventId, attendees, eventSegmentId) {
for (const day of days) {
for (const segment of segments) {
const sstart = new Date(`${day}T${segment}`)
const send = new Date(addMinutes(sstart, segmentMinutes))
if (compareAsc(sstart, time.end) < 0 && compareAsc(send, time.start) > 0) {
//console.log(timelineData[[day, segment].join(';')])
const baseScore = attendees ? (attendees > 3000 ? 3000 : (attendees < 200 ? 200 : attendees)) : 0
const target = timelineData[[day, segment].join(';')]
target.score += baseScore || 0
target.events.push([eventId, eventSegmentId])
}
}
}
}
function updateTimelineEvent(time, eventId, attendees, eventSegmentId) {
for (const day of days) {
for (const segment of segments) {
const sstart = new Date(`${day}T${segment}`);
const send = new Date(addMinutes(sstart, segmentMinutes));
if (compareAsc(sstart, time.end) < 0 && compareAsc(send, time.start) > 0) {
//console.log(timelineData[[day, segment].join(';')])
const baseScore = attendees
? attendees > 3000
? 3000
: attendees < 200
? 200
: attendees
: 0;
const target = timelineData[[day, segment].join(';')];
target.score += baseScore || 0;
target.events.push([eventId, eventSegmentId]);
}
}
}
}
const defaultTimes = "09:00-18:00"
for (const event of bundle.events) {
for (let i = 0; i < event.segments.length; i++) {
const eventSegment = event.segments[i]
const [ tstart, tend ] = (eventSegment.times || defaultTimes).split('-')
const time = {
start: new Date(`${eventSegment.date}T${tstart}`),
end: new Date(`${tend <= tstart ? format(addDays(new Date(eventSegment.date),1), 'yyyy-MM-dd') : eventSegment.date}T${tend}`)
}
updateTimelineEvent(time, event.id, eventSegment.ecap || event.attendees, i)
}
}
const defaultTimes = '09:00-18:00';
for (const event of bundle.events) {
for (let i = 0; i < event.segments.length; i++) {
const eventSegment = event.segments[i];
const [tstart, tend] = (eventSegment.times || defaultTimes).split('-');
const time = {
start: new Date(`${eventSegment.date}T${tstart}`),
end: new Date(
`${
tend <= tstart
? format(addDays(new Date(eventSegment.date), 1), 'yyyy-MM-dd')
: eventSegment.date
}T${tend}`
)
};
updateTimelineEvent(time, event.id, eventSegment.ecap || event.attendees, i);
}
}
const segmentsMax = Math.max(...Object.keys(timelineData).map(k => timelineData[k].score))
for (const sgm of Object.keys(timelineData)) {
const it = timelineData[sgm]
it.perc = (it.score / (segmentsMax/100))
}
const segmentsMax = Math.max(...Object.keys(timelineData).map((k) => timelineData[k].score));
for (const sgm of Object.keys(timelineData)) {
const it = timelineData[sgm];
it.perc = it.score / (segmentsMax / 100);
}
let selectedSegment = null
let selectedSegment = null;
function makeSelected (day, segment, keys) {
const baseDate = new Date(`${day}T${segment}`)
const title = format(baseDate, "EEEE MMMM d | HH:mm - ") + format(addMinutes(baseDate, segmentMinutes), "HH:mm")
return (event) => {
selectedSegment = {
day,
segment,
data: keys,
event,
title,
}
}
}
function makeSelected(day, segment, keys) {
const baseDate = new Date(`${day}T${segment}`);
const title =
format(baseDate, 'EEEE MMMM d | HH:mm - ') +
format(addMinutes(baseDate, segmentMinutes), 'HH:mm');
return (event) => {
selectedSegment = {
day,
segment,
data: keys,
event,
title
};
};
}
function makeClick (day, segment, keys) {
const start = new Date(`${day}T${segment}`)
const end = addMinutes(start, segmentMinutes)
//goto(`/${data.params.entry}/events?start=${start.toISOString()}&end=${end.toISOString()}`)
goto(`/${data.params.entry}/day/${day}?start=${start.toISOString()}&end=${end.toISOString()}`)
}
function makeClick(day, segment, keys) {
const start = new Date(`${day}T${segment}`);
const end = addMinutes(start, segmentMinutes);
//goto(`/${data.params.entry}/events?start=${start.toISOString()}&end=${end.toISOString()}`)
goto(`/${data.params.entry}/day/${day}?start=${start.toISOString()}&end=${end.toISOString()}`);
}
function hiddenSelected() {
selectedSegment = null
}
function eventDetail (id) {
return bundle.events.find(e => e.id === id)
}
function hiddenSelected() {
selectedSegment = null;
}
function eventDetail(id) {
return bundle.events.find((e) => e.id === id);
}
</script>
<div class="w-full mb-10 relative">
{#if selectedSegment}
<div class="absolute top-[81px] w-[300px] border bg-white z-50 py-2 px-4 {selectedSegment ? 'hidden md:block' : 'hidden'}" style="left: {selectedSegment.event.layerX}px;">
<div class="uppercase">{selectedSegment.title}</div>
<div class="text-xl mt-4">
{#each selectedSegment.data.events.map(e => { return [eventDetail(e[0]), e[1]] }) as [item, segmentId]}
<div class="flex gap-2 items-center mb-1">
<div class="">
<ItemLogo {item} width="h-8" />
</div>
<div class="">
{item.shortname || item.name}
{#if item.segments[segmentId].title}
- {item.segments[segmentId].title}
{/if}
</div>
</div>
{/each}
</div>
</div>
{/if}
<div class="flex text-center text-gray-400 text-sm items-end h-10">
{#each days as day}
<div class="mb-1 uppercase {highlightDay && highlightDay !== day ? "text-gray-400 text-lg" : "text-pbw-red text-lg"}" style="width: {1/(days.length/100)}%;">
<a href="/23/day/{format(new Date(day), 'yyyy-MM-dd')}"><span class="hidden md:inline-block">{format(new Date(day), 'eee ')}</span> {format(new Date(day), 'd')}</a>
</div>
{/each}
</div>
<div class="w-full border {highlightDay ? 'border-gray-300' : 'border-pbw-red'} flex">
{#each days as day, i}
<div
class="h-10 flex flex-grow hover:bg-pbw-yellow/20"
style="width: {1/(days.length/100)}%; {(highlightDay && highlightDay === day ? "border: 1px solid rgb(255, 22, 22);" : (!highlightDay ? "border-right: 1px solid rgb(255, 22, 22);" : (days.length-i > 1 ? "border-right: 1px solid silver;" : "")))}"
>
{#each segments as segment}
<div
id="{day}-{segment}"
data-events={timelineData[[day, segment].join(";")].events}
data-score={timelineData[[day, segment].join(";")].score}
class="md:hover:border md:hover:border-pbw-yellow flex-grow cursor-pointer"
style="width: {1/(segments.length/50)}%; background-color: rgba({!highlightDay || highlightDay === day ? "255, 22, 22" : "115, 115, 115"}, {timelineData[[day, segment].join(";")].perc}%);"
on:click={makeClick(day, segment, timelineData[[day, segment].join(";")])}
on:mouseenter={makeSelected(day, segment, timelineData[[day, segment].join(";")])}
on:mouseleave={hiddenSelected}
>
</div>
{/each}
</div>
{/each}
</div>
</div>
{#if selectedSegment}
<div
class="absolute top-[81px] w-[300px] border bg-white z-50 py-2 px-4 {selectedSegment
? 'hidden md:block'
: 'hidden'}"
style="left: {selectedSegment.event.layerX}px;"
>
<div class="uppercase">{selectedSegment.title}</div>
<div class="text-xl mt-4">
{#each selectedSegment.data.events.map((e) => {
return [eventDetail(e[0]), e[1]];
}) as [item, segmentId]}
<div class="flex gap-2 items-center mb-1">
<div class="">
<ItemLogo {item} width="h-8" />
</div>
<div class="">
{item.shortname || item.name}
{#if item.segments[segmentId].title}
- {item.segments[segmentId].title}
{/if}
</div>
</div>
{/each}
</div>
</div>
{/if}
<div class="flex text-center text-gray-400 text-sm items-end h-10">
{#each days as day}
<div
class="mb-1 uppercase {highlightDay && highlightDay !== day
? 'text-gray-400 text-lg'
: 'text-pbw-red text-lg'}"
style="width: {1 / (days.length / 100)}%;"
>
<a href="/23/day/{format(new Date(day), 'yyyy-MM-dd')}"
><span class="hidden md:inline-block">{format(new Date(day), 'eee ')}</span>
{format(new Date(day), 'd')}</a
>
</div>
{/each}
</div>
<div class="w-full border {highlightDay ? 'border-gray-300' : 'border-pbw-red'} flex">
{#each days as day, i}
<div
class="h-10 flex flex-grow hover:bg-pbw-yellow/20"
style="width: {1 / (days.length / 100)}%; {highlightDay && highlightDay === day
? 'border: 1px solid rgb(255, 22, 22);'
: !highlightDay
? 'border-right: 1px solid rgb(255, 22, 22);'
: days.length - i > 1
? 'border-right: 1px solid silver;'
: ''}"
>
{#each segments as segment}
<div
id="{day}-{segment}"
data-events={timelineData[[day, segment].join(';')].events}
data-score={timelineData[[day, segment].join(';')].score}
class="md:hover:border md:hover:border-pbw-yellow flex-grow cursor-pointer"
style="width: {1 / (segments.length / 50)}%; background-color: rgba({!highlightDay ||
highlightDay === day
? '255, 22, 22'
: '115, 115, 115'}, {timelineData[[day, segment].join(';')].perc}%);"
on:click={makeClick(day, segment, timelineData[[day, segment].join(';')])}
on:mouseenter={makeSelected(day, segment, timelineData[[day, segment].join(';')])}
on:mouseleave={hiddenSelected}
/>
{/each}
</div>
{/each}
</div>
</div>

View File

@ -1,31 +1,27 @@
import localData from "$lib/data.json";
import localData from '$lib/data.json';
export async function load(entry = "23", host = null) {
let data = null;
if (host === "localhost") {
data = localData;
} else {
const resp = await fetch(
`https://data.prgblockweek.com/${entry}/index.json`,
);
data = await resp.json();
}
data.events.sort((a, b) => (a.attendees || 0) < (b.attendees || 0) ? 1 : -1)
//console.log(data.events)
data.speakers = [];
for (const event of data.events) {
if (!event.speakers) continue;
for (const speaker of event.speakers) {
speaker.events = [event.id];
data.speakers.push(speaker);
}
}
return data;
export async function load(entry = '23', host = null) {
let data = null;
if (host === 'localhost') {
data = localData;
} else {
const resp = await fetch(`https://data.prgblockweek.com/${entry}/index.json`);
data = await resp.json();
}
data.events.sort((a, b) => ((a.attendees || 0) < (b.attendees || 0) ? 1 : -1));
//console.log(data.events)
data.speakers = [];
for (const event of data.events) {
if (!event.speakers) continue;
for (const speaker of event.speakers) {
speaker.events = [event.id];
data.speakers.push(speaker);
}
}
return data;
}
export async function loadSchema() {
const resp = await fetch(
"https://data.prgblockweek.com/schema/1/bundle.json",
);
return resp.json();
const resp = await fetch('https://data.prgblockweek.com/schema/1/bundle.json');
return resp.json();
}

View File

@ -1,44 +1,44 @@
export const config = {
collections: {
places: {
title: "Places",
model: "place",
img: "photo"
},
events: {
title: "Events",
model: "event"
},
speakers: {
title: "Speakers",
model: "speaker",
img: "photoUrl"
},
"media-partners": {
title: "Media Partners & Communities",
model: "media-partner",
aspect: "aspect-video"
},
benefits: {
title: "Benefits for visitors",
model: "benefit"
},
unions: {
title: "Event Unions",
model: "union"
},
chains: {
title: "Blockchains",
model: "chain"
}
},
eventTypeColors: {
conference: '#d3e5ee',
meetup: '#fdecc8',
hackathon: '#dad7ed',
expo: '#eee0da',
party: '#dbeddb'
},
date: "2023-06-02",
days: 10,
}
collections: {
places: {
title: 'Places',
model: 'place',
img: 'photo'
},
events: {
title: 'Events',
model: 'event'
},
speakers: {
title: 'Speakers',
model: 'speaker',
img: 'photoUrl'
},
'media-partners': {
title: 'Media Partners & Communities',
model: 'media-partner',
aspect: 'aspect-video'
},
benefits: {
title: 'Benefits for visitors',
model: 'benefit'
},
unions: {
title: 'Event Unions',
model: 'union'
},
chains: {
title: 'Blockchains',
model: 'chain'
}
},
eventTypeColors: {
conference: '#d3e5ee',
meetup: '#fdecc8',
hackathon: '#dad7ed',
expo: '#eee0da',
party: '#dbeddb'
},
date: '2023-06-02',
days: 10
};

View File

@ -1,32 +1,37 @@
import { format, addDays } from 'date-fns';
const langMapper = {
czech: 'cz',
slovak: 'sk',
english: 'gb'
czech: 'cz',
slovak: 'sk',
english: 'gb'
};
export function formatItemDate(item, opts = {}) {
let dt = format(new Date(item.date), 'MMMM d' + (opts.full && item.days === 1 ? ', yyyy' : ''));
if (item.days > 1) {
dt +=
'-' + format(addDays(new Date(item.date), item.days - 1), 'd' + (opts.full ? ', yyyy' : ''));
}
return dt;
}
export function formatItemDate (item, opts = {}) {
let dt = format(new Date(item.date), "MMMM d" + (opts.full && item.days === 1 ? ', yyyy' : ''))
if (item.days > 1) {
dt += "-" + format(addDays(new Date(item.date), item.days-1), "d"+ (opts.full ? ', yyyy' : ''))
}
return dt
}
export function bareDomain (link, type="") {
let out = link.replace(/https?:\/\/(twitter\.com\/|t\.me\/|www\.youtube\.com\/c\/|linkedin\.com\/in\/|www\.|)/g, '').replace(/\/$/, "")
if ([ "twitter", "telegram", "youtube" ].includes(type)) {
out = "@" + out
}
return out
export function bareDomain(link, type = '') {
let out = link
.replace(
/https?:\/\/(twitter\.com\/|t\.me\/|www\.youtube\.com\/c\/|linkedin\.com\/in\/|www\.|)/g,
''
)
.replace(/\/$/, '');
if (['twitter', 'telegram', 'youtube'].includes(type)) {
out = '@' + out;
}
return out;
}
export function getFlagEmoji(str, mapper = true) {
const codePoints = (mapper ? langMapper[str] : str)
.toUpperCase()
.split('')
.map(char => 127397 + char.charCodeAt());
return String.fromCodePoint(...codePoints);
}
const codePoints = (mapper ? langMapper[str] : str)
.toUpperCase()
.split('')
.map((char) => 127397 + char.charCodeAt());
return String.fromCodePoint(...codePoints);
}

View File

@ -1,20 +1,21 @@
<script>
import { page } from '$app/stores';
import "../app.css";
import { page } from '$app/stores';
import '../app.css';
$: homepage = !$page.params.type && !$page.params.date && $page.route.id !== "/[entry]/schedule"
$: homepage = !$page.params.type && !$page.params.date && $page.route.id !== '/[entry]/schedule';
</script>
{#if homepage}
<div class="px-6 xl:px-0 dark:bg-pbw-dark">
<div class="max-w-7xl mx-auto pt-10 pb-6">
<h1 class="text-5xl uppercase font-bold text-pbw-red"><a href="https://prgblockweek.com">Prague Blockchain Week 2023</a></h1>
<div class="text-4xl text-pbw-yellow">June 2-11, 2023</div>
</div>
</div>
<div class="px-6 xl:px-0 dark:bg-pbw-dark">
<div class="max-w-7xl mx-auto pt-10 pb-6">
<h1 class="text-5xl uppercase font-bold text-pbw-red">
<a href="https://prgblockweek.com">Prague Blockchain Week 2023</a>
</h1>
<div class="text-4xl text-pbw-yellow">June 2-11, 2023</div>
</div>
</div>
{/if}
<div class="pb-24 dark:bg-pbw-dark">
<slot />
</div>
<slot />
</div>

View File

@ -1,5 +1,5 @@
import { redirect } from "@sveltejs/kit";
import { redirect } from '@sveltejs/kit';
export function load() {
throw redirect(302, "/23");
throw redirect(302, '/23');
}

View File

@ -1,5 +1,5 @@
<svelte:head>
<title>Prague Blockchain Week | Explore</title>
<title>Prague Blockchain Week | Explore</title>
</svelte:head>
<div></div>
<div />

View File

@ -1,9 +1,9 @@
import * as dataApi from "$lib/dataApi";
import * as dataApi from '$lib/dataApi';
export async function load({ params, url }) {
return {
params,
bundle: await dataApi.load(params.entry, url.hostname),
schema: await dataApi.loadSchema(),
};
return {
params,
bundle: await dataApi.load(params.entry, url.hostname),
schema: await dataApi.loadSchema()
};
}

View File

@ -1,84 +1,151 @@
<script>
import CollectionList from '$lib/components/CollectionList.svelte';
import TimelineHeatmap from '$lib/components/TimelineHeatmap.svelte';
import Footer from '$lib/components/Footer.svelte';
import { page } from '$app/stores';
import CollectionList from '$lib/components/CollectionList.svelte';
import TimelineHeatmap from '$lib/components/TimelineHeatmap.svelte';
import Footer from '$lib/components/Footer.svelte';
import { page } from '$app/stores';
export let data;
$: entry = $page.params.entry
$: conferences = data.bundle.events.filter(e => e.types.find(t => ['conference', 'hackathon'].includes(t)))
$: otherEvents = data.bundle.events.filter(e => !e.types.find(t => ['conference', 'hackathon'].includes(t)))
export let data;
$: entry = $page.params.entry;
$: conferences = data.bundle.events.filter((e) =>
e.types.find((t) => ['conference', 'hackathon'].includes(t))
);
$: otherEvents = data.bundle.events.filter(
(e) => !e.types.find((t) => ['conference', 'hackathon'].includes(t))
);
const collections = [
{ title: "Days", value: 10, col: "schedule" },
{ title: "Events", col: "events" },
{ title: "Speakers", col: "speakers" },
{ title: "Places", col: "places" },
{ title: "Media Partners", col: "media-partners" },
//{ title: "Blockchains", col: "chains" },
//{ title: "Unions", col: "unions" },
{ title: "Benefits", col: "benefits" },
]
const collections = [
{ title: 'Days', value: 10, col: 'schedule' },
{ title: 'Events', col: 'events' },
{ title: 'Speakers', col: