🎨 Cleanup code formatting

This commit is contained in:
2024-02-02 23:02:39 +01:00
parent f6bd241db3
commit e98b24303c
26 changed files with 1943 additions and 2010 deletions

View File

@@ -32,6 +32,7 @@
"matrix-widget-api": "^1.1.1", "matrix-widget-api": "^1.1.1",
"ol": "^7.3.0", "ol": "^7.3.0",
"solid-js": "^1.6.6", "solid-js": "^1.6.6",
"solid-transition-group": "^0.0.10" "solid-transition-group": "^0.0.10",
"solidjs-lazily": "^0.1.2"
} }
} }

View File

@@ -1,15 +1,12 @@
import { Component, createSignal } from 'solid-js'; import { Component, createSignal, onCleanup, onMount } from 'solid-js';
import { IVisibilityActionRequest, MatrixCapabilities, WidgetApi, WidgetApiToWidgetAction } from 'matrix-widget-api'; // import { IVisibilityActionRequest, MatrixCapabilities, WidgetApi, WidgetApiToWidgetAction } from 'matrix-widget-api';
import { HopeProvider } from "@hope-ui/solid";
import { BusinessDataProvider } from './businessData'; import { BusinessDataProvider } from './businessData';
import { AppContextProvider } from './appContext'; import { AppContextProvider } from './appContext';
import { PassagesDisplay } from './passagesDisplay'; import { PassagesDisplay } from './passagesDisplay';
import { StopsSearchMenu } from './stopsSearchMenu/stopsSearchMenu'; import { StopsSearchMenu } from './stopsSearchMenu/stopsSearchMenu';
import "./App.scss"; import "./App.scss";
import { onCleanup, onMount } from 'solid-js';
function parseFragment() { function parseFragment() {
@@ -28,21 +25,21 @@ const App: Component = () => {
console.log("App: widgetId:" + widgetId); console.log("App: widgetId:" + widgetId);
console.log("App: userId:" + userId); console.log("App: userId:" + userId);
const api = new WidgetApi(widgetId != null ? widgetId : undefined); // const api = new WidgetApi(widgetId != null ? widgetId : undefined);
api.requestCapability(MatrixCapabilities.AlwaysOnScreen); // api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
api.start(); // api.start();
api.on("ready", function() { // api.on("ready", function() {
console.log("App: widget API is READY !!!!"); // console.log("App: widget API is READY !!!!");
}); // });
// Seems to don´t be used... // Seems to don´t be used...
api.on(`action:${WidgetApiToWidgetAction.UpdateVisibility}`, (ev: CustomEvent<IVisibilityActionRequest>) => { // api.on(`action:${WidgetApiToWidgetAction.UpdateVisibility}`, (ev: CustomEvent<IVisibilityActionRequest>) => {
console.log("App: Visibility change"); // console.log("App: Visibility change");
ev.preventDefault(); // we're handling it, so stop the widget API from doing something. // ev.preventDefault(); // we're handling it, so stop the widget API from doing something.
console.log("App: ", ev.detail); // custom handling here // console.log("App: ", ev.detail); // custom handling here
/* api.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{}); */ // /* api.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{}); */
api.transport.reply(ev.detail, {}); // api.transport.reply(ev.detail, {});
}); // });
createSignal({ createSignal({
height: window.innerHeight, height: window.innerHeight,
@@ -71,10 +68,8 @@ const App: Component = () => {
window.removeEventListener('resize', onResize); window.removeEventListener('resize', onResize);
}) })
return ( return <BusinessDataProvider>
<BusinessDataProvider>
<AppContextProvider> <AppContextProvider>
<HopeProvider>
<div class="App"> <div class="App">
<div class="panel"> <div class="panel">
<StopsSearchMenu /> <StopsSearchMenu />
@@ -83,10 +78,8 @@ const App: Component = () => {
<PassagesDisplay /> <PassagesDisplay />
</div> </div>
</div> </div>
</HopeProvider>
</AppContextProvider> </AppContextProvider>
</BusinessDataProvider> </BusinessDataProvider>;
);
}; };
export default App; export default App;

View File

@@ -6,7 +6,7 @@ import { Stop } from './types';
export interface AppContextStore { export interface AppContextStore {
getDisplayedStops: () => Stop[]; getDisplayedStops: () => Stop[];
setDisplayedStops: (stops: Stop[]) => void; setDisplayedStops: (stops: Stop[]) => void;
}; }
export const AppContextContext = createContext<AppContextStore>(); export const AppContextContext = createContext<AppContextStore>();
@@ -26,10 +26,7 @@ export function AppContextProvider(props: { children: JSX.Element }) {
const setDisplayedStops = (stops: Stop[]): void => { const setDisplayedStops = (stops: Stop[]): void => {
console.log("setDisplayedStops=", stops); console.log("setDisplayedStops=", stops);
// setStore((s: Store) => {
setStore('displayedStops', stops); setStore('displayedStops', stops);
// return s;
// });
} }
return ( return (
@@ -39,5 +36,4 @@ export function AppContextProvider(props: { children: JSX.Element }) {
{props.children} {props.children}
</AppContextContext.Provider> </AppContextContext.Provider>
); );
}
};

View File

@@ -6,6 +6,7 @@ import { Line, Lines, Passage, Passages, Stop, StopShape, StopShapes, Stops } fr
export type StopDestinations = Record<string, string[]>; export type StopDestinations = Record<string, string[]>;
export interface BusinessDataStore { export interface BusinessDataStore {
getLine: (lineId: string) => Promise<Line>; getLine: (lineId: string) => Promise<Line>;
getLinePassages: (lineId: string) => Record<string, Passage[]>; getLinePassages: (lineId: string) => Record<string, Passage[]>;
@@ -23,7 +24,7 @@ export interface BusinessDataStore {
getStopDestinations: (stopId: number) => Promise<StopDestinations | undefined>; getStopDestinations: (stopId: number) => Promise<StopDestinations | undefined>;
getStopShape: (stopId: number) => Promise<StopShape | undefined>; getStopShape: (stopId: number) => Promise<StopShape | undefined>;
}; }
export const BusinessDataContext = createContext<BusinessDataStore>(); export const BusinessDataContext = createContext<BusinessDataStore>();
@@ -120,7 +121,7 @@ export function BusinessDataProvider(props: { children: JSX.Element }) {
for (const lineId of Object.keys(passages)) { for (const lineId of Object.keys(passages)) {
const newLinePassages = passages[lineId]; const newLinePassages = passages[lineId];
const linePassages = storePassages[lineId]; const linePassages = storePassages[lineId];
if (linePassages === undefined) { if (linePassages === undefined || Object.keys(linePassages).length == 0) {
setStore('passages', lineId, newLinePassages); setStore('passages', lineId, newLinePassages);
} }
else { else {
@@ -159,7 +160,7 @@ ${linePassagesDestination.length} here... refresh all them.`);
const clearPassages = (): void => { const clearPassages = (): void => {
setStore((s: Store): Store => { setStore((s: Store): Store => {
for (const lineId of Object.keys(s.passages)) { for (const lineId of Object.keys(s.passages)) {
setStore('passages', lineId, undefined); setStore('passages', lineId, {});
} }
return s; return s;
}); });
@@ -231,21 +232,9 @@ ${linePassagesDestination.length} here... refresh all them.`);
getLine, getLinePassages, getLineDestinations, getDestinationPassages, passages, getPassagesLineIds, getLine, getLinePassages, getLineDestinations, getDestinationPassages, passages, getPassagesLineIds,
refreshPassages, addPassages, clearPassages, refreshPassages, addPassages, clearPassages,
getStop, getStopDestinations, getStopShape, searchStopByName getStop, getStopDestinations, getStopShape, searchStopByName
}}> }}>
{props.children} {props.children}
</BusinessDataContext.Provider> </BusinessDataContext.Provider>
); );
} }
export interface BusinessDataStore {
getLine: (lineId: string) => Promise<Line>;
getLinePassages: (lineId: string) => Record<string, Passage[]>;
passages: () => Passages;
refreshPassages: (stopId: number) => Promise<void>;
addPassages: (passages: Passages) => void;
clearPassages: () => void;
getStop: (stopId: number) => Stop | undefined;
searchStopByName: (name: string) => Promise<Stops>;
};

