🎉 First commit !!!

This commit is contained in:
2023-01-22 16:53:45 +01:00
commit dde835760a
68 changed files with 3250 additions and 0 deletions

23
frontend/.eslintrc.js Normal file
View File

@@ -0,0 +1,23 @@
module.exports = {
"env": {
"node": true,
"browser": true,
"es2021": true
},
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:solid/typescript",
],
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"solid"
],
"rules": {
}
}

3
frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
dist
package-lock.json

34
frontend/README.md Normal file
View File

@@ -0,0 +1,34 @@
## Usage
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
```bash
$ npm install # or pnpm install or yarn install
```
### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
## Available Scripts
In the project directory, you can run:
### `npm dev` or `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
### `npm run build`
Builds the app for production to the `dist` folder.<br>
It correctly bundles Solid in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
## Deployment
You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)

16
frontend/index.html Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
<title>Métro-Boulot-Dodo</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.tsx" type="module"></script>
</body>
</html>

33
frontend/package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "vite-template-solid",
"version": "0.0.0",
"engine": "19.3.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite --debug",
"build": "vite build",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"@vitejs/plugin-basic-ssl": "^1.0.1",
"eslint": "^8.32.0",
"eslint-plugin-solid": "^0.9.3",
"typescript": "^4.9.4",
"typescript-eslint-language-service": "^5.0.0",
"vite": "^4.0.3",
"vite-plugin-solid": "^2.5.0"
},
"dependencies": {
"@hope-ui/solid": "^0.6.7",
"@motionone/solid": "^10.15.5",
"@solid-primitives/date": "^2.0.5",
"@stitches/core": "^1.2.8",
"date-fns": "^2.29.3",
"leaflet": "^1.9.3",
"matrix-widget-api": "^1.1.1",
"solid-js": "^1.6.6",
"solid-transition-group": "^0.0.10"
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46469 283.46466"><defs><style>.cls-1{fill:#231f20;}.cls-2{fill:#00643c;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M141.73236,0C63.58334,0,0,63.57928,0,141.73236c0,78.149,63.58334,141.7323,141.73236,141.7323,78.15305,0,141.73233-63.58331,141.73233-141.7323C283.46469,63.57928,219.88541,0,141.73236,0Zm.00018,265.09479A123.36231,123.36231,0,1,1,265.09436,141.73248,123.5019,123.5019,0,0,1,141.73254,265.09479Z"/><circle class="cls-2" cx="141.73528" cy="141.73235" r="123.36528"/></g></g></svg>

After

Width:  |  Height:  |  Size: 618 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46469 283.46466"><defs><style>.cls-1{fill:#231f20;}.cls-2{fill:#ffbe00;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M141.73236,0C63.58334,0,0,63.57928,0,141.73236c0,78.149,63.58334,141.7323,141.73236,141.7323,78.15305,0,141.73233-63.58331,141.73233-141.7323C283.46469,63.57928,219.88541,0,141.73236,0Zm.00018,265.09479A123.36231,123.36231,0,1,1,265.09436,141.73248,123.5019,123.5019,0,0,1,141.73254,265.09479Z"/><circle class="cls-2" cx="141.73528" cy="141.73235" r="123.36528"/></g></g></svg>

After

Width:  |  Height:  |  Size: 618 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46469 283.46466"><defs><style>.cls-1{fill:#231f20;}.cls-2{fill:#ff5a00;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M141.73236,0C63.58334,0,0,63.57928,0,141.73236c0,78.149,63.58334,141.7323,141.73236,141.7323,78.15305,0,141.73233-63.58331,141.73233-141.7323C283.46469,63.57928,219.88541,0,141.73236,0Zm.00018,265.09479A123.36231,123.36231,0,1,1,265.09436,141.73248,123.5019,123.5019,0,0,1,141.73254,265.09479Z"/><circle class="cls-2" cx="141.73528" cy="141.73235" r="123.36528"/></g></g></svg>

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><path d="M244.14,161.22c0-14.53-8.15-23.03-18.42-28.7l-7.8-4.25c-4.6-2.48-8.5-6.38-8.5-11.34,0-5.67,4.61-9.56,11.34-9.56,4.61,0,8.86,1.77,12.05,3.19,4.96,2.48,8.15-.71,9.57-6.02,1.77-6.03-.71-8.15-4.96-10.27-4.25-2.13-10.27-3.55-16.29-3.55-16.66,0-30.48,10.98-30.48,28.7,0,13.82,7.08,21.62,18.43,27.99l8.15,4.61c4.96,2.84,8.15,6.74,8.15,12.05,0,6.73-6.38,9.92-12.76,9.92-4.96,0-10.98-2.13-14.18-3.55-5.31-2.48-8.15,.71-9.92,6.38-1.76,6.02,1.07,8.51,5.67,10.63,4.25,2.12,11.69,3.89,18.43,3.89,17.36,0,31.53-11.69,31.53-30.12m-62-3.55v-58.82c0-4.96-4.96-7.44-9.57-7.44-4.96,0-9.56,2.48-9.56,7.44v56.34c0,11.34-3.55,18.78-12.76,18.78s-13.11-7.09-13.11-18.78v-56.34c0-4.96-5.31-7.44-9.92-7.44-5.31,0-9.92,2.48-9.92,7.44v58.46c0,23.39,11.69,34.02,32.95,34.02,19.13,0,31.89-10.98,31.89-33.66m-74.06,4.26c0-16.31-11.33-22.33-17.36-23.39v-.35c7.09-3.55,15.59-10.28,15.59-22.33,0-16.29-14.18-24.09-27.99-24.09h-26.58c-4.96,0-7.79,3.89-7.79,8.15v82.91c0,4.96,4.96,7.45,9.57,7.45h25.15c15.24,0,29.41-8.15,29.41-28.35m-21.61-41.46c0,9.21-7.79,12.4-15.94,12.4h-7.44v-24.81h7.44c8.5,0,15.94,2.84,15.94,12.41m2.84,39.33c0,9.57-5.32,14.18-16.65,14.18h-8.51v-27.64h8.51c7.09,0,16.65,2.48,16.65,13.46M274.25,18.43H9.21C4.13,18.43,0,14.3,0,9.22S4.13,0,9.21,0H274.25c5.09,0,9.21,4.13,9.21,9.22s-4.12,9.21-9.21,9.21m0,265.04H9.21c-5.08,0-9.21-4.12-9.21-9.21s4.13-9.21,9.21-9.21H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.21-9.21,9.21"/><path d="M244.14,161.22c0-14.53-8.15-23.03-18.42-28.7l-7.8-4.25c-4.6-2.48-8.5-6.38-8.5-11.34,0-5.67,4.61-9.56,11.34-9.56,4.61,0,8.86,1.77,12.05,3.19,4.96,2.48,8.15-.71,9.57-6.02,1.77-6.03-.71-8.15-4.96-10.27-4.25-2.13-10.27-3.55-16.29-3.55-16.66,0-30.48,10.98-30.48,28.7,0,13.82,7.08,21.62,18.43,27.99l8.15,4.61c4.96,2.84,8.15,6.74,8.15,12.05,0,6.73-6.38,9.92-12.76,9.92-4.96,0-10.98-2.13-14.18-3.55-5.31-2.48-8.15,.71-9.92,6.38-1.76,6.02,1.07,8.51,5.67,10.63,4.25,2.12,11.69,3.89,18.43,3.89,17.36,0,31.53-11.69,31.53-30.12m-62-3.55v-58.82c0-4.96-4.96-7.44-9.57-7.44-4.96,0-9.56,2.48-9.56,7.44v56.34c0,11.34-3.55,18.78-12.76,18.78s-13.11-7.09-13.11-18.78v-56.34c0-4.96-5.31-7.44-9.92-7.44-5.31,0-9.92,2.48-9.92,7.44v58.46c0,23.39,11.69,34.02,32.95,34.02,19.13,0,31.89-10.98,31.89-33.66m-74.06,4.26c0-16.31-11.33-22.33-17.36-23.39v-.35c7.09-3.55,15.59-10.28,15.59-22.33,0-16.29-14.18-24.09-27.99-24.09h-26.58c-4.96,0-7.79,3.89-7.79,8.15v82.91c0,4.96,4.96,7.45,9.57,7.45h25.15c15.24,0,29.41-8.15,29.41-28.35m-21.61-41.46c0,9.21-7.79,12.4-15.94,12.4h-7.44v-24.81h7.44c8.5,0,15.94,2.84,15.94,12.41m2.84,39.33c0,9.57-5.32,14.18-16.65,14.18h-8.51v-27.64h8.51c7.09,0,16.65,2.48,16.65,13.46M274.25,18.43H9.21C4.13,18.43,0,14.3,0,9.22S4.13,0,9.21,0H274.25c5.09,0,9.21,4.13,9.21,9.22s-4.12,9.21-9.21,9.21m0,265.04H9.21c-5.08,0-9.21-4.12-9.21-9.21s4.13-9.21,9.21-9.21H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.21-9.21,9.21"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M165.206,155.193V97.366c0-2.976,3.686-5.883,7.655-5.883c3.683,0,7.653,2.907,7.653,5.883v60.307
c0,22.675-10.34,33.447-30.278,33.447c-22.063,0-31.569-10.415-31.569-33.801V97.366c0-2.976,3.688-5.883,7.938-5.883
c3.683,0,7.936,2.907,7.936,5.883v57.827c0,18.598,9.528,22.039,15.695,22.039C157.457,177.232,165.206,172.823,165.206,155.193
M72.638,144.988c11.66,0,18.621,5.768,18.621,15.431c0,10.709-6.265,16.139-18.621,16.139H60.913v-31.57H72.638z M89.899,138.539
v-0.354c6.654-3.594,14.587-10.39,14.587-22.355c0-16.532-13.57-24.063-28.79-24.062H53.605c-6.58-0.001-8.849,3.899-8.849,8.151
v82.91c0,4.961,3.969,7.442,10.063,7.442h21.329c27.936,0,29.912-21.844,29.912-28.538c0-19.969-15.493-23.068-16.161-23.196
M60.064,134.216v-28.415h9.248c11.447,0,18.952,5.046,18.952,14.208c0,8.896-7.837,14.207-18.952,14.207H60.064z M220.59,90.846
c-15.719,0.274-28.971,11.133-28.683,27.623c0.226,12.935,7.566,21.01,18.376,26.82l8.348,4.523
c5.794,3.191,9.859,6.681,9.977,13.386c0.155,8.884-7.359,13.902-15.429,14.043c-5.236,0.091-11.336-1.793-14.717-3.3
c-4.39-1.915-6.486,0.76-7.854,5.34c-1.37,4.863,0.986,6.812,4.788,8.452c4.238,2.008,11.675,3.555,18.314,3.44
c16.308-0.285,29.582-11.151,29.28-28.437c-0.238-13.629-7.92-21.829-17.816-27.082l-8.072-4.27
c-5.609-2.985-10.214-7.567-10.325-13.876c-0.139-8.03,5.632-13.83,13.763-13.972c4.878-0.085,9.396,1.701,12.811,3.328
c4.002,1.875,6.425-0.707,7.487-4.892c1.335-4.747-0.677-6.379-4.107-7.986C232.492,91.979,226.552,90.742,220.59,90.846
M283.465,7.37L283.465,7.37c0-4.07-3.3-7.37-7.37-7.37H7.37C3.3,0,0,3.3,0,7.37c0,4.071,3.3,7.371,7.37,7.371h268.725
C280.165,14.741,283.465,11.441,283.465,7.37 M283.465,276.095L283.465,276.095c0-4.07-3.3-7.37-7.37-7.37H7.37
c-4.07,0-7.37,3.3-7.37,7.37c0,4.07,3.3,7.37,7.37,7.37h268.725C280.165,283.465,283.465,280.165,283.465,276.095"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><path d="M274.25,18.43H9.21C4.12,18.43,0,14.31,0,9.21S4.12,0,9.21,0H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.22-9.21,9.22m9.21,255.82h0c0-5.09-4.12-9.21-9.21-9.21H9.21c-5.09,0-9.21,4.12-9.21,9.21s4.12,9.21,9.21,9.21H274.25c5.09,0,9.21-4.12,9.21-9.21M230.98,62.08l-84.43,14.89v36.42h38.9c11.2,0,21.21,6.69,25.5,17.03,5.7,13.69,8.59,28.23,8.59,43.2s-2.89,29.51-8.6,43.2c-4.29,10.34-14.29,17.03-25.49,17.03H98.02c-11.2,0-21.21-6.69-25.51-17.03-5.7-13.69-8.59-28.23-8.59-43.2s2.89-29.51,8.59-43.21c4.29-10.34,14.31-17.03,25.51-17.03h38.89v-34.72l-81.07,14.29c-1.75,.31-3.42-.86-3.72-2.61l-.56-3.17c-.31-1.74,.85-3.41,2.6-3.71l66.63-11.75-.29-1.67c-.76-4.32,2.12-8.44,6.44-9.19l26.24-4.63c4.32-.76,8.44,2.12,9.19,6.44l.3,1.67,66.63-11.75c1.74-.31,3.4,.85,3.71,2.59l.56,3.18c.31,1.75-.86,3.41-2.6,3.71m-116.88,120.76v-54.72c0-1.09-.89-1.98-1.99-1.98h-14.09c-6.03,0-11.41,3.59-13.72,9.16-5.06,12.15-7.62,25.04-7.62,38.32,0,3.16,.15,6.31,.45,9.42,.09,1.02,.96,1.79,1.98,1.79h33.01c1.1,0,1.99-.89,1.99-1.99m57.26,1.99h33.01c1.02,0,1.88-.77,1.98-1.79,.29-3.11,.45-6.26,.45-9.42,0-13.28-2.56-26.17-7.62-38.32-2.31-5.57-7.69-9.16-13.72-9.16h-14.09c-1.09,0-1.98,.89-1.98,1.98v54.72c0,1.1,.89,1.99,1.98,1.99m-14.74,34.29v-90.99c0-1.09-.89-1.98-1.98-1.98h-25.8c-1.09,0-1.98,.89-1.98,1.98v90.99c0,1.09,.89,1.98,1.98,1.98h25.8c1.09,0,1.98-.89,1.98-1.98"/><path d="M274.25,18.43H9.21C4.12,18.43,0,14.31,0,9.21S4.12,0,9.21,0H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.22-9.21,9.22m9.21,255.82h0c0-5.09-4.12-9.21-9.21-9.21H9.21c-5.09,0-9.21,4.12-9.21,9.21s4.12,9.21,9.21,9.21H274.25c5.09,0,9.21-4.12,9.21-9.21M230.98,62.08l-84.43,14.89v36.42h38.9c11.2,0,21.21,6.69,25.5,17.03,5.7,13.69,8.59,28.23,8.59,43.2s-2.89,29.51-8.6,43.2c-4.29,10.34-14.29,17.03-25.49,17.03H98.02c-11.2,0-21.21-6.69-25.51-17.03-5.7-13.69-8.59-28.23-8.59-43.2s2.89-29.51,8.59-43.21c4.29-10.34,14.31-17.03,25.51-17.03h38.89v-34.72l-81.07,14.29c-1.75,.31-3.42-.86-3.72-2.61l-.56-3.17c-.31-1.74,.85-3.41,2.6-3.71l66.63-11.75-.29-1.67c-.76-4.32,2.12-8.44,6.44-9.19l26.24-4.63c4.32-.76,8.44,2.12,9.19,6.44l.3,1.67,66.63-11.75c1.74-.31,3.4,.85,3.71,2.59l.56,3.18c.31,1.75-.86,3.41-2.6,3.71m-116.88,120.76v-54.72c0-1.09-.89-1.98-1.99-1.98h-14.09c-6.03,0-11.41,3.59-13.72,9.16-5.06,12.15-7.62,25.04-7.62,38.32,0,3.16,.15,6.31,.45,9.42,.09,1.02,.96,1.79,1.98,1.79h33.01c1.1,0,1.99-.89,1.99-1.99m57.26,1.99h33.01c1.02,0,1.88-.77,1.98-1.79,.29-3.11,.45-6.26,.45-9.42,0-13.28-2.56-26.17-7.62-38.32-2.31-5.57-7.69-9.16-13.72-9.16h-14.09c-1.09,0-1.98,.89-1.98,1.98v54.72c0,1.1,.89,1.99,1.98,1.99m-14.74,34.29v-90.99c0-1.09-.89-1.98-1.98-1.98h-25.8c-1.09,0-1.98,.89-1.98,1.98v90.99c0,1.09,.89,1.98,1.98,1.98h25.8c1.09,0,1.98-.89,1.98-1.98"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M233.576,58.371l-0.56-3.182c-0.308-1.742-1.969-2.906-3.711-2.598L162.67,64.34l-0.296-1.675
c-0.762-4.317-4.878-7.199-9.195-6.438l-26.24,4.627c-4.317,0.761-7.2,4.878-6.438,9.195l0.295,1.674l-66.635,11.75
c-1.742,0.307-2.905,1.969-2.598,3.711l0.559,3.173c0.308,1.747,1.974,2.914,3.722,2.606l81.07-14.295v34.719H98.018
c-11.198,0-21.209,6.685-25.5,17.025c-5.704,13.705-8.596,28.243-8.596,43.21c0,14.969,2.892,29.507,8.594,43.203
c4.293,10.348,14.303,17.034,25.502,17.034h87.429c11.2,0,21.21-6.687,25.498-17.027c5.706-13.701,8.598-28.239,8.598-43.21
c0-14.969-2.892-29.507-8.594-43.202c-4.293-10.347-14.302-17.033-25.502-17.033h-38.895V76.969l84.427-14.887
C232.721,61.775,233.884,60.113,233.576,58.371 M112.111,184.829H79.098c-1.019,0-1.883-0.77-1.978-1.785
c-0.292-3.116-0.443-6.258-0.443-9.422c0-13.276,2.563-26.165,7.621-38.314c2.31-5.568,7.696-9.166,13.72-9.166h14.093
c1.096,0,1.984,0.889,1.984,1.984v54.719C114.095,183.941,113.207,184.829,112.111,184.829 M169.37,182.845v-54.719
c0-1.095,0.889-1.984,1.985-1.984h14.092c6.025,0,11.411,3.598,13.721,9.166c5.058,12.149,7.62,25.038,7.62,38.314
c0,3.164-0.15,6.306-0.442,9.422c-0.095,1.015-0.959,1.785-1.979,1.785h-33.012C170.259,184.829,169.37,183.941,169.37,182.845
M154.63,221.103h-25.795c-1.096,0-1.984-0.889-1.984-1.985v-90.992c0-1.095,0.888-1.984,1.984-1.984h25.795
c1.097,0,1.984,0.889,1.984,1.984v90.992C156.614,220.214,155.727,221.103,154.63,221.103 M283.465,7.37L283.465,7.37
c0-4.07-3.3-7.37-7.37-7.37H7.37C3.3,0,0,3.3,0,7.37c0,4.071,3.3,7.371,7.37,7.371h268.725
C280.165,14.741,283.465,11.441,283.465,7.37 M283.465,276.095L283.465,276.095c0-4.07-3.3-7.37-7.37-7.37H7.37
c-4.07,0-7.37,3.3-7.37,7.37c0,4.07,3.3,7.37,7.37,7.37h268.725C280.165,283.465,283.465,280.165,283.465,276.095"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1 @@
symbole_metro_RVB.svg

View File

@@ -0,0 +1 @@
symbole_metro_support_fonce_RVB.svg

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><path d="M141.73,0C63.45,0,0,63.46,0,141.73s63.45,141.73,141.73,141.73,141.73-63.46,141.73-141.73S220.01,0,141.73,0m0,265.04c-68.1,0-123.31-55.21-123.31-123.31S73.63,18.43,141.73,18.43s123.3,55.2,123.3,123.3-55.2,123.31-123.3,123.31m70.51-59.89c0,6.74-5.32,10.63-11.69,10.63-5.68,0-12.05-3.89-12.05-10.63V113.03h-.35l-35.08,71.57c-2.48,4.96-5.66,7.79-11.34,7.79s-8.86-2.84-11.34-7.79l-35.08-71.57h-.35v92.13c0,6.74-6.38,10.63-12.05,10.63-6.38,0-11.69-3.89-11.69-10.63V81.5c0-7.09,3.9-14.53,15.59-14.53,8.86,0,12.4,3.9,16.3,11.69l38.62,79.72h.35l38.27-79.72c3.89-7.79,7.44-11.69,16.29-11.69,11.69,0,15.59,7.44,15.59,14.53v123.66"/><path d="M141.73,0C63.45,0,0,63.46,0,141.73s63.45,141.73,141.73,141.73,141.73-63.46,141.73-141.73S220.01,0,141.73,0m0,265.04c-68.1,0-123.31-55.21-123.31-123.31S73.63,18.43,141.73,18.43s123.3,55.2,123.3,123.3-55.2,123.31-123.3,123.31m70.51-59.89c0,6.74-5.32,10.63-11.69,10.63-5.68,0-12.05-3.89-12.05-10.63V113.03h-.35l-35.08,71.57c-2.48,4.96-5.66,7.79-11.34,7.79s-8.86-2.84-11.34-7.79l-35.08-71.57h-.35v92.13c0,6.74-6.38,10.63-12.05,10.63-6.38,0-11.69-3.89-11.69-10.63V81.5c0-7.09,3.9-14.53,15.59-14.53,8.86,0,12.4,3.9,16.3,11.69l38.62,79.72h.35l38.27-79.72c3.89-7.79,7.44-11.69,16.29-11.69,11.69,0,15.59,7.44,15.59,14.53v123.66"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M141.733,0.001C63.456,0.001,0,63.456,0,141.733s63.456,141.733,141.733,141.733
c78.276,0,141.732-63.456,141.732-141.733S220.009,0.001,141.733,0.001 M141.733,268.725c-70.136,0-126.992-56.856-126.992-126.992
S71.597,14.741,141.733,14.741c70.135,0,126.992,56.856,126.992,126.992S211.868,268.725,141.733,268.725 M141.721,192.325
c-4.736,0-7.4-2.32-9.472-6.38l-38.104-75.984h-0.354l0.001,96.712c0,5.721-5.42,9.035-10.24,9.035
c-5.421,0-9.939-3.315-9.939-9.036V78.7c0-5.669,3.261-11.622,13.045-11.622c7.413,0,10.57,3.118,13.639,9.355l41.259,87.057h0.354
l41.235-87.057c3.069-6.237,6.225-9.355,13.639-9.355c9.784,0,13.045,5.953,13.045,11.622v127.972c0,5.721-4.517,9.036-9.939,9.036
c-4.82,0-10.24-3.314-10.24-9.035l0.001-96.712h-0.355l-38.103,75.984C149.121,190.005,146.457,192.325,141.721,192.325"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><g><path d="M171.5,181.43c0-4.26-2.84-8.86-7.79-8.86h-26.94v-24.45h22.32c4.96,0,7.8-4.26,7.8-8.15,0-4.25-2.84-8.15-7.8-8.15h-22.32v-22.32h24.81c4.96,0,7.79-4.96,7.79-8.85,0-4.26-2.83-8.86-7.79-8.86h-36.15c-4.96,0-7.79,3.89-7.79,8.15v82.92c0,4.96,4.96,7.44,9.56,7.44h36.5c4.96,0,7.79-4.96,7.79-8.85"/><path d="M226.42,147.06c9.22-4.62,17.02-12.76,17.02-27.29,0-19.13-14.19-27.99-27.99-27.99h-26.58c-4.96,0-7.79,3.89-7.79,8.15v83.27c0,4.96,4.96,7.43,9.55,7.43,5.32,0,9.57-2.48,9.57-7.43v-32.24h8.15l15.94,35.78c1.42,2.84,3.91,3.89,6.74,3.89,5.66,0,13.82-5.31,10.63-11.68l-15.24-31.89Zm-20.55-10.28h-5.67v-28.7h6.72c8.86,0,16.65,3.9,16.65,13.82,0,12.05-10.97,14.88-17.71,14.88Z"/><path d="M89.29,147.06c9.22-4.62,17.01-12.76,17.01-27.29,0-19.13-14.17-27.99-27.99-27.99h-26.57c-4.96,0-7.8,3.89-7.8,8.15v83.27c0,4.96,4.96,7.43,9.56,7.43,5.31,0,9.56-2.48,9.56-7.43v-32.24h8.15l15.95,35.78c1.42,2.84,3.91,3.89,6.74,3.89,5.67,0,13.81-5.31,10.63-11.68l-15.24-31.89Zm-20.55-10.28h-5.68v-28.7h6.74c8.85,0,16.65,3.9,16.65,13.82,0,12.05-10.98,14.88-17.72,14.88Z"/><path d="M219.69,0H63.78C28.55,0,0,28.56,0,63.78V219.68c0,35.22,28.55,63.78,63.78,63.78H219.69c35.22,0,63.78-28.56,63.78-63.78V63.78c0-35.22-28.55-63.78-63.78-63.78Zm45.35,219.68c0,25.05-20.31,45.35-45.35,45.35H63.78c-25.05,0-45.35-20.31-45.35-45.35V63.78c0-25.05,20.31-45.36,45.35-45.36H219.69c25.05,0,45.35,20.31,45.35,45.36V219.68Z"/></g><g><path d="M171.5,181.43c0-4.26-2.84-8.86-7.79-8.86h-26.94v-24.45h22.32c4.96,0,7.8-4.26,7.8-8.15,0-4.25-2.84-8.15-7.8-8.15h-22.32v-22.32h24.81c4.96,0,7.79-4.96,7.79-8.85,0-4.26-2.83-8.86-7.79-8.86h-36.15c-4.96,0-7.79,3.89-7.79,8.15v82.92c0,4.96,4.96,7.44,9.56,7.44h36.5c4.96,0,7.79-4.96,7.79-8.85"/><path d="M226.42,147.06c9.22-4.62,17.02-12.76,17.02-27.29,0-19.13-14.19-27.99-27.99-27.99h-26.58c-4.96,0-7.79,3.89-7.79,8.15v83.27c0,4.96,4.96,7.43,9.55,7.43,5.32,0,9.57-2.48,9.57-7.43v-32.24h8.15l15.94,35.78c1.42,2.84,3.91,3.89,6.74,3.89,5.66,0,13.82-5.31,10.63-11.68l-15.24-31.89Zm-20.55-10.28h-5.67v-28.7h6.72c8.86,0,16.65,3.9,16.65,13.82,0,12.05-10.97,14.88-17.71,14.88Z"/><path d="M89.29,147.06c9.22-4.62,17.01-12.76,17.01-27.29,0-19.13-14.17-27.99-27.99-27.99h-26.57c-4.96,0-7.8,3.89-7.8,8.15v83.27c0,4.96,4.96,7.43,9.56,7.43,5.31,0,9.56-2.48,9.56-7.43v-32.24h8.15l15.95,35.78c1.42,2.84,3.91,3.89,6.74,3.89,5.67,0,13.81-5.31,10.63-11.68l-15.24-31.89Zm-20.55-10.28h-5.68v-28.7h6.74c8.85,0,16.65,3.9,16.65,13.82,0,12.05-10.98,14.88-17.72,14.88Z"/><path d="M219.69,0H63.78C28.55,0,0,28.56,0,63.78V219.68c0,35.22,28.55,63.78,63.78,63.78H219.69c35.22,0,63.78-28.56,63.78-63.78V63.78c0-35.22-28.55-63.78-63.78-63.78Zm45.35,219.68c0,25.05-20.31,45.35-45.35,45.35H63.78c-25.05,0-45.35-20.31-45.35-45.35V63.78c0-25.05,20.31-45.36,45.35-45.36H219.69c25.05,0,45.35,20.31,45.35,45.36V219.68Z"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M78.31,91.787c12.98,0,26.078,8.359,26.078,27.038c0,12.107-5.367,21.027-15.949,26.511
c-0.58,0.265-1.157,0.503-1.732,0.731l17.031,35.648c0.75,1.501,0.684,2.928-0.203,4.363c-1.556,2.516-5.465,4.563-8.716,4.563
c-2.456,0-4.052-0.903-5.021-2.841l-17.049-38.127H60.703v35.212c0,2.871-4.102,5.675-7.654,5.675
c-4.099,0-7.656-2.804-7.656-5.675V99.923c0-4.252,2.269-8.152,8.849-8.15L78.31,91.787z M45.393,184.885V99.923
c0-4.252,2.269-8.152,8.849-8.15 M68.742,136.917c9.056,0,19.63-4.399,19.63-16.795c0-9.705-7.114-15.733-18.567-15.733h-9.102
v32.528H68.742z"/>
<path fill="#FFFFFF" d="M215.438,91.787c12.98,0,26.078,8.359,26.078,27.038c0,12.107-5.367,21.027-15.949,26.511
c-0.58,0.265-1.157,0.503-1.732,0.731l17.031,35.648c0.75,1.501,0.684,2.928-0.203,4.363c-1.556,2.516-5.465,4.563-8.716,4.563
c-2.456,0-4.052-0.903-5.021-2.841l-17.049-38.127h-12.046v35.212c0,2.871-4.102,5.675-7.654,5.675
c-4.099,0-7.656-2.804-7.656-5.675V99.923c0-4.252,2.269-8.152,8.849-8.15L215.438,91.787z M205.87,136.917
c9.056,0,19.63-4.399,19.63-16.795c0-9.705-7.114-15.733-18.567-15.733h-9.102v32.528H205.87z"/>
<path fill="#FFFFFF" d="M163.987,190.277c3.786,0,5.881-4.188,5.881-7.084c0-2.942-1.825-7.087-5.881-7.088h-29.33v-29.623h24.724
c4.056,0,5.881-3.813,5.881-6.52c0-3.14-1.84-6.519-5.881-6.519h-24.724v-27.496h27.203c3.838,0,5.883-4.115,5.883-7.087
c0-2.942-1.825-7.086-5.883-7.086h-33.632c-6.58-0.002-8.848,3.898-8.848,8.15v82.913c0,5.455,4.577,7.435,7.653,7.435
L163.987,190.277z"/>
<path fill="#FFFFFF" d="M219.685,283.465H63.78C28.556,283.465,0,254.91,0,219.685V63.78C0,28.556,28.556,0,63.78,0h155.905
c35.225,0,63.78,28.556,63.78,63.78v155.905C283.465,254.91,254.91,283.465,219.685,283.465 M268.725,219.685V63.78
c0-27.084-21.956-49.039-49.04-49.039H63.78c-27.084,0-49.039,21.955-49.039,49.039v155.905c0,27.084,21.955,49.04,49.039,49.04
h155.905C246.769,268.725,268.725,246.769,268.725,219.685"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><path d="M274.25,18.42H9.5A9.39,9.39,0,0,1,.1,10.58,9.22,9.22,0,0,1,9.21,0H274a9.41,9.41,0,0,1,9.4,7.85,9.22,9.22,0,0,1-9.12,10.57m9.21,255.83h0a9.21,9.21,0,0,0-9.21-9.21H9.5a9.39,9.39,0,0,0-9.4,7.84,9.22,9.22,0,0,0,9.11,10.58h265a9.21,9.21,0,0,0,9.21-9.21" transform="translate(0)"/><path d="M124.42,141.74l2-7.49,4.83-18.14.94,1.34c.18.26.38.51.58.75a10.16,10.16,0,0,0,2.93,2.37,11.7,11.7,0,0,0,1.74.75l10.08,3.78a31.12,31.12,0,0,0,15.36-7.29l-21-7.89S134.51,97.78,131,94.49a7.82,7.82,0,0,0-4.33-2.16,10.55,10.55,0,0,0-2.39-.26h0a15.42,15.42,0,0,0-2.25.31l-.24.05a1.14,1.14,0,0,0-.25.06h0a18.27,18.27,0,0,0-12.67,12.81l-8,30.25a10.19,10.19,0,0,0,0,4.08,10.77,10.77,0,0,0,2.82,5.2l2.53,2.87,4.14,4.71,20.19,21.16-5.59,39.71a6.87,6.87,0,0,0,10.06,6.32,6.7,6.7,0,0,0,2.23-4.36l7-39.54a10.72,10.72,0,0,0,.17-2.71,10.17,10.17,0,0,0-1.76-5.07Z" transform="translate(0)"/><path d="M128.78,87c3.19.68,6.75.88,9.46-.83s3.93-5.12,4.61-8.31.88-6.75-.83-9.47-5.12-3.93-8.31-4.6-6.75-.88-9.47.82-3.92,5.12-4.6,8.32-.88,6.75.82,9.47S125.58,86.32,128.78,87Z" transform="translate(0)"/><path d="M241.83,197.62a37.21,37.21,0,0,0-31.63-35.34,36.43,36.43,0,0,0-18,1.87l-19.67-34.07a46.36,46.36,0,0,0,12.6-16.8,2.87,2.87,0,0,0-1.66-3.83l-4-1.46a2.82,2.82,0,0,0-3.54,1.53,36.76,36.76,0,0,1-34.05,21.71,2.86,2.86,0,0,0-2.95,2.57l-.37,4.25a2.86,2.86,0,0,0,2.76,3.12,46.69,46.69,0,0,0,20.41-4.23l5.41,9.37-16.63,26.55L144.94,204A7.81,7.81,0,0,0,148,201l26.35-42.09,6.75,11.68a37,37,0,1,0,60.73,27.08Zm-40,28.1a27,27,0,0,1-15.58-46.33l13.36,23.25a4.27,4.27,0,0,0,5.83,1.56l3.7-2.13a4.27,4.27,0,0,0,1.56-5.83L197.32,173a27,27,0,1,1,4.47,52.68Z" transform="translate(0)"/><path d="M116,192a36.89,36.89,0,0,0-9-18l7.09-9.36-9-9.4-8.22,10.91a37,37,0,0,0-25.29-3.38,37,37,0,1,0,44.57,42h4.18l1.8-12.8Zm-15.23-9.79A26.7,26.7,0,0,1,105.7,192H93.36Zm-21.1,43.71a27,27,0,0,1-7.42-53,26.54,26.54,0,0,1,18.47,1.36l-16.2,21.4a5.68,5.68,0,0,0,4.53,9.12h27A27,27,0,0,1,79.67,225.89Z" transform="translate(0)"/></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1 @@
symbole_transilien_RVB.svg

View File

@@ -0,0 +1 @@
symbole_transilien_support_fonce_RVB.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 28.346 28.346" enable-background="new 0 0 28.346 28.346" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M10.615,12.933c0.029-0.019,0.057-0.04,0.082-0.063c0.247-0.201,0.479-0.508,0.647-0.986
c0.236-0.668,0.402-1.265,0.447-2.001c0.064-0.905-0.309-2.313-0.555-2.969l-0.087-0.231c-0.053-0.146-0.256-0.461-0.616-0.836
c-0.309-0.323-0.607-0.346-1.06-0.346H7.634c-0.452,0-0.749,0.023-1.059,0.346C6.214,6.221,6.011,6.536,5.959,6.683L5.873,6.915
C5.625,7.57,5.253,8.978,5.315,9.886c0.045,0.733,0.212,1.33,0.448,2c0.168,0.478,0.4,0.784,0.648,0.985
c0.026,0.022,0.053,0.044,0.082,0.062l-1.339,1.488c-0.053,0.061-0.082,0.139-0.082,0.22c0,0.08,0.029,0.158,0.082,0.219
c0.025,0.028,0.055,0.051,0.088,0.066c0.035,0.016,0.071,0.024,0.108,0.024c0.038,0,0.074-0.008,0.109-0.024
c0.033-0.015,0.064-0.038,0.087-0.066l0.463-0.514h5.09l0.461,0.514c0.025,0.028,0.055,0.051,0.089,0.066
c0.034,0.016,0.07,0.024,0.108,0.024c0.037,0,0.074-0.008,0.108-0.024c0.034-0.015,0.064-0.038,0.088-0.066
c0.053-0.061,0.082-0.139,0.082-0.219c0-0.081-0.029-0.159-0.082-0.22L10.615,12.933z M10.166,12.39
c-0.091,0-0.18-0.027-0.255-0.077c-0.075-0.051-0.134-0.123-0.169-0.206c-0.035-0.085-0.044-0.177-0.026-0.266
c0.017-0.089,0.062-0.171,0.126-0.235c0.064-0.065,0.146-0.108,0.235-0.126c0.089-0.018,0.182-0.009,0.265,0.026
c0.084,0.034,0.156,0.094,0.206,0.169c0.051,0.076,0.078,0.165,0.078,0.255c0,0.122-0.049,0.239-0.135,0.325
C10.405,12.342,10.288,12.39,10.166,12.39 M6.004,9.443c-0.281,0,0.162-2.466,0.362-2.466h4.325c0.22,0,0.731,2.466,0.391,2.466
H6.004z M6.473,11.93c0-0.09,0.027-0.179,0.077-0.256c0.051-0.075,0.123-0.134,0.207-0.168c0.083-0.035,0.176-0.045,0.266-0.027
c0.089,0.018,0.17,0.061,0.235,0.126c0.064,0.064,0.108,0.146,0.126,0.235c0.018,0.09,0.009,0.182-0.026,0.267
c-0.035,0.083-0.094,0.155-0.17,0.206c-0.075,0.05-0.164,0.077-0.255,0.077c-0.061,0-0.121-0.012-0.176-0.034
c-0.056-0.024-0.108-0.058-0.149-0.1c-0.044-0.043-0.077-0.094-0.1-0.149C6.484,12.05,6.473,11.99,6.473,11.93 M6.566,13.726
l0.492-0.547c0.206,0.042,0.415,0.06,0.624,0.055h1.744c0.209,0.005,0.418-0.013,0.622-0.055l0.495,0.547H6.566z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M21.942,7.531c0.184,0.184,0.184,0.483,0,0.668L7.769,22.371
c-0.184,0.186-0.484,0.186-0.668,0c-0.185-0.184-0.185-0.483,0-0.668L21.274,7.531C21.458,7.346,21.758,7.346,21.942,7.531"/>
<path fill="#FFFFFF" d="M21.968,28.346H6.377C2.855,28.346,0,25.491,0,21.968V6.378c0-3.523,2.856-6.379,6.378-6.379h15.591
c3.523,0,6.378,2.856,6.378,6.379v15.59C28.346,25.491,25.491,28.346,21.968,28.346 M26.872,21.968V6.378
c0-2.709-2.196-4.904-4.904-4.904H6.377c-2.708,0-4.903,2.195-4.903,4.904v15.59c0,2.708,2.195,4.904,4.903,4.904h15.591
C24.676,26.872,26.872,24.676,26.872,21.968"/>
<path fill="#FFFFFF" d="M16.165,18.045c0.631,0,1.267,0.407,1.267,1.315c0,0.588-0.26,1.022-0.774,1.288
c-0.029,0.013-0.057,0.025-0.085,0.036l0.828,1.732c0.036,0.073,0.033,0.143-0.01,0.213c-0.075,0.122-0.265,0.221-0.423,0.221
c-0.12,0-0.197-0.043-0.245-0.138l-0.828-1.853h-0.586v1.712c0,0.139-0.199,0.275-0.372,0.275c-0.199,0-0.372-0.136-0.372-0.275
v-4.13c0-0.207,0.111-0.396,0.43-0.396H16.165z M14.565,22.571v-4.13c0-0.207,0.111-0.396,0.43-0.396 M15.7,20.239
c0.44,0,0.954-0.214,0.954-0.816c0-0.472-0.346-0.765-0.902-0.765h-0.443v1.581H15.7z"/>
<path fill="#FFFFFF" d="M22.83,18.045c0.631,0,1.267,0.407,1.267,1.315c0,0.588-0.26,1.022-0.775,1.288
c-0.028,0.013-0.056,0.025-0.084,0.036l0.828,1.732c0.036,0.073,0.033,0.143-0.01,0.213c-0.076,0.122-0.266,0.221-0.424,0.221
c-0.119,0-0.197-0.043-0.244-0.138l-0.829-1.853h-0.585v1.712c0,0.139-0.199,0.275-0.372,0.275c-0.199,0-0.372-0.136-0.372-0.275
v-4.13c0-0.207,0.11-0.396,0.43-0.396H22.83z M22.365,20.239c0.44,0,0.954-0.214,0.954-0.816c0-0.472-0.346-0.765-0.903-0.765
h-0.442v1.581H22.365z"/>
<path fill="#FFFFFF" d="M20.329,22.832c0.184,0,0.286-0.203,0.286-0.344c0-0.143-0.089-0.345-0.286-0.345h-1.425v-1.44h1.201
c0.198,0,0.286-0.185,0.286-0.317c0-0.152-0.089-0.316-0.286-0.316h-1.201v-1.337h1.322c0.186,0,0.286-0.2,0.286-0.344
c0-0.143-0.089-0.345-0.286-0.345h-1.635c-0.32,0-0.43,0.19-0.43,0.396v4.03c0,0.266,0.222,0.362,0.372,0.362H20.329z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><path d="M274.25,18.42H9.21C4.12,18.42,0,14.3,0,9.21S4.12,0,9.21,0H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.21-9.21,9.21m9.21,255.83h0c0-5.09-4.12-9.22-9.21-9.22H9.21c-5.09,0-9.21,4.13-9.21,9.22s4.12,9.21,9.21,9.21H274.25c5.09,0,9.21-4.12,9.21-9.21m-32.32-38.41c2.19,0,3.97-1.78,3.97-3.97v-3.97c0-2.19-1.78-3.96-3.97-3.96H28.35v11.91H251.14M28.35,170.78h41.25c1.09,0,1.98-.89,1.98-1.98v-54.85c0-1.09-.89-1.98-1.98-1.98H28.35v-12.76H92.72l25.23-20.74-31.74-26.08c-1.37-1.12-1.57-3.15-.44-4.52l2.04-2.49c1.13-1.37,3.15-1.56,4.52-.44l36.14,29.69c2.41,1.98,2.42,5.68,0,7.66l-20.58,16.91h98.03c7.78,0,15.18,3.29,20.43,9.03,15.45,16.89,25.27,37.77,28.41,60.39,1,7.19-.09,14.31-3.16,20.56-7.09,14.44-21.47,23.41-37.55,23.41H28.35v-41.81Zm188.48-54.06c-2.8-3.05-6.77-4.75-10.91-4.75h-34.57c-1.09,0-1.98,.89-1.98,1.98v54.85c0,1.09,.89,1.98,1.98,1.98h59.11c6.94,0,11.07-5.46,9.31-12.17-4.1-15.56-11.91-29.87-22.94-41.89m-62.2,83.12c1.09,0,1.98-.89,1.98-1.98V113.95c0-1.09-.89-1.98-1.98-1.98h-25.79c-1.1,0-1.99,.89-1.99,1.98v83.91c0,1.09,.89,1.98,1.99,1.98h25.79M86.32,111.97c-1.09,0-1.98,.89-1.98,1.98v83.91c0,1.09,.89,1.98,1.98,1.98h25.79c1.1,0,1.99-.89,1.99-1.98V113.95c0-1.09-.89-1.98-1.99-1.98h-25.79"/><path d="M274.25,18.42H9.21C4.12,18.42,0,14.3,0,9.21S4.12,0,9.21,0H274.25c5.09,0,9.21,4.12,9.21,9.21s-4.12,9.21-9.21,9.21m9.21,255.83h0c0-5.09-4.12-9.22-9.21-9.22H9.21c-5.09,0-9.21,4.13-9.21,9.22s4.12,9.21,9.21,9.21H274.25c5.09,0,9.21-4.12,9.21-9.21m-32.32-38.41c2.19,0,3.97-1.78,3.97-3.97v-3.97c0-2.19-1.78-3.96-3.97-3.96H28.35v11.91H251.14M28.35,170.78h41.25c1.09,0,1.98-.89,1.98-1.98v-54.85c0-1.09-.89-1.98-1.98-1.98H28.35v-12.76H92.72l25.23-20.74-31.74-26.08c-1.37-1.12-1.57-3.15-.44-4.52l2.04-2.49c1.13-1.37,3.15-1.56,4.52-.44l36.14,29.69c2.41,1.98,2.42,5.68,0,7.66l-20.58,16.91h98.03c7.78,0,15.18,3.29,20.43,9.03,15.45,16.89,25.27,37.77,28.41,60.39,1,7.19-.09,14.31-3.16,20.56-7.09,14.44-21.47,23.41-37.55,23.41H28.35v-41.81Zm188.48-54.06c-2.8-3.05-6.77-4.75-10.91-4.75h-34.57c-1.09,0-1.98,.89-1.98,1.98v54.85c0,1.09,.89,1.98,1.98,1.98h59.11c6.94,0,11.07-5.46,9.31-12.17-4.1-15.56-11.91-29.87-22.94-41.89m-62.2,83.12c1.09,0,1.98-.89,1.98-1.98V113.95c0-1.09-.89-1.98-1.98-1.98h-25.79c-1.1,0-1.99,.89-1.99,1.98v83.91c0,1.09,.89,1.98,1.99,1.98h25.79M86.32,111.97c-1.09,0-1.98,.89-1.98,1.98v83.91c0,1.09,.89,1.98,1.98,1.98h25.79c1.1,0,1.99-.89,1.99-1.98V113.95c0-1.09-.89-1.98-1.99-1.98h-25.79"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M276.095,14.741H7.37c-4.07,0-7.37-3.3-7.37-7.37c0-4.07,3.3-7.37,7.37-7.37h268.725
c4.07,0,7.37,3.3,7.37,7.37C283.465,11.441,280.165,14.741,276.095,14.741"/>
<path fill="#FFFFFF" d="M276.095,283.465H7.37c-4.07,0-7.37-3.3-7.37-7.37c0-4.07,3.3-7.37,7.37-7.37h268.725
c4.07,0,7.37,3.3,7.37,7.37C283.465,280.165,280.165,283.465,276.095,283.465"/>
<path fill="#FFFFFF" d="M251.149,235.841H28.346v-11.904h222.803c2.191,0,3.969,1.776,3.969,3.967v3.969
C255.118,234.066,253.34,235.841,251.149,235.841"/>
<path fill="#FFFFFF" d="M28.347,212.6h185.7c16.075,0,30.461-8.971,37.546-23.412c3.07-6.257,4.164-13.365,3.167-20.561
c-3.137-22.618-12.96-43.499-28.406-60.389c-5.247-5.738-12.654-9.024-20.43-9.024h-98.025l20.574-16.909
c2.415-1.984,2.414-5.681-0.001-7.665L92.332,44.949c-1.371-1.127-3.395-0.929-4.522,0.442l-2.04,2.483
c-1.126,1.371-0.928,3.395,0.443,4.522l31.743,26.077L92.719,99.214H28.347v12.756h41.243c1.096,0,1.985,0.889,1.985,1.984v54.85
c0,1.097-0.889,1.985-1.985,1.985H28.347V212.6z M216.829,116.724c11.03,12.022,18.841,26.331,22.941,41.892
c1.769,6.709-2.362,12.173-9.302,12.173h-59.113c-1.096,0-1.984-0.888-1.984-1.985v-54.85c0-1.095,0.888-1.984,1.984-1.984h34.569
C210.061,111.97,214.031,113.675,216.829,116.724 M154.63,199.844h-25.794c-1.096,0-1.985-0.889-1.985-1.984v-83.906
c0-1.095,0.889-1.984,1.985-1.984h25.794c1.096,0,1.985,0.889,1.985,1.984v83.906C156.615,198.955,155.725,199.844,154.63,199.844
M86.314,111.97h25.796c1.096,0,1.984,0.889,1.984,1.984v83.906c0,1.095-0.888,1.984-1.984,1.984H86.314
c-1.096,0-1.984-0.889-1.984-1.984v-83.906C84.33,112.859,85.218,111.97,86.314,111.97"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.46 283.46"><g id="Layer_1-2"><g><path d="M219.68,283.46H63.78c-35.22,0-63.78-28.55-63.78-63.78V63.78C0,28.55,28.56,0,63.78,0H219.68c35.22,0,63.78,28.55,63.78,63.78V219.69c0,35.22-28.56,63.78-63.78,63.78m45.36-63.78V63.78c0-25.05-20.31-45.35-45.36-45.35H63.78c-25.05,0-45.35,20.31-45.35,45.35V219.69c0,25.05,20.31,45.35,45.35,45.35H219.68c25.05,0,45.36-20.31,45.36-45.35m-81.17-15.09c.62-.42,1.22-.86,1.66-1.29,5.09-4.12,9.86-10.45,13.31-20.24,4.83-13.74,8.24-26.02,9.18-41.12,1.31-18.6-6.35-47.54-11.43-61.04l-1.77-4.75c-1.09-3.04-5.26-9.47-12.65-17.18-6.35-6.62-12.47-7.11-21.77-7.11h-37.76c-9.3,0-15.4,.49-21.78,7.11-7.39,7.69-11.56,14.15-12.65,17.18l-1.78,4.78c-5.08,13.48-12.73,42.42-11.44,61.04,.94,15.06,4.36,27.32,9.21,41.1,3.45,9.82,8.19,16.12,13.29,20.24,.48,.42,1.06,.85,1.69,1.27l-27.51,30.58c-2.24,2.5-2.24,6.53,0,9.01,2.24,2.47,5.85,2.47,8.07,0l9.5-10.54h104.53l9.48,10.54c2.22,2.47,5.85,2.47,8.07,0,2.24-2.48,2.24-6.51,0-9.01l-27.48-30.56Zm-9.24-11.15c-5.21,0-9.45-4.22-9.45-9.45s4.24-9.42,9.45-9.42,9.46,4.22,9.46,9.42-4.22,9.45-9.46,9.45m-85.47-60.55c-5.77,0,3.29-50.66,7.43-50.66h88.85c4.49,0,15.02,50.66,7.96,50.66H89.16Zm9.62,51.1c0-5.2,4.23-9.42,9.45-9.42s9.44,4.22,9.44,9.42-4.21,9.45-9.44,9.45-9.45-4.22-9.45-9.45m1.92,36.9l10.13-11.25c4.94,1.14,9.48,1.14,12.79,1.14h35.82c3.31,0,7.86,0,12.79-1.14l10.14,11.25H100.7Z"/><path d="M219.68,283.46H63.78c-35.22,0-63.78-28.55-63.78-63.78V63.78C0,28.55,28.56,0,63.78,0H219.68c35.22,0,63.78,28.55,63.78,63.78V219.69c0,35.22-28.56,63.78-63.78,63.78m45.36-63.78V63.78c0-25.05-20.31-45.35-45.36-45.35H63.78c-25.05,0-45.35,20.31-45.35,45.35V219.69c0,25.05,20.31,45.35,45.35,45.35H219.68c25.05,0,45.36-20.31,45.36-45.35m-81.17-15.09c.62-.42,1.22-.86,1.66-1.29,5.09-4.12,9.86-10.45,13.31-20.24,4.83-13.74,8.24-26.02,9.18-41.12,1.31-18.6-6.35-47.54-11.43-61.04l-1.77-4.75c-1.09-3.04-5.26-9.47-12.65-17.18-6.35-6.62-12.47-7.11-21.77-7.11h-37.76c-9.3,0-15.4,.49-21.78,7.11-7.39,7.69-11.56,14.15-12.65,17.18l-1.78,4.78c-5.08,13.48-12.73,42.42-11.44,61.04,.94,15.06,4.36,27.32,9.21,41.1,3.45,9.82,8.19,16.12,13.29,20.24,.48,.42,1.06,.85,1.69,1.27l-27.51,30.58c-2.24,2.5-2.24,6.53,0,9.01,2.24,2.47,5.85,2.47,8.07,0l9.5-10.54h104.53l9.48,10.54c2.22,2.47,5.85,2.47,8.07,0,2.24-2.48,2.24-6.51,0-9.01l-27.48-30.56Zm-9.24-11.15c-5.21,0-9.45-4.22-9.45-9.45s4.24-9.42,9.45-9.42,9.46,4.22,9.46,9.42-4.22,9.45-9.46,9.45m-85.47-60.55c-5.77,0,3.29-50.66,7.43-50.66h88.85c4.49,0,15.02,50.66,7.96,50.66H89.16Zm9.62,51.1c0-5.2,4.23-9.42,9.45-9.42s9.44,4.22,9.44,9.42-4.21,9.45-9.44,9.45-9.45-4.22-9.45-9.45m1.92,36.9l10.13-11.25c4.94,1.14,9.48,1.14,12.79,1.14h35.82c3.31,0,7.86,0,12.79-1.14l10.14,11.25H100.7Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 283.465 283.465" enable-background="new 0 0 283.465 283.465" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M183.87,204.599c0.622-0.424,1.223-0.858,1.666-1.293c5.097-4.122,9.857-10.449,13.313-20.242
c4.827-13.737,8.238-26.025,9.183-41.121c1.306-18.605-6.354-47.538-11.433-61.04l-1.767-4.757
c-1.092-3.031-5.257-9.47-12.655-17.179c-6.353-6.618-12.468-7.108-21.768-7.108h-37.757c-9.3,0-15.405,0.49-21.777,7.108
c-7.397,7.687-11.563,14.148-12.646,17.179l-1.776,4.779c-5.079,13.48-12.734,42.413-11.441,61.04
c0.94,15.063,4.36,27.318,9.209,41.099c3.447,9.814,8.194,16.12,13.295,20.242c0.483,0.423,1.057,0.847,1.693,1.271l-27.504,30.581
c-2.237,2.496-2.237,6.528,0,9.002c2.233,2.472,5.849,2.472,8.069,0l9.499-10.539h104.528l9.478,10.539
c2.215,2.472,5.845,2.472,8.068,0c2.237-2.474,2.237-6.506,0-9.002L183.87,204.599z M174.639,193.447
c-5.216,0-9.456-4.223-9.456-9.447c0-5.203,4.24-9.425,9.456-9.425c5.231,0,9.454,4.222,9.454,9.425
C184.093,189.224,179.87,193.447,174.639,193.447 M89.161,132.897c-5.771,0,3.294-50.657,7.432-50.657h88.847
c4.492,0,15.028,50.657,7.969,50.657H89.161z M98.782,184c0-5.203,4.226-9.425,9.448-9.425c5.231,0,9.439,4.222,9.439,9.425
c0,5.224-4.208,9.447-9.439,9.447C103.008,193.447,98.782,189.224,98.782,184 M100.697,220.898l10.127-11.253
c4.935,1.137,9.483,1.137,12.798,1.137h35.817c3.307,0,7.854,0,12.789-1.137l10.132,11.253H100.697z"/>
<path fill="#FFFFFF" d="M219.685,283.465H63.78C28.556,283.465,0,254.91,0,219.685V63.78C0,28.556,28.556,0,63.78,0h155.905
c35.225,0,63.78,28.556,63.78,63.78v155.905C283.465,254.91,254.91,283.465,219.685,283.465 M268.725,219.685V63.78
c0-27.084-21.956-49.039-49.04-49.039H63.78c-27.084,0-49.039,21.955-49.039,49.039v155.905c0,27.084,21.955,49.04,49.039,49.04
h155.905C246.769,268.725,268.725,246.769,268.725,219.685"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,21 @@
.App {
--idfm-black: #2c2e35;
--idfm-white: #ffffff;
height: inherit;
width: inherit;
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
text-align: center;
}
.panel {
min-width: 100%;
height: inherit;
width: inherit;
scroll-snap-align: center;
}

65
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,65 @@
import { Component } from 'solid-js';
import { MatrixCapabilities, WidgetApi, WidgetApiToWidgetAction, CustomEvent, IVisibilityActionRequest } from 'matrix-widget-api';
import { HopeProvider } from "@hope-ui/solid";
import { BusinessDataProvider } from './businessData';
import { SearchProvider } from './search';
import { NextPassagesDisplay } from './nextPassagesDisplay';
import { StopsManager } from './stopsManager';
import styles from './App.module.css';
function parseFragment() {
const fragmentString = (window.location.hash || "?");
return new URLSearchParams(fragmentString.substring(Math.max(fragmentString.indexOf('?'), 0)));
}
const App: Component = () => {
console.log('App: New');
const qs = parseFragment();
const widgetId = qs.get('widgetId');
const userId = qs.get('userId');
console.log("App: widgetId:" + widgetId);
console.log("App: userId:" + userId);
const api = new WidgetApi(widgetId);
api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
api.start();
api.on("ready", function() {
console.log("App: widget API is READY !!!!");
});
// Seems to don´t be used...
api.on(`action:${WidgetApiToWidgetAction.UpdateVisibility}`, (ev: CustomEvent<IVisibilityActionRequest>) => {
console.log("App: Visibility change");
ev.preventDefault(); // we're handling it, so stop the widget API from doing something.
console.log("App: ", ev.detail); // custom handling here
/* api.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{}); */
api.transport.reply(ev.detail, {});
});
return (
<BusinessDataProvider>
<SearchProvider>
<HopeProvider>
<div class={styles.App} data-panelsnap-id="1">
<div class={styles.panel}>
<StopsManager />
</div>
<div class={styles.panel}>
<NextPassagesDisplay />
</div>
</div>
</HopeProvider>
</SearchProvider>
</BusinessDataProvider>
);
};
export default App;

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,79 @@
import { createContext, createSignal } from 'solid-js';
import { createStore } from 'solid-js/store';
import { Passages, Stops } from './types';
interface Store {
passages: () => Passages;
getLinePassages?: (lineId: string) => Passages;
addPassages?: (passages) => void;
clearPassages?: () => void;
stops: () => Stops;
addStops?: (stops) => void;
};
export const BusinessDataContext = createContext<Store>();
export function BusinessDataProvider(props: { children: JSX.Element }) {
const [serverUrl, setServerUrl] = createSignal<string>("https://localhost:4443");
const [store, setStore] = createStore({ lines: {}, passages: {}, stops: {} });
async function getLine(lineId: number) {
let line = store.lines[lineId];
if (line === undefined) {
console.log(`${lineId} not found... fetch it from backend.`);
const data = await fetch(`${serverUrl()}/line/${lineId}`, {
headers: { 'Content-Type': 'application/json' }
});
line = await data.json();
setStore('lines', lineId, line);
}
return line;
}
const passages = () => {
return store.passages;
};
const getLinePassages = (lineId: string) => {
return store.passages[lineId];
};
const addPassages = (passages) => {
setStore((s) => {
// console.log("s=", s);
setStore('passages', passages);
// console.log("s=", s);
});
}
const clearPassages = () => {
setStore((s) => {
// TODO: Really need to set to undefined to reset ?
console.log("s=", s);
console.log("s.passages=", s.passages);
// setStore('passages', undefined);
// setStore('passages', {});
console.log("Object.keys(s.passages)=", Object.keys(s.passages));
for (const lineId of Object.keys(s.passages)) {
console.log("lineId=", lineId);
setStore('passages', lineId, undefined);
}
console.log("s=", s);
});
// setStore('passages', undefined);
// setStore('passages', {});
// }
console.log("passages=", store.passages);
}
return (
<BusinessDataContext.Provider value={{ getLine, passages, getLinePassages, addPassages, clearPassages, serverUrl }}>
{props.children}
</BusinessDataContext.Provider>
);
}

28
frontend/src/index.css Normal file
View File

@@ -0,0 +1,28 @@
@font-face {
font-family: IDFVoyageur-regular;
src: url(/public/fonts/IDFVoyageur-Regular.otf)
}
@font-face {
font-family: IDFVoyageur-bold;
src: url(/public/fonts/IDFVoyageur-Bold.otf);
}
@font-face {
font-family: IDFVoyageur-medium;
src: url(/public/fonts/IDFVoyageur-Medium.otf);
}
body {
aspect-ratio: 16/9;
width: 100vw;
margin: 0;
font-family: IDFVoyageur;
}
#root {
height: inherit;
width: inherit;
}

