Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVP: Setup of the latest otp-react-redux app implementation #206

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "web-demo/otp-react-redux"]
path = web-demo/lib/vendor/otp-react-redux
url = https://github.com/opentripplanner/otp-react-redux.git
20 changes: 20 additions & 0 deletions web-demo/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"plugins": [
"babel-plugin-add-module-exports",
"@babel/plugin-proposal-class-properties",
"babel-plugin-lodash"
],
"presets": [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
"env": {
"development": {
"plugins": ["react-refresh/babel"]
},
"test": {
"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]]
}
}
}
126 changes: 126 additions & 0 deletions web-demo/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
module.exports = {
extends: [
'standard',
'standard-jsx',
'react-app',
'plugin:@typescript-eslint/recommended',
'plugin:typescript-sort-keys/recommended',
'plugin:react/recommended',
'plugin:jest/recommended',
'plugin:jsx-a11y/strict',
'plugin:prettier/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
'sort-keys-fix',
'import',
'jest',
'jsx-a11y',
'react',
'sort-destructure-keys',
'sort-imports-es6-autofix',
'typescript-sort-keys'
],
rules: {
'@typescript-eslint/member-delimiter-style': [
'off',
{
multiline: {
delimiter: 'none',
requireLast: false
},
singleline: {
delimiter: 'comma',
requireLast: false
}
}
],
'@typescript-eslint/no-use-before-define': ['error'],
'@typescript-eslint/no-var-requires': 0,
complexity: ['warn', 12],
'import/order': [
'warn',
{
'newlines-between': 'always'
}
],
'jsx-a11y/label-has-for': [
2,
{
allowChildren: false,
components: ['Label'],
required: {
every: ['id']
}
}
],
// from docs: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md#how-to-use
// it must be disabled to work correctly
'no-use-before-define': 'off',
'object-curly-spacing': 0,
'prefer-const': [
'warn',
{
destructuring: 'all',
ignoreReadBeforeAssign: false
}
],
'prettier/prettier': [
'error',
{
semi: false,
singleQuote: true,
trailingComma: 'none'
}
],
quotes: [2, 'single', { avoidEscape: true }],
'react/jsx-handler-names': 'off',
'react/jsx-sort-props': [
'error',
{
ignoreCase: true
}
],
'sort-destructure-keys/sort-destructure-keys': [
'error',
{
caseSensitive: false
}
],
'sort-imports-es6-autofix/sort-imports-es6': [
2,
{
ignoreCase: true,
ignoreMemberSort: false
}
],
'sort-keys': [
'error',
'asc',
{
caseSensitive: false
}
],
'sort-keys-fix/sort-keys-fix': [
'warn',
'asc',
{
caseSensitive: false
}
],
'sort-vars': [
'error',
{
ignoreCase: true
}
]
},
settings: {
react: {
version: '999.999.999'
}
}
}

1 change: 1 addition & 0 deletions web-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
51 changes: 51 additions & 0 deletions web-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Web app based on otp-react-redux

<img src="https://github.com/opentripplanner/otp-react-redux/raw/master/otprr.png" width="500" />