View File

@@ -4,7 +4,8 @@ import { VoidComponent } from "solid-js";
export const IconHamburgerMenu: VoidComponent<{}> = () => { export const IconHamburgerMenu: VoidComponent<{}> = () => {
return ( return (
<svg class="iconHamburgerMenu" viewBox="0 0 15 15"> <svg class="iconHamburgerMenu" viewBox="0 0 15 15">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386 <path
d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386
13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5 13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5
8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761 8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761
13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z" 13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z"

View File

@@ -14,6 +14,7 @@
} }
html, body { html, body {
height: 100vh;
aspect-ratio: 16/9; aspect-ratio: 16/9;
margin: 0; margin: 0;

View File

@@ -1,7 +1,6 @@
import { createContext, createEffect, createResource, createSignal, For, JSX, ParentComponent, Show, useContext, VoidComponent } from "solid-js"; import { createContext, createEffect, createResource, createSignal, For, JSX, ParentComponent, Show, useContext, VoidComponent } from "solid-js";
import { createStore } from "solid-js/store"; import { createStore } from "solid-js/store";
import { createDateNow } from "@solid-primitives/date"; import { createDateNow } from "@solid-primitives/date";
import { IconButton, Menu, MenuTrigger, MenuContent, MenuItem } from "@hope-ui/solid";
import { format } from "date-fns"; import { format } from "date-fns";
import { BusinessDataContext, BusinessDataStore } from "./businessData"; import { BusinessDataContext, BusinessDataStore } from "./businessData";
@@ -9,7 +8,6 @@ import { AppContextContext, AppContextStore } from "./appContext";
import { getTransportModeSrc, PositionedPanel } from "./utils"; import { getTransportModeSrc, PositionedPanel } from "./utils";
import { PassagesPanel } from "./passagesPanel"; import { PassagesPanel } from "./passagesPanel";
import { IconHamburgerMenu } from './extra/iconHamburgerMenu';
import "./passagesDisplay.scss"; import "./passagesDisplay.scss";
@@ -25,7 +23,7 @@ interface PassagesDisplayStore {
getDisplayedPanelId: () => number; getDisplayedPanelId: () => number;
setDisplayedPanelId: (panelId: number) => void; setDisplayedPanelId: (panelId: number) => void;
}; }
const PassagesDisplayContext = createContext<PassagesDisplayStore>(); const PassagesDisplayContext = createContext<PassagesDisplayStore>();
@@ -91,7 +89,6 @@ const Header: VoidComponent<{ title: string }> = (props) => {
return <div />; return <div />;
const { getLine, passages } = businessDataStore; const { getLine, passages } = businessDataStore;
const { isPassagesRefreshEnabled, togglePassagesRefresh } = passagesDisplayStore;
const [dateNow] = createDateNow(1000); const [dateNow] = createDateNow(1000);
@@ -113,16 +110,14 @@ const Header: VoidComponent<{ title: string }> = (props) => {
setLinesIds(Object.keys(passages())); setLinesIds(Object.keys(passages()));
}); });
return ( return <div class="header">
<div class="header">
<Show when={transportModeUrls() !== undefined} > <Show when={transportModeUrls() !== undefined} >
<For each={transportModeUrls()}> <For each={transportModeUrls()}>
{(url) => {(url) =>
<div class="transportMode"> <div class="transportMode">
<img src={url} /> <img src={url} />
</div> </div>
} }</For>
</For>
</Show> </Show>
<div class="title"> <div class="title">
<svg viewBox="0 0 1260 50"> <svg viewBox="0 0 1260 50">
@@ -132,15 +127,6 @@ const Header: VoidComponent<{ title: string }> = (props) => {
</svg> </svg>
</div> </div>
<div class="menu"> <div class="menu">
<Menu>
<MenuTrigger
as={IconButton}
icon=<IconHamburgerMenu />
/>
<MenuContent>
<MenuItem onSelect={() => togglePassagesRefresh()}>{isPassagesRefreshEnabled() ? "Disable" : "Enable"}</MenuItem>
</MenuContent>
</Menu>
</div> </div>
<div class="clock"> <div class="clock">
<svg viewBox="0 0 115 43"> <svg viewBox="0 0 115 43">
@@ -149,8 +135,7 @@ const Header: VoidComponent<{ title: string }> = (props) => {
</text> </text>
</svg> </svg>
</div> </div>
</div > </div>;
);
}; };
const Footer: VoidComponent<{}> = () => { const Footer: VoidComponent<{}> = () => {
@@ -176,8 +161,7 @@ const Footer: VoidComponent<{}> = () => {
</svg> </svg>
</div> </div>
); );
}} }}</For>
</For>
</div> </div>
); );
} }
@@ -286,13 +270,11 @@ export const PassagesDisplay: ParentComponent = () => {
const syncPeriodMsec = 20 * 1000; const syncPeriodMsec = 20 * 1000;
const panelSwitchPeriodMsec = 4 * 1000; const panelSwitchPeriodMsec = 4 * 1000;
return ( return <div class="passagesDisplay">
<div class="passagesDisplay">
<PassagesDisplayProvider> <PassagesDisplayProvider>
<Header title="Prochains passages" /> <Header title="Prochains passages" />
<Body maxPassagesPerPanel={MAX_PASSAGES_PER_PANEL} syncPeriodMsec={syncPeriodMsec} panelSwitchPeriodMsec={panelSwitchPeriodMsec} /> <Body maxPassagesPerPanel={MAX_PASSAGES_PER_PANEL} syncPeriodMsec={syncPeriodMsec} panelSwitchPeriodMsec={panelSwitchPeriodMsec} />
<Footer /> <Footer />
</PassagesDisplayProvider> </PassagesDisplayProvider>
</div> </div>;
);
}; };