7
frontend/src/index.tsx Normal file
View File

@@ -0,0 +1,7 @@
/* @refresh reload */
import { render } from 'solid-js/web';
import './index.css';
import App from './App';
render(() => (<App/>), document.getElementById('root') as HTMLElement);

View File

@@ -0,0 +1,226 @@
/* TODO: Remove this class */
.ar16x9 {
aspect-ratio: 16 / 9;
}
/* Idfm: 1860x1080px */
.NextPassagesDisplay {
aspect-ratio: 16/9;
--reverse-aspect-ratio: 9/16;
/* height is set according to the aspect-ratio, don´t touch it */
width: 100%;
display: flex;
flex-direction: column;
background-color: var(--idfm-black);
}
/* Idfm: 1800x100px (margin: 17px 60px) */
.header {
width: calc(1800/1920*100%);
height: calc(100/1080*100%);
/*Percentage margin are computed relatively to the nearest block container's width, not height */
/* cf. https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom */
margin: calc(17/1080*var(--reverse-aspect-ratio)*100%) calc(60/1920*100%);
display: flex;
align-items: center;
font-family: IDFVoyageur-bold;
}
.header .transportMode {
height: 100%;
margin: 0;
margin-right: calc(23/1920*100%);
}
.header .title {
height: 50%;
width: 70%;
margin-right: auto;
}
.header .clock {
width: calc(175/1920*100%);
height: calc(80/100*100%);
display: flex;
align-items: center;
justify-content: center;
border:solid var(--idfm-white) 3px;
border-radius: calc(9/86*100%);
}
.header .clock svg {
aspect-ratio: 2.45;
height: calc(0.7*100%);
}
/* Idfm: 1860x892px (margin: 0px 30px) */
.panelsContainer {
width: calc(1860/1920*100%);
height: calc(892/1080*100%);
margin: 0 calc(30/1920*100%);
display: flex;
flex-direction: column;
background-color: white;
border-collapse:separate;
border:solid var(--idfm-black) 1px;
border-radius: calc(15/1920*100%);
}
.nextPassagesContainer {
height: 100%;
width: 100%;
display: none;
position: relative;
}
.nextPassagesContainer .line:last-child {
border-bottom: 0;
/* To make up for the bottom border deletion */
padding-bottom: calc(2px);
}
.displayed {
display: block;
}
/* Idfm: 1880x176px (margin: 0px 20px) */
.line {
width: calc(1880/1920*100%);
height: calc(100% / 5);
margin: 0 calc(20/1920*100%);
display: flex;
align-items: center;
/* TODO: compute the border weight according to the parent height */
/* TODO: Disable border-bottom for the last .line */
border-bottom: solid calc(2px);
}
.line svg {
font-family: IDFVoyageur-bold;
max-width: 100%;
max-height: 100%;
}
/* Idfm: 100x100px (margin: 0px 15px) */
.transportMode {
aspect-ratio : 1 / 1;
height: calc(100/176*100%);
margin: 0 calc(15/1920*100%);
}
.tramLinePicto {
aspect-ratio : 1 / 1;
height: calc(100/176*100%);
margin-right: calc(23/1920*100%);
}
.busLinePicto {
aspect-ratio : 2.25;
height: calc(70/176*100%);
margin-right: calc(23/1920*100%);
}
.destination {
height: calc(60/176*100%);
width: 50%;
font-family: IDFVoyageur-bold;
text-align: left;
}
.trafficStatus {
height: calc(50/176*100%);
aspect-ratio: 35/50;
margin-left: auto;
display: flex;
align-items: center;
justify-content: center;
}
.trafficStatus svg {
width: 100%;
}
.firstPassage {
height: calc(100/176*100%);
aspect-ratio: 2.5;
display: flex;
align-items: center;
justify-content: center;
padding-right: calc(30/1920*100%);
/* TODO: compute the border weight according to the parent width */
border-right: solid calc(5px);
}
.unavailableFirstPassage {
height: calc(100/176*100%);
aspect-ratio: calc(230/100);
margin-right: calc(30/1920*100%);
/* TODO: compute the border weight according to the parent width */
border-right: solid calc(5px);
}
.firstPassage svg {
aspect-ratio: 215/50;
height: calc(1/2*100%);
}
.secondPassage {
height: calc(45/176*100%);
aspect-ratio: calc(230/45);
margin-right: calc(30/1920*100%);
}
.secondPassage svg {
font-family: IDFVoyageur-regular;
}
.unavailableSecondPassage {
height: calc(100/176*100%);
aspect-ratio: calc(230/100);
margin-right: calc(30/1920*100%);
}
.unavailableSecondNextPassage svg {
font-family: IDFVoyageur-regular;
}
/* Idfm: 1800x54px (margin: 0px 50px) */
.footer {
width: calc(1820/1920*100%);
height: calc(54/1080*100%);
margin: 0 calc(50/1920*100%);
display: flex;
align-items: center;
justify-content: right;
}
.footer div {
aspect-ratio: 1;
height: 50%;
margin-left: calc(42/1920*100%);
}

