This commit is contained in:
Andras Schmelczer 2026-05-17 10:16:30 +01:00
parent 47d89f6fad
commit 017902b8e6
82 changed files with 331466 additions and 54841 deletions

View file

@ -0,0 +1,100 @@
import * as Sentry from '@sentry/react';
import type { ReactElement, ReactNode } from 'react';
declare const __BUGSINK_DSN__: string | undefined;
declare const __BUGSINK_ENVIRONMENT__: string | undefined;
declare const __BUGSINK_RELEASE__: string | undefined;
declare const __BUGSINK_SEND_DEFAULT_PII__: boolean | undefined;
interface BugsinkConfig {
dsn?: string;
environment?: string;
release?: string;
sendDefaultPii?: boolean;
}
declare global {
interface Window {
__PERFECT_POSTCODE_BUGSINK__?: BugsinkConfig;
}
}
function nonempty(value: unknown): string | undefined {
if (typeof value !== 'string') {
return undefined;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : undefined;
}
function readBuildTimeString(value: unknown): string | undefined {
return nonempty(value);
}
function readBuildTimeBoolean(value: unknown): boolean {
return typeof value === 'boolean' ? value : false;
}
function readRuntimeConfig(): BugsinkConfig {
if (typeof document === 'undefined') {
return {};
}
const element = document.getElementById('perfect-postcode-bugsink-config');
const json = element?.textContent?.trim();
if (!json || json === '__PERFECT_POSTCODE_BUGSINK_CONFIG__') {
return window.__PERFECT_POSTCODE_BUGSINK__ ?? {};
}
try {
const config = JSON.parse(json) as BugsinkConfig;
window.__PERFECT_POSTCODE_BUGSINK__ = config;
return config;
} catch {
return window.__PERFECT_POSTCODE_BUGSINK__ ?? {};
}
}
export function initBugsink(): boolean {
const runtimeConfig = readRuntimeConfig();
const dsn =
nonempty(runtimeConfig.dsn) ??
readBuildTimeString(typeof __BUGSINK_DSN__ === 'string' ? __BUGSINK_DSN__ : undefined);
if (!dsn) {
return false;
}
Sentry.init({
dsn,
environment:
nonempty(runtimeConfig.environment) ??
readBuildTimeString(
typeof __BUGSINK_ENVIRONMENT__ === 'string' ? __BUGSINK_ENVIRONMENT__ : undefined
),
release:
nonempty(runtimeConfig.release) ??
readBuildTimeString(typeof __BUGSINK_RELEASE__ === 'string' ? __BUGSINK_RELEASE__ : undefined),
sendDefaultPii:
runtimeConfig.sendDefaultPii ??
readBuildTimeBoolean(
typeof __BUGSINK_SEND_DEFAULT_PII__ === 'boolean'
? __BUGSINK_SEND_DEFAULT_PII__
: undefined
),
tracesSampleRate: 0,
});
Sentry.setTag('app', 'frontend');
return true;
}
export function BugsinkErrorBoundary({
children,
fallback,
}: {
children: ReactNode;
fallback: ReactElement;
}) {
return <Sentry.ErrorBoundary fallback={fallback}>{children}</Sentry.ErrorBoundary>;
}

View file

@ -16,6 +16,8 @@ const GROUP_ICONS: Record<string, ComponentType<{ className?: string }>> = {
'Property prices': TagIcon,
Transport: RouteIcon,
Education: GraduationCapIcon,
Schools: GraduationCapIcon,
'Defining characteristics': TreeIcon,
'Area development': ChartBarIcon,
Crime: ShieldIcon,
Neighbours: UsersIcon,

View file

@ -197,7 +197,7 @@ export function getSchoolFilterMeta(features: FeatureMeta[]): FeatureMeta {
return {
name: SCHOOL_FILTER_NAME,
type: 'numeric',
group: 'Education',
group: 'Schools',
min: sourceFeature?.min ?? 0,
max: sourceFeature?.max ?? 10,
step: 1,