View File

@@ -14,15 +14,13 @@ import "./passagesPanel.scss";
const UnavailablePassage: VoidComponent<{ style: string }> = (props) => { const UnavailablePassage: VoidComponent<{ style: string }> = (props) => {
const textStyle = { fill: "#000000" }; const textStyle = { fill: "#000000" };
return ( return <div class={props.style}>
<div class={props.style}>
<svg viewBox="0 0 230 110"> <svg viewBox="0 0 230 110">
<text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text> <text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text>
<text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text> <text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text>
<text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text> <text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text>
</svg> </svg>
</div> </div>;
);
} }
const Platform: VoidComponent<{ name: string }> = (props) => { const Platform: VoidComponent<{ name: string }> = (props) => {
@@ -43,14 +41,12 @@ const Platform: VoidComponent<{ name: string }> = (props) => {
} }
}); });
return ( return <svg class="platform" viewBox={`0 0 ${viewBoxWidthPx} 40`}>
<svg class="platform" viewBox={`0 0 ${viewBoxWidthPx} 40`}>
<rect ref={rectRef} x="0" y="0" height="100%" rx="9" ry="9" /> <rect ref={rectRef} x="0" y="0" height="100%" rx="9" ry="9" />
<text ref={textRef} x="100%" y="55%" dominant-baseline="middle" text-anchor="end" font-size="25" style={{ fill: "#ffffff" }}> <text ref={textRef} x="100%" y="55%" dominant-baseline="middle" text-anchor="end" font-size="25" style={{ fill: "#ffffff" }}>
QUAI {props.name} QUAI {props.name}
</text> </text>
</svg> </svg>;
);
} }
const TtwPassage: VoidComponent<{ const TtwPassage: VoidComponent<{
@@ -88,8 +84,7 @@ const TtwPassage: VoidComponent<{
</Motion.text> </Motion.text>
</svg>; </svg>;
return ( return <Show when={passage !== undefined} fallback={<UnavailablePassage style={props.fallbackStyle} />}>
<Show when={passage !== undefined} fallback=<UnavailablePassage style={props.fallbackStyle} />>
<Show <Show
when={passage.arrivalPlatformName !== null} when={passage.arrivalPlatformName !== null}
fallback={ fallback={
@@ -101,8 +96,7 @@ const TtwPassage: VoidComponent<{
<Platform name={passage.arrivalPlatformName} /> <Platform name={passage.arrivalPlatformName} />
</div> </div>
</Show> </Show>
</Show > </Show>;
);
}); });
} }
@@ -122,8 +116,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) }; // const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) }; const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };
return ( return <div class="line">
<div class="line">
<div class="transportMode"> <div class="transportMode">
{renderLineTransportMode(props.line)} {renderLineTransportMode(props.line)}
</div> </div>
@@ -142,8 +135,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
<TtwPassage line={props.line} destination={props.destination} index={1} <TtwPassage line={props.line} destination={props.destination} index={1}
style="secondPassage" withPlatformStyle="withPlatformSecondPassage" style="secondPassage" withPlatformStyle="withPlatformSecondPassage"
fontSize={45} fallbackStyle="unavailableSecondPassage" /> fontSize={45} fallbackStyle="unavailableSecondPassage" />
</div > </div>;
);
} }
export type PassagesPanelComponentProps = ParentProps & { stopId: number, lineIds: string[], show: boolean }; export type PassagesPanelComponentProps = ParentProps & { stopId: number, lineIds: string[], show: boolean };
@@ -162,19 +154,16 @@ export const PassagesPanel: PassagesPanelComponent = (props) => {
} }
const [lines] = createResource<Line[], string[]>(props.lineIds, getLines); const [lines] = createResource<Line[], string[]>(props.lineIds, getLines);
return ( return <div classList={{ "passagesContainer": true, "displayed": props.show }} >
<div classList={{ ["passagesContainer"]: true, ["displayed"]: props.show }} >
<Show when={lines() !== undefined} > <Show when={lines() !== undefined} >
<For each={lines()}> <For each={lines()}>
{(line) => {(line) =>
<Show when={getLineDestinations(line.id) !== undefined}> <Show when={getLineDestinations(line.id) !== undefined}>
<For each={getLineDestinations(line.id)}> <For each={getLineDestinations(line.id)}>{
{(destination) => <DestinationPassages line={line} destination={destination} />} (destination) => <DestinationPassages line={line} destination={destination} />
</For> }</For>
</Show> </Show>
} }</For>
</For>
</Show> </Show>
</div > </div>;
);
} }