[![Join the chat for otp-react-redux at https://gitter.im/opentripplanner/otp-react-redux](https://badges.gitter.im/repo.png)](https://gitter.im/opentripplanner/otp-react-redux)

This is an example implementation using otp-react-redux for Italy South Tyrol region. otp-react-redux is a library for writing modern [OpenTripPlanner](http://www.opentripplanner.org/)-compatible multimodal journey planning applications using [React]() and [Redux]().

## Note on this integration

While it's not possible to directly use otp-react-redux as a library, we want to integrate as much upstream changes as possible. We've integrated the base otp-react-redux app as a git submodule in `otp-react-redux` folder.

Changes that are generic enough to be integrated within the upstream application should be done in the otp-react-redux git repository. Some files from this folder are copied over from otp-react-redux, mainly the dependendies of the project and the build scripts.

When updating the upstream repository, the dependencies and potential changes to the build script should be integrated in this folder as needed.

## Running the application

To run, first clone the repo and install [yarn](https://yarnpkg.com/) if needed.

Update `config.yml` with the needed API keys, and optionally, the OTP endpoint and initial map origin. (The default values are for a test server for Portland, OR.). See the comments at the head of the config file for further details.

Install the dependencies and start a local development server using the following script:

```bash
yarn start
```

The port on which the development server listens can be configured in `.env`.

Should you want to maintain multiple configuration files, OTP-RR can be made to use a custom config file by using environment variables. Other environment variables also exist. `CUSTOM_CSS` can be used to point to a css file to inject, and `JS_CONFIG` can be used to point to a `config.js` file to override the one shipped with OTP-RR.

```bash
env YAML_CONFIG=/absolute/path/to/config.yml yarn start
```

## Deploying the UI

Build a production js/css bundle by running `yarn build`. The build will appear in the `dist/` directory). It consists entirely of static files and can be served by a simple static web server or CDN.

The same environment variables which affect the behavior of `yarn start` also affect `yarn build`. Running the following command builds OTP-RR with customized js and css:

```bash
env JS_CONFIG=my-custom-js.js CUSTOM_CSS=my-custom-css.css yarn build
```

## Library Documentation

You can chat with the main OTP-RR developers in our [Gitter chat](https://gitter.im/opentripplanner/otp-react-redux). Support is not guaranteed, but we may be able to answer questions and assist people wishing to make contributions.

As of version 2.0, otp-react-redux utilizes React's context API in a number of components. This changed the way that some components receive props such that they will not work properly unless wrapped with the context provider used in the `ResponsiveWebapp` component.
64 changes: 64 additions & 0 deletions web-demo/craco-icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import PropTypes from 'prop-types'
import React from 'react'
// FIXME: This dependency is restricting typescripting of this file
import {
ClassicBus,
ClassicGondola,
ClassicModeIcon,
Ferry,
LegIcon,
StandardGondola
} from '@opentripplanner/icons'

/**
* For more advanced users, you can replicate and customize components and
* observe the change in icons.
* - For LegIcon: https://github.com/opentripplanner/otp-ui/blob/master/packages/icons/src/trimet-leg-icon.js
* - For ModeIcon: https://github.com/opentripplanner/otp-ui/blob/master/packages/icons/src/trimet-mode-icon.js
* The example below shuffles some icons around from what you might normally
* expect for demonstration purposes.
*
* These are *examples* of mode/leg icon customizations
*/

const CustomTransitIcon = Ferry
const CustomRailIcon = ClassicGondola
const CustomStreetcarIcon = StandardGondola
const CustomBikeRentalIcon = ClassicBus

/**
* This component renders a custom icon for a passed mode
*/
export const CustomModeIcon = ({ mode, ...props }) => {
if (!mode) return null
switch (mode.toLowerCase()) {
// Place custom icons for each mode here.
case 'transit':
return <CustomTransitIcon {...props} />
case 'rail':
return <CustomRailIcon {...props} />
default:
return <ClassicModeIcon mode={mode} {...props} />
}
}
CustomModeIcon.propTypes = {
mode: PropTypes.string
}

/**
* This component renders a custom icon for a mode given a passed leg
*/
export const CustomLegIcon = ({ leg, ...props }) => {
if (leg.routeLongName && leg.routeLongName.startsWith('MAX')) {
return <CustomStreetcarIcon />
} else if (leg.rentedBike) {
return <CustomBikeRentalIcon />
}
return <LegIcon leg={leg} ModeIcon={CustomModeIcon} {...props} />
}
CustomLegIcon.propTypes = {
leg: PropTypes.shape({
rentedBike: PropTypes.bool,
routeLongName: PropTypes.string
})
}
Loading