View File

@@ -0,0 +1,253 @@
import { Component, createEffect, createSignal, useContext } from "solid-js";
import { createStore } from "solid-js/store";
import { createDateNow } from "@solid-primitives/date";
import { format } from "date-fns";
import { getTransportModeSrc } from "./types";
import { BusinessDataContext } from "./businessData";
import { NextPassagesPanel } from "./nextPassagesPanel";
import { SearchContext } from "./search";
import styles from "./nextPassagesDisplay.module.css";
export const NextPassagesDisplay: Component = () => {
const maxPassagePerPanel = 5;
const syncPeriodMsec = 20 * 1000;
const { passages, getLinePassages, addPassages, clearPassages, serverUrl } =
useContext(BusinessDataContext);
const { getDisplayedStop } = useContext(SearchContext);
const [panels, setPanels] = createStore([]);
const [displayedPanelId, setDisplayedPanelId] = createSignal<number>(0);
let _lines = new Map();
const [dateNow] = createDateNow(1000);
const panelSwapInterval = setInterval(() => {
let nextPanelId = displayedPanelId() + 1;
if (nextPanelId >= panels.length) {
nextPanelId = 0;
}
/* console.log(`Display panel #${nextPanelId}`); */
setDisplayedPanelId(nextPanelId);
}, 4000);
createEffect(() => {
console.log("######### onStopIdUpdate #########");
// Track local.stopIp to force dependency.
console.log("getDisplayedStop=", getDisplayedStop());
clearPassages();
});
createEffect(async () => {
console.log(`## OnPassageUpdate ${passages()} ##`);
/* console.log(passages()); */
await requestPassages();
});
async function _fetchLine(lineId: string) {
if (!_lines.has(lineId)) {
const data = await fetch(`${serverUrl()}/line/${lineId}`, {
headers: { "Content-Type": "application/json" },
});
const line = await data.json();
_lines.set(line.id, line);
}
}
async function requestPassages() {
console.log("### requestPassages ###");
/* TODO: Manage several displays (one by stop) */
const stops = getDisplayedStop();
if (stops.length == 0) {
return;
}
const stop = stops[0];
const httpOptions = { headers: { "Content-Type": "application/json" } };
if (stop !== undefined) {
const stopId = stop.id;
console.log(`Fetching data for ${stopId}`);
const url = `${serverUrl()}/stop/nextPassages/${stopId}`;
/* console.log(`url=${url}`); */
const data = await fetch(url, httpOptions);
const response = await data.json();
/* console.log(response); */
const byLineByDstPassages = response.passages;
/* console.log(byLineByDstPassages); */
const linePromises = [];
for (const lineId of Object.keys(byLineByDstPassages)) {
linePromises.push(_fetchLine(lineId));
}
await Promise.all(linePromises);
console.log("byLineByDstPassages=", byLineByDstPassages);
// console.log("before addPassages passages=", passages());
addPassages(byLineByDstPassages);
console.log("AFTER passages=", passages());
}
}
setInterval(
// const nextPassagesRequestsInterval = setTimeout(
async () => {
await requestPassages();
},
syncPeriodMsec
);
// TODO: Sort transport modes by weight
// TODO: Split this method to isolate the nextPassagesPanel part.
function _computeHeader(title: string): JSX.Element {
let transportModes = [];
transportModes = new Set(
Object.keys(passages()).map((lineId) => {
const line = _lines.get(lineId);
if (line !== undefined) {
return getTransportModeSrc(line.transportMode, false);
}
return null;
})
);
return (
<div class={styles.header}>
<For each={Array.from(transportModes)}>
{(transportMode) => {
return (
<div class={styles.transportMode}>
<img src={transportMode} />
</div>
);
}}
</For>
<div class={styles.title}>
<svg viewbox="0 0 1260 50">
<text
x="0"
y="50%"
dominant-baseline="middle"
font-size="50"
style="fill: #ffffff"
>
{title}
</text>
</svg>
</div>
<div class={styles.clock}>
<svg viewbox="0 0 115 43">
<text
x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
font-size="43"
style="fill: #ffffff"
>
{format(dateNow(), "HH:mm")}
</text>
</svg>
</div>
</div>
);
}
function _computeFooter(): JSX.Element {
return (
<div class={styles.footer}>
<For each={panels}>
{(positioned) => {
const { position, panel } = positioned;
const circleStyle = {
fill: `var(--idfm-${position == displayedPanelId() ? "white" : "black"
})`,
};
return (
<div>
<svg viewBox="0 0 29 29">
<circle
cx="50%"
cy="50%"
r="13"
stroke="#ffffff"
stroke-width="3"
style={circleStyle}
/>
</svg>
</div>
);
}}
</For>
</div>
);
}
const mainDivClasses = `${styles.NextPassagesDisplay} ${styles.ar16x9}`;
return (
<div class={mainDivClasses}>
{_computeHeader("Prochains passages")}
<div class={styles.panelsContainer}>
{() => {
setPanels([]);
let newPanels = [];
let positioneds = [];
let index = 0;
let chunk = {};
let chunkSize = 0;
console.log("passages=", passages());
for (const lineId of Object.keys(passages())) {
console.log("lineId=", lineId);
const byLinePassages = getLinePassages(lineId);
console.log("byLinePassages=", byLinePassages);
const byLinePassagesKeys = Object.keys(byLinePassages);
console.log("byLinePassagesKeys=", byLinePassagesKeys);
if (byLinePassagesKeys.length <= maxPassagePerPanel - chunkSize) {
chunk[lineId] = byLinePassages;
chunkSize += byLinePassagesKeys.length;
} else {
console.log("chunk=", chunk);
const [store, setStore] = createStore(chunk);
const panelid = index++;
const panel = (
<NextPassagesPanel
show={panelid == displayedPanelId()}
nextPassages={store}
lines={_lines}
/>
);
newPanels.push(panel);
positioneds.push({ position: panelid, panel });
chunk = {};
chunk[lineId] = byLinePassages;
chunkSize = byLinePassagesKeys.length;
}
}
if (chunkSize) {
const panelId = index++;
const [store, setStore] = createStore(chunk);
const panel = (
<NextPassagesPanel
show={panelId == displayedPanelId()}
nextPassages={store}
lines={_lines}
/>
);
newPanels.push(panel);
positioneds.push({ position: panelId, panel });
}
setPanels(positioneds);
return newPanels;
}}
</div>
{_computeFooter()}
</div>
);
};

