-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #211 from vgteam/demos
Demos for the controls
- Loading branch information
Showing
13 changed files
with
485 additions
and
16,503 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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
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 @@ | ||
/// DemoLibrary.js: page that shows a library of demos for different components included in this project. | ||
/// When developing a component, you can work on it on its demo page until it | ||
/// actually starts working, and then perfect automated tests and add it to the | ||
/// actual application. This is compatible with the dev server's hot reloading! | ||
/// | ||
/// To use this: | ||
/// 1. Make your component, Whatever.js | ||
/// 2. Make a demo file, Whatever.demo.js | ||
/// 3. In the demo file, import your component, import Demo from 'react-demo', | ||
/// and make the default export be a <Demo> component: | ||
/// | ||
/// import { Whatever } from './Whatever' | ||
/// import { Demo, props as P } from 'react-demo' | ||
/// export default (<Demo target={Whatever} />) | ||
/// | ||
/// 4. If the component needs props, pass a "props" attribute to the Demo | ||
/// component, with the props to use. See | ||
/// <https://github.com/rpominov/react-demo#available-demoprops>. | ||
/// 5. If the component needs two-way binding, use "advanced mode" | ||
/// <https://github.com/rpominov/react-demo#advanced-mode>. Make the Demo | ||
/// tag have a body which is a function that takes "props" and "update". | ||
/// Return your component rendered with the "props", and use "update" as if | ||
/// it were setState to update the props. | ||
/// | ||
/// For an example, see RegionInput.demo.js | ||
/// | ||
/// To see your demos, run `npm run start`, and go to: | ||
/// | ||
/// http://127.0.0.1:3001/demo | ||
/// | ||
/// (Assuming this component is mounted there in the React router.) | ||
|
||
import Library from 'react-demo-library' | ||
import { SafeLink } from "./SafeLink" | ||
|
||
// To auto-magically pick up demos, we use this magic to tell Webpack what we | ||
// want it to grab (*.demo.js, recursively), which it can work out at bundle | ||
// time. See | ||
// <https://webpack.js.org/guides/dependency-management/#requirecontext>. | ||
// Can't use constandt here, arguments *MUST* be literals for the magic to | ||
// work. | ||
const getFromContext = require.context('.', true, /\.demo\.js$/) | ||
|
||
// Each demo gets an object in this array with fields: | ||
// location: array of path components to mount at, after a hashbang | ||
// demo: React element for the demo itself, a react-demo Demo component | ||
// description: text about the demo, if any | ||
// importPath: hint about where to find the component to use it | ||
// fullWidth: boolean, true if we want to hide the demo picker | ||
// files: array of name and content objects to show along with the demo. | ||
// | ||
// Really we just need location and demo set. | ||
let demoList = [] | ||
|
||
for (let moduleName of getFromContext.keys()) { | ||
// Load all the demos available. | ||
|
||
// Work out what import this should be a demo for (drop the whole extension) | ||
let componentFile = moduleName.replace(/\.demo\.js$/, '') | ||
// Work out what this should be a demo for (drop './' and extension and split | ||
// path segments). | ||
// Last one will be the component name. | ||
let componentPathSegments = componentFile.replace(/^\.\//, '').split('/') | ||
|
||
// We need to fetch out the default export manually by its magic name. See | ||
// <https://stackoverflow.com/a/33705077> | ||
demoList.push({location: componentPathSegments, importPath: componentFile, demo: getFromContext(moduleName).default}) | ||
} | ||
|
||
export const DemoLibrary = () => { | ||
return ( | ||
<> | ||
{ | ||
// Because the demo UI does a bunch of full-browser-size stuff we have to float our back link over it | ||
} | ||
<div style={{position: "absolute", left: "0.5em", bottom: "0.5em", zIndex: 1001}}> | ||
<SafeLink to="/">Back to Tube Map</SafeLink> | ||
</div> | ||
<Library demos={demoList}/> | ||
</> | ||
) | ||
} |
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 @@ | ||
/// Footer.js: main page footer component. Includes project page links and demo link. | ||
|
||
import { Container, Row, Col, Navbar, Nav, NavItem, NavLink } from "reactstrap" | ||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" | ||
import { faGithub } from "@fortawesome/free-brands-svg-icons" | ||
import { faCode, faDna } from "@fortawesome/free-solid-svg-icons" | ||
|
||
import SafeLink from "./SafeLink" | ||
|
||
import PACKAGE from "../../package.json" | ||
|
||
|
||
export const Footer = () => { | ||
return ( | ||
<Container tag="footer" fluid={true} style={{marginTop: "1em"}}> | ||
<Row className="bg-light"> | ||
<Col lg={{offset: 2, size: 8}}> | ||
<Navbar> | ||
<Nav className="mr-auto"> | ||
<NavItem> | ||
<NavLink target="_blank" href="https://github.com/vgteam/sequenceTubeMap"><FontAwesomeIcon icon={faGithub} size="md" /> Github</NavLink> | ||
</NavItem> | ||
<NavItem> | ||
<NavLink target="_blank" href="https://genomics.ucsc.edu/"><FontAwesomeIcon icon={faDna} size="md" /> UCSC GI</NavLink> | ||
</NavItem> | ||
</Nav> | ||
<Nav> | ||
<NavItem> | ||
{PACKAGE.name} v{PACKAGE.version} | ||
</NavItem> | ||
</Nav> | ||
<Nav> | ||
<NavItem> | ||
<SafeLink to="/demo" title="Component Demos" style={{textDecoration: "none"}}><NavLink><FontAwesomeIcon icon={faCode} size="md" /> Component Demos</NavLink></SafeLink> | ||
</NavItem> | ||
</Nav> | ||
</Navbar> | ||
</Col> | ||
</Row> | ||
</Container> | ||
) | ||
} | ||
|
||
export default Footer |
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,30 @@ | ||
import Demo, {props as P} from 'react-demo' | ||
// See https://github.com/rpominov/react-demo for how to make a demo | ||
|
||
import RegionInput from "./RegionInput"; | ||
|
||
// We want to two-way-bind the demo region prop so we use advanced mode and pass the render function. | ||
export default (<Demo | ||
props={{ | ||
region: P.string('pathy:1-100'), | ||
regionInfo: P.json({ | ||
chr: ['chr600'], | ||
start: [10], | ||
end: [90], | ||
desc: ['Something cool'] | ||
}), | ||
pathNames: P.json(["pathy", "anotherPath", "node", "chr600"]) | ||
}} | ||
> | ||
{ | ||
(props, update) => { | ||
// We need to render the component under test using the props in props, and | ||
// call update when the component wants to adjust the props. | ||
return <RegionInput {...props} handleRegionChange={(newRegion) => { | ||
// When region is changed by the component, update the demo's region state | ||
update({region: newRegion}) | ||
}}/> | ||
} | ||
} | ||
</Demo>) | ||
|
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 |
---|---|---|
|
@@ -81,3 +81,5 @@ RegionInput.propTypes = { | |
start: PropTypes.array, | ||
}), | ||
}; | ||
|
||
export default RegionInput; |
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,25 @@ | ||
/// SafeLink.js: React Router-compatible Link component that doesn't explode if | ||
/// not used inside a React Router. | ||
|
||
import { Link, useInRouterContext } from "react-router-dom" | ||
|
||
export const SafeLink = ({children, ...props}) => { | ||
// Find out if we are in a router | ||
let insideRouter = useInRouterContext() | ||
if (insideRouter) { | ||
// We can use Link | ||
return ( | ||
<Link {...props}>{children}</Link> | ||
) | ||
} else { | ||
// We can't use Link | ||
// Also try to fix to -> href | ||
let {to, href, ...otherProps} = props | ||
let fixedProps = {href: href || to, ...otherProps} | ||
return ( | ||
<a {...fixedProps}>{children}</a> | ||
) | ||
} | ||
} | ||
|
||
export default SafeLink |
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,28 @@ | ||
import Demo, {props as P} from 'react-demo' | ||
// See https://github.com/rpominov/react-demo for how to make a demo | ||
|
||
import SelectionDropdown from "./SelectionDropdown"; | ||
|
||
// We want to two-way-bind the demo region prop so we use advanced mode and pass the render function. | ||
export default (<Demo | ||
props={{ | ||
id: P.string('theDropdown'), | ||
inputId: P.string('theTextBox'), | ||
className: P.string('someCSSClass'), | ||
value: P.string('one thing'), | ||
options: P.json(['one thing', 'another thing', 'yet a third thing']), | ||
}} | ||
> | ||
{ | ||
(props, update) => { | ||
// We need to render the component under test using the props in props, and | ||
// call update when the component wants to adjust the props. | ||
return <SelectionDropdown {...props} onChange={(fakeEvent) => { | ||
// Bind new value back up to value. | ||
// Remember: we get a fake event object with a "target" that has an "id" and a "value" | ||
update({value: fakeEvent.target.value}) | ||
}}/> | ||
} | ||
} | ||
</Demo>) | ||
|
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 |
---|---|---|
@@ -1,6 +1,27 @@ | ||
import React from "react"; | ||
import ReactDOM from "react-dom"; | ||
import { BrowserRouter, Routes, Route } from "react-router-dom"; | ||
import "bootstrap/dist/css/bootstrap.css"; | ||
import App from "./App"; | ||
import { DemoLibrary } from "./components/DemoLibrary"; | ||
|
||
ReactDOM.render(<App />, document.getElementById("root")); | ||
|
||
ReactDOM.render(( | ||
|
||
<BrowserRouter> | ||
<Routes> | ||
<Route path="/"> | ||
{ | ||
// Main application renders at the root | ||
} | ||
<Route index element={<App />} /> | ||
{ | ||
// Demos for custom controls show up at /demo | ||
// Each demo gets a nice hashbang URL. | ||
} | ||
<Route path="demo" element={<DemoLibrary />} /> | ||
</Route> | ||
</Routes> | ||
</BrowserRouter> | ||
|
||
), document.getElementById("root")); |