Skip to content

Commit

Permalink
Merge pull request #857 from tradingstrategy-ai/856-strategy-microsite
Browse files Browse the repository at this point in the history
Strategy microsite
  • Loading branch information
kenkunz authored Dec 2, 2024
2 parents 3568335 + adfa506 commit aeebde2
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 40 deletions.
27 changes: 17 additions & 10 deletions src/hooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Handle, HandleServerError } from '@sveltejs/kit';
import { sequence } from '@sveltejs/kit/hooks';
import * as Sentry from '@sentry/sveltekit';
import { env } from '$env/dynamic/private';
import { backendUrl, backendInternalUrl, sentryDsn, siteMode, version } from '$lib/config';
import { backendUrl, backendInternalUrl, sentryDsn, siteMode, strategyMicrosite, version } from '$lib/config';
import { countryCodeSchema } from '$lib/helpers/geo';
import { parseDate } from '$lib/helpers/date';

Expand Down Expand Up @@ -47,15 +47,22 @@ export const handleError = Sentry.handleErrorWithSentry((async ({ error }) => {
}) as HandleServerError);

const handleColorMode: Handle = async ({ event, resolve }) => {
const colorMode = event.cookies.get('color-mode') || 'system';

// update the cookie (in case not set and to update expiration)
event.cookies.set('color-mode', colorMode, {
httpOnly: false,
secure: false,
path: '/',
maxAge: ONE_YEAR
});
let colorMode: string;

if (strategyMicrosite) {
// ignore cookie value and set to 'dark' for custom strategy site
colorMode = 'dark';
} else {
// check and update cookie value and expiration
colorMode = event.cookies.get('color-mode') || 'system';

event.cookies.set('color-mode', colorMode, {
httpOnly: false,
secure: false,
path: '/',
maxAge: ONE_YEAR
});
}

return resolve(event, {
transformPageChunk({ html }) {
Expand Down
40 changes: 17 additions & 23 deletions src/lib/breadcrumb/Breadcrumbs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ https://search.google.com/structured-data/testing-tool
<Breadcrumbs labels={{ 'url-path-segment': 'Human Readable Name' }} />
```
-->
<script context="module" lang="ts">
type BreadcrumbLabels = Record<string, string>;
<script lang="ts">
import { page } from '$app/stores';
import { Section } from '$lib/components';
interface Breadcrumb {
href: string;
label: string;
}
type Props = {
labels?: Record<string, string>;
startAt?: number;
};
let { labels = {}, startAt = 0 }: Props = $props();
const baseLabels: BreadcrumbLabels = {
const baseLabels: Record<string, string> = {
about: 'About',
backtesting: 'Historical data',
blog: 'Blog',
Expand All @@ -32,23 +35,14 @@ https://search.google.com/structured-data/testing-tool
tokens: 'Tokens',
'trading-view': 'Trading data'
};
</script>
<script lang="ts">
import { page } from '$app/stores';
import { Section } from '$lib/components';
export let labels: BreadcrumbLabels = {};
$: breadcrumbs = buildBreadcrumbs($page.url.pathname, { ...baseLabels, ...labels });
function buildBreadcrumbs(pagePath: string, labels: BreadcrumbLabels): Breadcrumb[] {
const segments = pagePath.split('/');
return segments.slice(1).map((segment, index) => ({
href: segments.slice(0, index + 2).join('/'),
label: labels[segment] ?? segment
let breadcrumbs = $derived.by(() => {
const segments = $page.url.pathname.split('/');
return segments.slice(startAt + 1).map((segment, index) => ({
href: segments.slice(0, index + startAt + 2).join('/'),
label: labels[segment] ?? baseLabels[segment] ?? segment
}));
}
});
</script>

<Section tag="nav" ariaAttrs={{ 'aria-label': 'breadcrumb' }}>
Expand All @@ -65,7 +59,7 @@ https://search.google.com/structured-data/testing-tool
<span itemprop="name">{label}</span>
</span>
{/if}
<meta itemprop="position" content={index + 1} />
<meta itemprop="position" content={String(index + 1)} />
</li>
{/each}
</ol>
Expand Down
8 changes: 8 additions & 0 deletions src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ export const strategyConfig = config((jsonStr: string) => {
}
}, 'STRATEGIES');

/**
* If a configured strategy includes a truthy `microsite` value, set strategyMicrosite
* to the strategy's ID (otherwise undefined)
*/
export const strategyMicrosite = ((strategies: any[]) => {
return strategies.find((s) => s.microsite)?.id;
})(strategyConfig) as string | undefined;

/**
* Load WalletConnect projectId and warn if not available.
*/
Expand Down
1 change: 1 addition & 0 deletions src/lib/trade-executor/schemas/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const strategyConfigurationSchema = z.object({
new_version_id: z.string().optional(),
hiddenPositions: primaryKey.array().default([]),
frontpage: z.boolean().default(false),
microsite: z.boolean().default(false),
depositOnEnzyme: z.boolean().default(false)
});
export type StrategyConfiguration = z.infer<typeof strategyConfigurationSchema>;
Expand Down
23 changes: 21 additions & 2 deletions src/routes/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
// Make admin, ipCountry and announcementDismissedAt available to all layouts/pages
export async function load({ locals }) {
import { strategyMicrosite } from '$lib/config';
import { error, redirect } from '@sveltejs/kit';

export async function load({ locals, route }) {
// restrict routes on custom strategy site
if (strategyMicrosite) {
restrictMicrositeRoutes(route.id!, strategyMicrosite);
}

// Make admin, ipCountry and announcementDismissedAt available to all layouts/pages
const { admin, ipCountry, announcementDismissedAt } = locals;
return { admin, ipCountry, announcementDismissedAt };
}

function restrictMicrositeRoutes(routeId: string, strategyId: string) {
// redirect home page to strategy page
if (routeId === '/') redirect(302, `/strategies/${strategyId}`);

// return 404 for all pages other than strategies, glossary and diagnostics
const segments = routeId.split('/').slice(1);
if (!['strategies', 'glossary', 'diagnostics'].includes(segments[0])) {
error(404, 'Not found');
}
}
4 changes: 2 additions & 2 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Root layout
-->
<script lang="ts">
import { announcement } from '$lib/config';
import { announcement, strategyMicrosite } from '$lib/config';
import { browser } from '$app/environment';
import { page } from '$app/stores';
import { beforeNavigate } from '$app/navigation';
Expand Down Expand Up @@ -51,7 +51,7 @@

<AppHead />
<PageLoadProgressBar />
{#if !$page.data.skipNavbar}
{#if !($page.data.skipNavbar || strategyMicrosite)}
{#if announcement}
<AnnouncementBanner {...announcement} dismissedAt={announcementDismissedAt} />
{/if}
Expand Down
32 changes: 29 additions & 3 deletions src/routes/strategies/[strategy]/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { strategyMicrosite } from '$lib/config';
import { page } from '$app/stores';
import Breadcrumbs from '$lib/breadcrumb/Breadcrumbs.svelte';
import { AlertList, DataBadge, PageHeading } from '$lib/components';
Expand Down Expand Up @@ -29,14 +30,27 @@
};
</script>

<Breadcrumbs labels={breadcrumbs} />
{#if !strategyMicrosite}
<Breadcrumbs labels={breadcrumbs} />
{/if}

{#if $page.data.skipSideNav}
{#if strategyMicrosite}
<Breadcrumbs labels={breadcrumbs} startAt={1} />
{/if}
<slot />
{:else}
<main class="strategy-layout ds-container ds-3">
<main class="strategy-layout ds-container ds-3" class:microsite={strategyMicrosite}>
<PageHeading description={strategy.short_description}>
<StrategyIcon slot="icon" {strategy} />
<svelte:fragment slot="icon">
{#if strategyMicrosite && !isOverviewPage}
<a href="/strategies/{strategy.id}" aria-label="Home">
<StrategyIcon {strategy} />
</a>
{:else}
<StrategyIcon {strategy} />
{/if}
</svelte:fragment>
<div class="title" slot="title">
{strategy.name}

Expand Down Expand Up @@ -95,6 +109,18 @@
display: grid;
gap: var(--space-md);
&.microsite {
margin-top: 1.5rem;
@media (--viewport-xs) {
margin-top: 1rem;
}
a {
width: 100%;
}
}
:global(.badge) {
font-size: clamp(11px, 0.45em, 16px);
margin-inline: 0.25em;
Expand Down

0 comments on commit aeebde2

Please sign in to comment.