View File

@@ -0,0 +1,121 @@
import { Component } from 'solid-js';
import { createStore } from 'solid-js/store';
import { createDateNow, getTime } from '@solid-primitives/date';
import { Motion } from "@motionone/solid";
import { TrafficStatus } from './types';
import { renderLineTransportMode, renderLinePicto } from './utils';
import styles from './nextPassagesDisplay.module.css';
export const NextPassagesPanel: Component = (props) => {
/* TODO: Find where to get data to compute traffic status. */
const trafficStatusColor = new Map<TrafficStatus, string>([
[TrafficStatus.UNKNOWN, "#ffffff"],
[TrafficStatus.FLUID, "#00643c"],
[TrafficStatus.DISRUPTED, "#ffbe00"],
[TrafficStatus.VERY_DISRUPTED, "#ff5a00"],
[TrafficStatus.BYPASSED, "#ffffff"]
]);
const [dateNow] = createDateNow(5000);
function _computeTtwPassage(class_, passage, fontSize) {
const refTs = passage.expectedDepartTs !== null ? passage.expectedDepartTs : passage.expectedArrivalTs;
const ttwSec = refTs - (getTime(dateNow()) / 1000);
const isApproaching = ttwSec <= 60;
return (
<div class={class_}>
<svg viewBox={`0 0 215 ${fontSize}`}>
<Motion.text
x="100%" y="55%"
dominant-baseline="middle" text-anchor="end"
font-size={fontSize} style={{ fill: "#000000" }}
initial={isApproaching}
animate={{ opacity: [1, 0, 1] }}
transition={{ duration: 3, repeat: Infinity }}>
{Math.floor(ttwSec / 60)} min
</Motion.text>
</svg>
</div>
);
}
function _computeUnavailablePassage(class_) {
const textStyle = { fill: "#000000" };
return (
<div class={class_}>
<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="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>
</svg>
</div>
);
}
function _computeSecondPassage(passage): JSX.Element {
return (
<Show when={passage !== undefined} fallback={_computeUnavailablePassage(styles.unavailableSecondPassage)}>
{_computeTtwPassage(styles.secondPassage, passage, 45)}
</Show>
);
}
function _computeFirstPassage(passage): JSX.Element {
return (
<Show when={passage !== undefined} fallback={_computeUnavailablePassage(styles.unavailableFirstPassage)}>
{_computeTtwPassage(styles.firstPassage, passage, 50)}
</Show>
);
}
/* TODO: Manage end of service */
function _genNextPassages(nextPassages, line, destination) {
const nextPassagesLength = nextPassages.length;
const firstPassage = nextPassagesLength > 0 ? nextPassages[0] : undefined;
const secondPassage = nextPassagesLength > 1 ? nextPassages[1] : undefined;
const trafficStatusStyle = { fill: trafficStatusColor.get(line.trafficStatus) };
return (
<div class={styles.line}>
<div class={styles.transportMode}>
{renderLineTransportMode(line)}
</div>
{renderLinePicto(line, styles)}
<div class={styles.destination}>
<svg viewbox="0 0 600 40">
<text x="0" y="50%" dominant-baseline="middle" font-size="40" style={{ fill: "#000000" }}>
{destination}
</text>
</svg>
</div>
<div class={styles.trafficStatus}>
<svg viewBox="0 0 51 51">
<circle cx="50%" cy="50%" r="24" stroke="#231f20" stroke-width="3" style={trafficStatusStyle} />
</svg>
</div>
{firstPassage ? _computeFirstPassage(firstPassage) : null}
{secondPassage ? _computeSecondPassage(secondPassage) : null}
</div>
);
}
return (
<div classList={{ [styles.nextPassagesContainer]: true, [styles.displayed]: props.show }} style={{ "top": `${100 * props.position}%` }}>
{() => {
const ret = [];
for (const lineId of Object.keys(props.nextPassages)) {
const line = props.lines.get(lineId);
const byLineNextPassages = props.nextPassages[lineId];
for (const destination of Object.keys(byLineNextPassages)) {
const nextPassages = byLineNextPassages[destination];
ret.push(_genNextPassages(nextPassages, line, destination));
}
}
return ret;
}}
</div>
);
}