View File

@@ -1,8 +1,8 @@
import { batch, createContext, JSX } from 'solid-js'; import { createContext, JSX } from 'solid-js';
import { createStore } from 'solid-js/store'; import { createStore } from 'solid-js/store';
import { Marker as LeafletMarker } from 'leaflet'; import { Marker as LeafletMarker } from 'leaflet';
import { Stop, Stops } from './types'; import { Stop } from './types';
export type ByStopIdMarkers = Record<number, LeafletMarker[] | undefined>; export type ByStopIdMarkers = Record<number, LeafletMarker[] | undefined>;
@@ -52,9 +52,7 @@ export function SearchProvider(props: { children: JSX.Element }) {
setStore('markers', stopId, markers); setStore('markers', stopId, markers);
} }
return ( return <SearchContext.Provider value={{ getFoundStops, setFoundStops, getDisplayedStops, setDisplayedStops, addMarkers }}>
<SearchContext.Provider value={{ getFoundStops, setFoundStops, getDisplayedStops, setDisplayedStops, addMarkers }}>
{props.children} {props.children}
</SearchContext.Provider> </SearchContext.Provider>;
);
} }

View File

@@ -41,7 +41,7 @@ export const Map: ParentComponent<{}> = () => {
// TODO: Set padding according to the marker design. // TODO: Set padding according to the marker design.
const fitPointsPadding = [50, 50, 50, 50]; const fitPointsPadding = [50, 50, 50, 50];
let mapDiv: HTMLDivElement | undefined = undefined; let mapDiv: HTMLDivElement | undefined;
let popup: StopPopup | undefined = undefined; let popup: StopPopup | undefined = undefined;
const stopVectorSource = new OlVectorSource({ features: [] }); const stopVectorSource = new OlVectorSource({ features: [] });
@@ -76,6 +76,7 @@ export const Map: ParentComponent<{}> = () => {
], ],
overlays: [overlay], overlays: [overlay],
}); });
console.log("map=", map);
map.on('singleclick', onClickedMap); map.on('singleclick', onClickedMap);
} }
@@ -108,7 +109,10 @@ export const Map: ParentComponent<{}> = () => {
} }
} }
onMount(() => buildMap(mapDiv)); onMount(() => {
buildMap(mapDiv);
})
;
// Filling the map with stops shape // Filling the map with stops shape
createEffect(() => { createEffect(() => {
@@ -207,8 +211,8 @@ export const Map: ParentComponent<{}> = () => {
} }
return <> return <>
<div ref={mapDiv} class="map"> <div ref={mapDiv!} class="map">
<StopPopup ref={popup} stop={selectedMapStop()} show={isPopupDisplayed()} /> <StopPopup ref={popup!} stop={selectedMapStop()} show={isPopupDisplayed()} />
</div> </div>
<For each={getFoundStops()}>{(stop) => <MapStop stop={stop} selected={selectedMapStop()} />}</For> <For each={getFoundStops()}>{(stop) => <MapStop stop={stop} selected={selectedMapStop()} />}</For>
</>; </>;

View File

@@ -149,8 +149,7 @@ export function SearchProvider(props: { children: JSX.Element }) {
setStore('mapFeatures', stopId, feature); setStore('mapFeatures', stopId, feature);
}; };
return ( return <SearchContext.Provider value={{
<SearchContext.Provider value={{
getSearchText, setSearchText, getSearchText, setSearchText,
getFoundStops, setFoundStops, getFoundStops, setFoundStops,
getDisplayedPanelId, setDisplayedPanelId, getDisplayedPanelId, setDisplayedPanelId,
@@ -160,6 +159,5 @@ export function SearchProvider(props: { children: JSX.Element }) {
getMapFeature, getAllMapFeatures, setMapFeature, getMapFeature, getAllMapFeatures, setMapFeature,
}}> }}>
{props.children} {props.children}
</SearchContext.Provider> </SearchContext.Provider>;
);
} }

View File

@@ -33,8 +33,7 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
const [lineReprs] = createResource<JSX.Element[], string[]>(props.stop.lines, fetchLinesRepr); const [lineReprs] = createResource<JSX.Element[], string[]>(props.stop.lines, fetchLinesRepr);
return ( return <div class="stop">
<div class="stop">
<svg class="name" viewBox={`0 0 215 ${fontSize}`}> <svg class="name" viewBox={`0 0 215 ${fontSize}`}>
<text <text
x="100%" y="55%" x="100%" y="55%"
@@ -44,8 +43,7 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
</text> </text>
</svg> </svg>
<For each={lineReprs()}>{(line: JSX.Element) => line}</For> <For each={lineReprs()}>{(line: JSX.Element) => line}</For>
</div> </div>;
);
} }
@@ -91,12 +89,11 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
} }
} }
const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] < const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] < TransportModeWeights[y] ? 1 : -1);
TransportModeWeights[y] ? 1 : -1);
return ( return <div class="lineRepr">
<div class="lineRepr"> <For each={sortedTransportModes}>
<For each={sortedTransportModes}>{(transportMode) => { {(transportMode) => {
const reprs = byModeReprs[transportMode]; const reprs = byModeReprs[transportMode];
const lineNames = Object.keys(reprs.lines).sort((x, y) => x.localeCompare(y)); const lineNames = Object.keys(reprs.lines).sort((x, y) => x.localeCompare(y));
return <> return <>
@@ -104,16 +101,14 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
<div class="linesRepresentationMatrix"> <div class="linesRepresentationMatrix">
<For each={lineNames}>{(lineName) => reprs.lines[lineName]}</For> <For each={lineNames}>{(lineName) => reprs.lines[lineName]}</For>
</div> </div>
</> </>;
}} }}</For>
</For> </div>;
</div >
);
} }
const [lineReprs] = createResource(props.stop, fetchLinesRepr); const [lineReprs] = createResource(props.stop, fetchLinesRepr);
return ( return <div
<div
class="stop" class="stop"
onClick={() => setDisplayedStops([props.stop])} onClick={() => setDisplayedStops([props.stop])}
onMouseEnter={() => setHighlightedStop(props.stop)} onMouseEnter={() => setHighlightedStop(props.stop)}
@@ -123,21 +118,17 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
<ScrollingText height={fontSize} width={100} content={props.stop.name} /> <ScrollingText height={fontSize} width={100} content={props.stop.name} />
</div> </div>
{lineReprs()} {lineReprs()}
</div> </div>;
);
} }
export const StopsPanel: ParentComponent<{ stops: Stop[], show: boolean }> = (props) => { export const StopsPanel: ParentComponent<{ stops: Stop[], show: boolean }> = (props) => {
return ( return <div classList={{ "stopPanel": true, "displayed": props.show }}>
<div classList={{ "stopPanel": true, "displayed": props.show }}>
<For each={props.stops.sort((x, y) => x.name.localeCompare(y.name))}> <For each={props.stops.sort((x, y) => x.name.localeCompare(y.name))}>
{(stop) => { {(stop) => {
return <Show when={stop.stops !== undefined} fallback={<StopRepr stop={stop} />}> return <Show when={stop.stops !== undefined} fallback={<StopRepr stop={stop} />}>
<StopAreaRepr stop={stop} /> <StopAreaRepr stop={stop} />
</Show>; </Show>;
}} }}</For>
</For> </div>;
</div>
);
} }

