-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add interactive stop to map for create shuttle stop and edit sh…
…uttle stop (#999) * feat: add map to stop page * fix: add png files from leaflet dist to fix incorrect leaflet asset path * feat: add stop marker on stop edit page * feat: live stop_form with React map updates using phoenix_live_react * fix: update stop_controller to use get for index page * tests: add tests for stop_live * fix: add @types packages for phoenix and phoenix_live_view * fix: fix wss connect by adding check_origin config * fix: fix markerIcon size on mobile sizes by adding iconSize and iconAnchor * feat: fallback to longpoll in live socket if websocket has issues * feat: add _header and _footer shared templates for app and live views
- Loading branch information
Showing
37 changed files
with
624 additions
and
285 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
webpack.config.js | ||
src/ReactPhoenix.js | ||
src/LiveReactPhoenix.js | ||
src/socket.js |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import React from "react" | ||
import ReactDOM from "react-dom" | ||
|
||
const render = function ( | ||
el, | ||
target, | ||
componentClass, | ||
additionalProps = {}, | ||
previousProps = {} | ||
) { | ||
let props = el.dataset.liveReactProps | ||
? JSON.parse(el.dataset.liveReactProps) | ||
: {} | ||
if (el.dataset.liveReactMerge) { | ||
props = { ...previousProps, ...props, ...additionalProps } | ||
} else { | ||
props = { ...props, ...additionalProps } | ||
} | ||
const reactElement = React.createElement(componentClass, props) | ||
ReactDOM.render(reactElement, target) | ||
return props | ||
} | ||
|
||
const initLiveReactElement = function (el, additionalProps) { | ||
const target = el.nextElementSibling | ||
const componentClass = Array.prototype.reduce.call( | ||
el.dataset.liveReactClass.split("."), | ||
(acc, el) => { | ||
return acc[el] | ||
}, | ||
window | ||
) | ||
render(el, target, componentClass, additionalProps) | ||
return { target: target, componentClass: componentClass } | ||
} | ||
|
||
const initLiveReact = function () { | ||
const elements = document.querySelectorAll("[data-live-react-class]") | ||
Array.prototype.forEach.call(elements, (el) => { | ||
initLiveReactElement(el) | ||
}) | ||
} | ||
|
||
const LiveReact = { | ||
mounted() { | ||
const { el } = this | ||
const pushEvent = this.pushEvent.bind(this) | ||
const pushEventTo = this.pushEventTo && this.pushEventTo.bind(this) | ||
const handleEvent = this.handleEvent && this.handleEvent.bind(this) | ||
const { target, componentClass } = initLiveReactElement(el, { pushEvent }) | ||
const props = render(el, target, componentClass, { | ||
pushEvent, | ||
pushEventTo, | ||
handleEvent, | ||
}) | ||
if (el.dataset.liveReactMerge) this.props = props | ||
Object.assign(this, { target, componentClass }) | ||
}, | ||
|
||
updated() { | ||
const { el, target, componentClass } = this | ||
const pushEvent = this.pushEvent.bind(this) | ||
const pushEventTo = this.pushEventTo && this.pushEventTo.bind(this) | ||
const handleEvent = this.handleEvent | ||
const previousProps = this.props | ||
const props = render( | ||
el, | ||
target, | ||
componentClass, | ||
{ pushEvent, pushEventTo }, | ||
previousProps | ||
) | ||
if (el.dataset.liveReactMerge) this.props = props | ||
}, | ||
|
||
destroyed() { | ||
const { target } = this | ||
ReactDOM.unmountComponentAtNode(target) | ||
}, | ||
} | ||
|
||
export { LiveReact as default, initLiveReact, initLiveReactElement } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,51 @@ | ||
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons. | ||
import "phoenix_html" | ||
import LiveReact from "./LiveReactPhoenix" | ||
// Establish Phoenix Socket and LiveView configuration. | ||
import { Socket } from "phoenix" | ||
import { LiveSocket } from "phoenix_live_view" | ||
|
||
import ReactPhoenix from "./ReactPhoenix" | ||
import DisruptionCalendar from "./components/DisruptionCalendar" | ||
import DisruptionForm from "./components/DisruptionForm" | ||
import ShapeViewMap from "./components/ShapeViewMap" | ||
import StopViewMap from "./components/StopViewMap" | ||
|
||
declare global { | ||
interface Window { | ||
liveSocket: LiveSocket | ||
Components: { | ||
[name: string]: (props: any) => JSX.Element | ||
} | ||
} | ||
} | ||
|
||
window.Components = { DisruptionCalendar, DisruptionForm, ShapeViewMap } | ||
// https://github.com/fidr/phoenix_live_react | ||
const hooks = { LiveReact } | ||
|
||
const csrfToken = document | ||
.querySelector("meta[name='csrf-token']")! | ||
.getAttribute("content") | ||
const liveSocket = new LiveSocket("/live", Socket, { | ||
hooks, | ||
longPollFallbackMs: location.host.startsWith("localhost") ? undefined : 2500, | ||
params: { _csrf_token: csrfToken }, | ||
}) | ||
|
||
// connect if there are any LiveViews on the page | ||
liveSocket.connect() | ||
|
||
// expose liveSocket on window for web console debug logs and latency simulation: | ||
// >> liveSocket.enableDebug() | ||
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session | ||
// >> liveSocket.disableLatencySim() | ||
window.liveSocket = liveSocket | ||
|
||
window.Components = { | ||
DisruptionCalendar, | ||
DisruptionForm, | ||
ShapeViewMap, | ||
StopViewMap, | ||
} | ||
|
||
ReactPhoenix.init() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import React from "react" | ||
import { LatLngExpression, icon } from "leaflet" | ||
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet" | ||
|
||
type Stop = { | ||
stop_name: string | ||
stop_desc: string | ||
stop_lat: number | ||
stop_lon: number | ||
} | ||
|
||
const defaultCenter: LatLngExpression = [42.360718, -71.05891] | ||
|
||
const markerIcon = icon({ | ||
iconUrl: "/images/marker-icon.png", | ||
iconRetinaUrl: "/images/marker-icon-2x.png", | ||
shadowUrl: "/images/marker-shadow.png", | ||
iconSize: [25, 41], | ||
iconAnchor: [12, 41], | ||
}) | ||
|
||
const StopViewMap = ({ stop }: { stop?: Stop }) => { | ||
return ( | ||
<MapContainer | ||
data-testid="stop-view-map-container" | ||
style={{ height: "800px" }} | ||
center={defaultCenter} | ||
zoom={13} | ||
scrollWheelZoom={true} | ||
> | ||
<TileLayer | ||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | ||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" | ||
/> | ||
{stop && stop.stop_lat && stop.stop_lon && ( | ||
<Marker position={[stop.stop_lat, stop.stop_lon]} icon={markerIcon}> | ||
<Popup>{stop.stop_name}</Popup> | ||
</Marker> | ||
)} | ||
</MapContainer> | ||
) | ||
} | ||
|
||
export default StopViewMap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from "react" | ||
import { render } from "@testing-library/react" | ||
import StopViewMap from "../../src/components/StopViewMap" | ||
|
||
describe("StopViewMap", () => { | ||
test("renders", () => { | ||
const { container } = render(<StopViewMap />) | ||
expect(container.getElementsByClassName("leaflet-map-pane").length).toBe(1) | ||
expect( | ||
container.getElementsByClassName("leaflet-control-container").length | ||
).toBe(1) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.