75
frontend/src/search.tsx Normal file
View File

@@ -0,0 +1,75 @@
import { batch, createContext, createSignal } from 'solid-js';
import { createStore } from 'solid-js/store';
import { Stop, Stops } from './types';
interface Store {
getMarkers: () => Markers;
addMarkers?: (stopId, markers) => void;
setMarkers?: (markers) => void;
getStops: () => Stops;
setStops?: (stops) => void;
removeStops?: (stopIds) => void;
getDisplayedStop: () => Stop;
setDisplayedStop: (stop: Stop) => void;
};
export const SearchContext = createContext<Store>();
export function SearchProvider(props: { children: JSX.Element }) {
const [store, setStore] = createStore({stops: {}, markers: {}, displayedStop: []});
const getStops = () => {
return store.stops;
};
const setStops = (stops) => {
setStore((s) => {
setStore('stops', stops);
});
};
const removeStops = (stopIds) => {
batch(() => {
for(const stopId of stopIds) {
setStore('stops', stopId, undefined);
setStore('markers', stopId, undefined);
}
});
};
const getMarkers = () => {
return store.markers;
};
const addMarkers = (stopId, markers) => {
setStore('markers', stopId, markers);
};
const setMarkers = (markers) => {
setStore('markers', markers);
};
const getDisplayedStop = () => {
/* console.log(store.displayedStop); */
return store.displayedStop;
};
const setDisplayedStop = (stop: Stop) => {
/* console.log(stop); */
setStore((s) => {
console.log("s.displayedStop=", s.displayedStop);
setStore('displayedStop', [stop]);
});
/* console.log(store.displayedStop); */
};
return (
<SearchContext.Provider value={{addMarkers, getMarkers, setMarkers, getStops, removeStops, setStops, getDisplayedStop, setDisplayedStop}}>
{props.children}
</SearchContext.Provider>
);
}