View File

@@ -29,8 +29,8 @@ export const StopPopup: ParentComponent<{ stop: Stop, show: boolean }> = (props)
} }
const [destinations] = createResource(() => props.stop, getDestinations); const [destinations] = createResource(() => props.stop, getDestinations);
return (
<div ref={popupDiv} classList={{ "popup": true, "displayed": props.show }}> return <div ref={popupDiv} classList={{ "popup": true, "displayed": props.show }}>
<div class="header">{props.stop?.name}</div> <div class="header">{props.stop?.name}</div>
<div class="body" > <div class="body" >
<For each={destinations()}> <For each={destinations()}>
@@ -41,9 +41,7 @@ export const StopPopup: ParentComponent<{ stop: Stop, show: boolean }> = (props)
<ScrollingText height={10} width={130} content={dst.destinations.join('/')} /> <ScrollingText height={10} width={130} content={dst.destinations.join('/')} />
</div> </div>
</div>; </div>;
}} }}</For>
</For>
</div> </div>
</div > </div>;
);
} }

View File

@@ -33,6 +33,7 @@
background-color: transparent; background-color: transparent;
.leftAddon { .leftAddon {
width: 17%; width: 17%;

View File

@@ -1,4 +1,4 @@
import { createEffect, For, JSX, lazy, ParentComponent, useContext, Show, VoidComponent } from 'solid-js'; import { createEffect, For, JSX, ParentComponent, useContext, Show, VoidComponent } from 'solid-js';
import { lazily } from 'solidjs-lazily'; import { lazily } from 'solidjs-lazily';
import { createScrollPosition } from "@solid-primitives/scroll"; import { createScrollPosition } from "@solid-primitives/scroll";
@@ -16,11 +16,10 @@ import "./stopsSearchMenu.scss";
const StopNameInput: VoidComponent<{ onInput: JSX.EventHandler<HTMLInputElement, InputEvent>, leftAddon: string, placeholder: string }> = (props) => { const StopNameInput: VoidComponent<{ onInput: JSX.EventHandler<HTMLInputElement, InputEvent>, leftAddon: string, placeholder: string }> = (props) => {
return ( return <div class="stopNameInput">
<div class="stopNameInput">
<div class="leftAddon">{props.leftAddon}</div> <div class="leftAddon">{props.leftAddon}</div>
<input type="text" oninput={props.onInput} placeholder={props.placeholder} /> <input type="text" oninput={props.onInput} placeholder={props.placeholder} />
</div>); </div>;
}; };
@@ -40,8 +39,7 @@ const Header: VoidComponent<{ title: string, minCharsNb: number }> = (props) =>
} }
} }
return ( return <div class="header">
<div class="header">
<div class="title"> <div class="title">
<svg viewBox="0 0 1260 50"> <svg viewBox="0 0 1260 50">
<text x="0" y="50%" dominant-baseline="middle" font-size="50" style="fill: #ffffff"> <text x="0" y="50%" dominant-baseline="middle" font-size="50" style="fill: #ffffff">
@@ -50,8 +48,7 @@ const Header: VoidComponent<{ title: string, minCharsNb: number }> = (props) =>
</svg> </svg>
</div> </div>
<StopNameInput onInput={onStopNameInput} leftAddon="🚉 🚏" placeholder="Stop name..." /> <StopNameInput onInput={onStopNameInput} leftAddon="🚉 🚏" placeholder="Stop name..." />
</div > </div>;
);
}; };
@@ -71,13 +68,15 @@ const StopsPanels: ParentComponent<{ maxStopsPerPanel: number }> = (props) => {
yStopsPanelsScroll(); yStopsPanelsScroll();
for (const panel of getPanels()) { for (const panel of getPanels()) {
const panelDiv = panel.panel(); const panelDiv = panel.panel;
if (panelDiv != null) {
const panelDivClientRect = panelDiv.getBoundingClientRect(); const panelDivClientRect = panelDiv.getBoundingClientRect();
if (panelDivClientRect.y > 0) { if (panelDivClientRect.y > 0) {
setDisplayedPanelId(panel.position); setDisplayedPanelId(panel.position);
break; break;
} }
} }
}
}); });
return ( return (
@@ -133,7 +132,8 @@ const MapPlaceholder: VoidComponent<{}> = () => {
} }
return <div return <div
class="mapPlaceholder" ondblclick={() => onDoubleClick()}> class="mapPlaceholder"
ondblclick={() => onDoubleClick()}>
Double-clic pour activer la carte Double-clic pour activer la carte
</div>; </div>;
}; };
@@ -166,35 +166,31 @@ const Footer: VoidComponent<{}> = () => {
const { getDisplayedPanelId, getPanels } = searchStore; const { getDisplayedPanelId, getPanels } = searchStore;
return ( return <div class="footer">
<div class="footer">
<For each={getPanels()}> <For each={getPanels()}>
{(panel) => { {(panel) => {
const position = panel.position; const position = panel.position;
return ( return (
<div> <div>
<svg viewBox="0 0 29 29"> <svg viewBox="0 0 29 29">
<circle cx="50%" cy="50%" r="13" stroke="#ffffff" stroke-width="3" <circle
cx="50%" cy="50%" r="13" stroke="#ffffff" stroke-width="3"
style={{ fill: `var(--idfm-${position == getDisplayedPanelId() ? "white" : "black"})` }} style={{ fill: `var(--idfm-${position == getDisplayedPanelId() ? "white" : "black"})` }}
/> />
</svg> </svg>
</div> </div>
); );
}} }}</For>
</For> </div>;
</div>
);
}; };
export const StopsSearchMenu: VoidComponent = () => { export const StopsSearchMenu: VoidComponent = () => {
return ( return <div class="stopSearchMenu">
<div class="stopSearchMenu">
<SearchProvider> <SearchProvider>
<Header title="Recherche de l'arrêt..." minCharsNb={4} /> <Header title="Recherche de l'arrêt..." minCharsNb={4} />
<Body /> <Body />
<Footer /> <Footer />
</SearchProvider> </SearchProvider>
</div> </div>;
);
}; };