View File

@@ -0,0 +1,33 @@
svg {
font-family: IDFVoyageur-bold;
}
.transportMode {
aspect-ratio : 1 / 1;
height: 70%;
margin-left: 1%;
}
.tramLinePicto {
height: 70%;
margin-left: 1%;
aspect-ratio : 1 / 1;
}
.trainLinePicto {
height: 70%;
margin-left: 1%;
aspect-ratio : 1 / 1;
}
.metroLinePicto {
height: 70%;
margin-left: 1%;
aspect-ratio : 1 / 1;
}
.busLinePicto {
height: 70%;
margin-left: 1%;
aspect-ratio : 2.25;
}

View File

@@ -0,0 +1,224 @@
import { batch, Component, createEffect, createResource, createSignal, onMount, Show, useContext } from 'solid-js';
import {
Box, Button, Input, InputLeftAddon, InputGroup, HStack, List, ListItem, Progress,
ProgressIndicator, VStack
} from "@hope-ui/solid";
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import { BusinessDataContext } from './businessData';
import { SearchContext } from './search';
import { renderLineTransportMode, renderLinePicto, TransportModeWeights } from './utils';
import styles from './stopManager.module.css';
const StopRepr: Component = (props) => {
const { getLine } = useContext(BusinessDataContext);
const [lineReprs] = createResource(props.stop.lines, fetchLinesRepr);
async function fetchLinesRepr(lineIds) {
const reprs = [];
for (const lineId of lineIds) {
const line = await getLine(lineId);
if (line !== undefined) {
reprs.push(<div class={styles.transportMode}>{renderLineTransportMode(line)}</div>);
reprs.push(renderLinePicto(line, styles));
}
}
return reprs;
}
return (
<HStack height="100%">
{props.stop.name}
<For each={lineReprs()}>{(line) => line}</For>
</HStack>
);
}
const StopAreaRepr: Component = (props) => {
const { getLine } = useContext(BusinessDataContext);
const [lineReprs] = createResource(props.stop, fetchLinesRepr);
async function fetchLinesRepr(stop) {
const lineIds = new Set(stop.lines);
const stops = stop.stops;
for (const stop of stops) {
stop.lines.forEach(lineIds.add, lineIds);
}
const byModeReprs = {};
for (const lineId of lineIds) {
const line = await getLine(lineId);
if (line !== undefined) {
if (!(line.transportMode in byModeReprs)) {
byModeReprs[line.transportMode] = {
mode: <div class={styles.transportMode}>{renderLineTransportMode(line)}</div>
};
}
byModeReprs[line.transportMode][line.shortName] = renderLinePicto(line, styles);
}
}
const reprs = [];
const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] < TransportModeWeights[y]);
for (const transportMode of sortedTransportModes) {
const lines = byModeReprs[transportMode];
const repr = [lines.mode];
delete lines.mode;
for (const lineId of Object.keys(lines).sort((x, y) => x.localeCompare(y))) {
repr.push(lines[lineId]);
}
reprs.push(repr);
}
return reprs;
}
return (
<HStack height="100%">
{props.stop.name}
<For each={lineReprs()}>{(line) => line}</For>
</HStack>
);
}
const Map: Component = (props) => {
const mapCenter = [48.853, 2.35];
const { addMarkers, getStops } = useContext(SearchContext);
let mapDiv: any;
let map = null;
const stopsLayerGroup = L.featureGroup();
function buildMap(div: HTMLDivElement) {
map = L.map(div).setView(mapCenter, 11);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
stopsLayerGroup.addTo(map);
}
function setMarker(stop) {
const markers = [];
if (stop.lat !== undefined && stop.lon !== undefined) {
/* TODO: Add stop lines representation to popup. */
markers.push(L.marker([stop.lat, stop.lon]).bindPopup(`${stop.name}`).openPopup());
}
else {
for (const _stop of stop.stops) {
markers.push(...setMarker(_stop));
}
}
return markers;
}
onMount(() => buildMap(mapDiv));
const onStopUpdate = createEffect(() => {
/* TODO: Avoid to clear all layers... */
stopsLayerGroup.clearLayers();
for (const stop of Object.values(getStops())) {
const markers = setMarker(stop);
addMarkers(stop.id, markers);
for (const marker of markers) {
stopsLayerGroup.addLayer(marker);
}
}
const stopsBound = stopsLayerGroup.getBounds();
if (Object.keys(stopsBound).length) {
map.fitBounds(stopsBound);
}
});
return <div ref={mapDiv} id='main-map' style={{ width: "100%", height: "100%" }} />;
}
export const StopsManager: Component = (props) => {
const [minCharactersNb, setMinCharactersNb] = createSignal<int>(4);
const [_inProgress, _setInProgress] = createSignal<bool>(false);
const { serverUrl } = useContext(BusinessDataContext);
const { getStops, removeStops, setStops, setDisplayedStop } = useContext(SearchContext);
async function _fetchStopByName(name) {
const data = await fetch(`${serverUrl()}/stop/?name=${name}`, {
headers: { 'Content-Type': 'application/json' }
});
const stops = await data.json();
const stopIds = stops.map((stop) => stop.id);
const stopIdsToRemove = Object.keys(getStops()).filter(stopId => !(stopId in stopIds));
const byIdStops = {};
for (const stop of stops) {
byIdStops[stop.id] = stop;
}
batch(() => {
removeStops(stopIdsToRemove);
setStops(byIdStops);
});
}
async function _onStopNameInput(event) {
/* TODO: Add a tempo before fetching stop for giving time to user to finish his request */
const stopName = event.target.value;
if (stopName.length >= minCharactersNb()) {
console.log(`Fetching data for ${stopName}`);
_setInProgress(true);
await _fetchStopByName(stopName);
_setInProgress(false);
}
}
return (
<VStack h="100%">
<InputGroup w="50%" h="5%">
<InputLeftAddon>🚉 🚏</InputLeftAddon>
<Input onInput={_onStopNameInput} readOnly={_inProgress()} placeholder="Stop name..." />
</InputGroup>
<Progress size="xs" w="50%" indeterminate={_inProgress()}>
<ProgressIndicator striped animated />
</Progress>
<Box w="100%" h="40%" borderWidth="1px" borderColor="var(--idfm-black)" borderRadius="$lg" overflow="scroll" marginBottom="2px">
<List width="100%" height="100%">
{() => {
const items = [];
for (const stop of Object.values(getStops()).sort((x, y) => x.name.localeCompare(y.name))) {
items.push(
<ListItem h="10%" borderWidth="1px" mb="0px" color="var(--idfm-black)" borderRadius="$lg">
<Button fullWidth="true" color="var(--idfm-black)" bg="white" onClick={() => {
console.log(`${stop.id} clicked !!!`);
setDisplayedStop(stop);
}}>
<Box w="100%" h="100%">
<Show when={stop.stops !== undefined} fallback={<StopRepr stop={stop} />}>
<StopAreaRepr stop={stop} />
</Show>
</Box>
</Button>
</ListItem>);
}
return items;
}}
</List>
</Box>
<Box borderWidth="1px" borderColor="var(--idfm-black)" borderRadius="$lg" h="55%" w="100%" overflow="scroll">
<Map />
</Box>
</VStack>
);
};