View File

@@ -34,7 +34,7 @@ export class Passage {
this.arrivalStatus = arrivalStatus; this.arrivalStatus = arrivalStatus;
this.departStatus = departStatus; this.departStatus = departStatus;
} }
}; }
export type Passages = Record<string, Record<string, Passage[]>>; export type Passages = Record<string, Record<string, Passage[]>>;
@@ -59,7 +59,7 @@ export class Stop {
this.lines.push(...stop.lines); this.lines.push(...stop.lines);
} }
} }
}; }
export type Stops = Record<number, Stop>; export type Stops = Record<number, Stop>;
@@ -77,7 +77,7 @@ export class StopShape {
this.epsg3857_bbox = epsg3857_bbox; this.epsg3857_bbox = epsg3857_bbox;
this.epsg3857_points = epsg3857_points; this.epsg3857_points = epsg3857_points;
} }
}; }
export type StopShapes = Record<number, StopShape>; export type StopShapes = Record<number, StopShape>;
@@ -111,6 +111,6 @@ export class Line {
this.audibleSignsAvailable = audibleSignsAvailable; this.audibleSignsAvailable = audibleSignsAvailable;
this.stopIds = stopIds; this.stopIds = stopIds;
} }
}; }
export type Lines = Record<string, Line>; export type Lines = Record<string, Line>;

View File

@@ -36,11 +36,11 @@ export function renderLineTransportMode(line: Line): JSX.Element {
} }
function renderBusLinePicto(line: Line): JSX.Element { function renderBusLinePicto(line: Line): JSX.Element {
return ( return <div class="busLinePicto">
<div class="busLinePicto">
<svg viewBox="0 0 31.5 14"> <svg viewBox="0 0 31.5 14">
<rect x="0" y="0" width="31.5" height="14" rx="1.5" ry="1.5" style={{ fill: `#${line.backColorHexa}` }} /> <rect x="0" y="0" width="31.5" height="14" rx="1.5" ry="1.5" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%" <text
x="50%"
y="55%" y="55%"
dominant-baseline="middle" dominant-baseline="middle"
text-anchor="middle" text-anchor="middle"
@@ -49,18 +49,17 @@ function renderBusLinePicto(line: Line): JSX.Element {
{line.shortName} {line.shortName}
</text> </text>
</svg> </svg>
</div> </div>;
);
} }
function renderTramLinePicto(line: Line): JSX.Element { function renderTramLinePicto(line: Line): JSX.Element {
const lineStyle = { fill: `#${line.backColorHexa}` }; const lineStyle = { fill: `#${line.backColorHexa}` };
return ( return <div class="tramLinePicto">
<div class="tramLinePicto">
<svg viewBox="0 0 20 20"> <svg viewBox="0 0 20 20">
<rect x="0" y="0" width="20" height="3" rx="1" ry="1" style={lineStyle} /> <rect x="0" y="0" width="20" height="3" rx="1" ry="1" style={lineStyle} />
<rect x="0" y="17" width="20" height="3" rx="1" ry="1" style={lineStyle} /> <rect x="0" y="17" width="20" height="3" rx="1" ry="1" style={lineStyle} />
<text x="50%" <text
x="50%"
y="55%" y="55%"
dominant-baseline="middle" dominant-baseline="middle"
text-anchor="middle" text-anchor="middle"
@@ -69,16 +68,15 @@ function renderTramLinePicto(line: Line): JSX.Element {
{line.shortName} {line.shortName}
</text> </text>
</svg> </svg>
</div> </div>;
);
} }
function renderMetroLinePicto(line: Line): JSX.Element { function renderMetroLinePicto(line: Line): JSX.Element {
return ( return <div class="metroLinePicto">
<div class="metroLinePicto">
<svg viewBox="0 0 20 20"> <svg viewBox="0 0 20 20">
<circle cx="10" cy="10" r="10" style={{ fill: `#${line.backColorHexa}` }} /> <circle cx="10" cy="10" r="10" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%" <text
x="50%"
y="55%" y="55%"
dominant-baseline="middle" dominant-baseline="middle"
text-anchor="middle" text-anchor="middle"
@@ -86,16 +84,15 @@ function renderMetroLinePicto(line: Line): JSX.Element {
{line.shortName} {line.shortName}
</text> </text>
</svg> </svg>
</div> </div>;
);
} }
function renderTrainLinePicto(line: Line): JSX.Element { function renderTrainLinePicto(line: Line): JSX.Element {
return ( return <div class="trainLinePicto">
<div class="trainLinePicto">
<svg viewBox="0 0 20 20"> <svg viewBox="0 0 20 20">
<rect x="0" y="0" width="20" height="20" rx="4.5" ry="4.5" style={{ fill: `#${line.backColorHexa}` }} /> <rect x="0" y="0" width="20" height="20" rx="4.5" ry="4.5" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%" <text
x="50%"
y="55%" y="55%"
dominant-baseline="middle" dominant-baseline="middle"
text-anchor="middle" text-anchor="middle"
@@ -104,8 +101,7 @@ function renderTrainLinePicto(line: Line): JSX.Element {
{line.shortName} {line.shortName}
</text> </text>
</svg> </svg>
</div> </div>;
);
} }
export function renderLinePicto(line: Line): JSX.Element { export function renderLinePicto(line: Line): JSX.Element {
@@ -152,8 +148,7 @@ export const ScrollingText: VoidComponent<{ height: number, width: number, conte
} }
}); });
return ( return <svg ref={viewBoxRef} viewBox={`0 0 ${props.width} ${props.height}`}>
<svg ref={viewBoxRef} viewBox={`0 0 ${props.width} ${props.height}`}>
<text <text
ref={textRef} ref={textRef}
x="0%" y="55%" x="0%" y="55%"
@@ -161,6 +156,5 @@ export const ScrollingText: VoidComponent<{ height: number, width: number, conte
font-size={`${props.height}px`}> font-size={`${props.height}px`}>
{props.content} {props.content}
</text> </text>
</svg > </svg>;
);
} }

View File

@@ -4,6 +4,7 @@
"jsxImportSource": "solid-js", "jsxImportSource": "solid-js",
"noImplicitAny": true, "noImplicitAny": true,
"target": "ES6", "target": "ES6",
"module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"allowJs": true, "allowJs": true,
"outDir": "build", "outDir": "build",