43
frontend/src/types.tsx Normal file
View File

@@ -0,0 +1,43 @@
const validTransportModes = ["bus", "tram", "metro", "rer", "transilien", "funicular", "ter", "unknown"];
export function getTransportModeSrc(mode: string, color: bool = true): string {
let ret = null;
if (validTransportModes.includes(mode)) {
ret = `/public/symbole_${mode}_${color ? "" : "support_fonce_"}RVB.svg`;
}
return ret;
}
export enum TrafficStatus {
UNKNOWN = 0,
FLUID,
DISRUPTED,
VERY_DISRUPTED,
BYPASSED
}
export interface Passages { };
export interface Passage {
line: number,
operator: string,
destinations: Array<string>,
atStop: boolean,
aimedArrivalTs: number,
expectedArrivalTs: number,
arrivalPlatformName: string,
aimedDepartTs: number,
expectedDepartTs: number,
arrivalStatus: string,
departStatus: string,
};
export interface Stops { };
export interface Stop {
id: number,
name: string,
town: string,
lat: number,
lon: number,
lines: Array<string>
};

106
frontend/src/utils.tsx Normal file
View File

@@ -0,0 +1,106 @@
import { getTransportModeSrc } from './types';
export const TransportModeWeights = {
bus: 1,
tram: 2,
val: 3,
funicular: 4,
metro: 5,
rer: 6,
transilien: 7,
ter: 8,
};
export function renderLineTransportMode(line): JSX.Element {
return <img src={getTransportModeSrc(line.transportMode)} />
}
function renderBusLinePicto(line, styles): JSX.Element {
return (
<div class={styles.busLinePicto}>
<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}` }} />
<text x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
font-size="7.4"
style={{ fill: `#${line.foreColorHexa}` }}>
{line.shortName}
</text>
</svg>
</div>
);
}
function renderTramLinePicto(line, styles): JSX.Element {
const lineStyle = { fill: `#${line.backColorHexa}` };
return (
<div class={styles.tramLinePicto}>
<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="17" width="20" height="3" rx="1" ry="1" style={lineStyle} />
<text x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
font-size="11"
style={{ fill: "#00000" }}>
{line.shortName}
</text>
</svg>
</div>
);
}
function renderMetroLinePicto(line, styles): JSX.Element {
return (
<div class={styles.metroLinePicto}>
<svg viewbox="0 0 20 20">
<circle cx="10" cy="10" r="10" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
font-size="11" style={{ fill: `#${line.foreColorHexa}` }}>
{line.shortName}
</text>
</svg>
</div>
);
}
function renderTrainLinePicto(line, styles): JSX.Element {
return (
<div class={styles.trainLinePicto}>
<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}` }} />
<text x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
font-size="11"
style={{ fill: `#${line.foreColorHexa}` }}>
{line.shortName}
</text>
</svg>
</div>
);
}
export function renderLinePicto(line, styles): JSX.Element {
switch (line.transportMode) {
case "bus":
case "funicular":
return renderBusLinePicto(line, styles);
case "tram":
return renderTramLinePicto(line, styles);
/* case "val": */
case "metro":
return renderMetroLinePicto(line, styles);
case "transilien":
case "rer":
case "ter":
return renderTrainLinePicto(line, styles);
}
}

21
frontend/tsconfig.json Normal file
View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js",
"noImplicitAny": true,
"target": "ES6",
"moduleResolution": "node",
"allowJs": true,
"outDir": "build",
"strict": true,
"types": ["vite/client"],
"noEmit": true,
"isolatedModules": true,
"plugins": [
{
"name": "typescript-eslint-language-service"
}
]
},
"include": ["src"]
}

23
frontend/vite.config.ts Normal file
View File

@@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
import basicSsl from '@vitejs/plugin-basic-ssl'
export default defineConfig({
plugins: [solidPlugin(), basicSsl()],
server: {
port: 3000,
base: '/widget',
proxy: {
'/widget/.*': {
target: 'https://localhost:3000/',
rewrite: (path) => {
console.error("PATH: ", path);
return path.replace(/\/widget/, '#');
},
},
},
},
build: {
target: 'esnext',
},
});