Display results nicer
This commit is contained in:
parent
bedcf95596
commit
3a5dfdd115
@ -31,7 +31,22 @@ div.item {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
#results {
|
||||||
width: 100%;
|
> ul {
|
||||||
overflow: scroll;
|
> li {
|
||||||
|
padding: 5px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
> ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&.expand {
|
||||||
|
> ul {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
client/actions/results.js
Normal file
51
client/actions/results.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { pick } from 'lowline';
|
||||||
|
|
||||||
|
export const DELETE_RESULT = 'DELETE_RESULT';
|
||||||
|
|
||||||
|
const baseUrl = '/api/results';
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
accept: 'application/json',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FETCH_RESULTS = 'FETCH_RESULTS';
|
||||||
|
|
||||||
|
// query can be a query string (without ?, ie not a search string)
|
||||||
|
export function fetchResults(query = {}) {
|
||||||
|
query = typeof query === 'string' ? query : qs.stringify(query);
|
||||||
|
|
||||||
|
return (dispatch) => {
|
||||||
|
fetch(`${baseUrl}${query ? `?${query}` : ''}`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers,
|
||||||
|
}).then((res) => res.json())
|
||||||
|
.then((json) => {
|
||||||
|
const actions = [receiveResults(json.results || [])];
|
||||||
|
|
||||||
|
if (json.perPage) {
|
||||||
|
actions.push(setPagination(pick(json, 'perPage', 'totalCount')));
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(batchActions(actions));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RECEIVE_RESULTS = 'RECEIVE_RESULTS';
|
||||||
|
|
||||||
|
export function receiveResults(json) {
|
||||||
|
return {
|
||||||
|
type: RECEIVE_RESULTS,
|
||||||
|
payload: json,
|
||||||
|
receivedAt: Date.now(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const REMOVE_RESULTS = 'REMOVE_RESULTS';
|
||||||
|
|
||||||
|
export function removeResults() {
|
||||||
|
return {
|
||||||
|
type: REMOVE_RESULTS,
|
||||||
|
};
|
||||||
|
}
|
||||||
13
client/components/Link.jsx
Normal file
13
client/components/Link.jsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
|
||||||
|
import formatTime from '../util/formatTime';
|
||||||
|
|
||||||
|
export default (props) => (
|
||||||
|
<li>
|
||||||
|
<span class="line">{props.Line.Name}</span>
|
||||||
|
<ul>
|
||||||
|
<li>{formatTime(props.DepDateTime)} {props.From.Name}</li>
|
||||||
|
<li>{formatTime(props.ArrDateTime)} {props.To.Name}</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
25
client/components/Result.jsx
Normal file
25
client/components/Result.jsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
|
||||||
|
import Link from './Link';
|
||||||
|
|
||||||
|
import formatTime from '../util/formatTime';
|
||||||
|
|
||||||
|
export default class Result extends Component {
|
||||||
|
toggle() {
|
||||||
|
console.log('toggle');
|
||||||
|
this.setState({
|
||||||
|
expand: !this.state.expand,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render(props, { expand }) {
|
||||||
|
return (
|
||||||
|
<li className={{ expand }} onClick={() => this.toggle()}>
|
||||||
|
{formatTime(props.DepDateTime)} - {formatTime(props.ArrDateTime)}
|
||||||
|
<ul>
|
||||||
|
{props.RouteLinks.RouteLink.map((link, i) => <Link key={i} {...link} />)}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
client/components/ResultList.jsx
Normal file
24
client/components/ResultList.jsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
|
||||||
|
import Result from './Result';
|
||||||
|
import store from '../store';
|
||||||
|
|
||||||
|
export default class ResultList extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.unsubscribe = store.subscribe(() => this.forceUpdate());
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { results } = store.getState();
|
||||||
|
console.log(results);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>{results && results.map((result, i) => <Result key={i} {...result} />)}</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,7 +1,11 @@
|
|||||||
import { $, $$ } from 'dollr';
|
import { $, $$ } from 'dollr';
|
||||||
import dragula from 'dragula';
|
import dragula from 'dragula';
|
||||||
|
|
||||||
|
import { h, render } from 'preact';
|
||||||
|
import ResultList from './components/ResultList';
|
||||||
|
|
||||||
|
import store from './store';
|
||||||
|
import { receiveResults } from './actions/results';
|
||||||
const result = $('pre');
|
const result = $('pre');
|
||||||
const containers = $$('.location');
|
const containers = $$('.location');
|
||||||
|
|
||||||
@ -34,7 +38,8 @@ drake.on('drop', (el, target, source) => {
|
|||||||
return res.json();
|
return res.json();
|
||||||
}).then((json) => {
|
}).then((json) => {
|
||||||
console.log(json);
|
console.log(json);
|
||||||
result.textContent = JSON.stringify(json, null, ' ')
|
// result.textContent = JSON.stringify(json, null, ' ')
|
||||||
|
store.dispatch(receiveResults(json));
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log('error');
|
console.log('error');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@ -46,10 +51,6 @@ function prevent(e) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.addEventListener('touchmove', (e) => {
|
|
||||||
if (e.target.classList.contains('item')) e.preventDefault();
|
|
||||||
}, { passive: false });
|
|
||||||
|
|
||||||
drake.on('over', (el, target, source) => {
|
drake.on('over', (el, target, source) => {
|
||||||
if (target !== source) {
|
if (target !== source) {
|
||||||
target.classList.add('over');
|
target.classList.add('over');
|
||||||
@ -62,3 +63,8 @@ drake.on('out', (el, target, source) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ResultList />,
|
||||||
|
$('#results')
|
||||||
|
);
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export default ({ articleUrl, protocol, hostname, websocketsPort, INITIAL_STATE,
|
|||||||
<div data-location="brother" class="location l03"><div data-location="brother" class="item"><span>Brother</span></div></div>
|
<div data-location="brother" class="location l03"><div data-location="brother" class="item"><span>Brother</span></div></div>
|
||||||
<div data-location="therapist" class="location l04"><div data-location="therapist" class="item"><span>The Rapist</span></div></div>
|
<div data-location="therapist" class="location l04"><div data-location="therapist" class="item"><span>The Rapist</span></div></div>
|
||||||
</div>
|
</div>
|
||||||
<pre></pre>
|
<div id="results"></div>
|
||||||
<script src={"/js/app" + (js ? js.suffix : '') + '.js'} />
|
<script src={"/js/app" + (js ? js.suffix : '') + '.js'} />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
16
client/reducers/results.js
Normal file
16
client/reducers/results.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {
|
||||||
|
RECEIVE_RESULTS,
|
||||||
|
REMOVE_RESULTS,
|
||||||
|
} from '../actions/results';
|
||||||
|
|
||||||
|
export default (state = null, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case RECEIVE_RESULTS:
|
||||||
|
return action.payload || [];
|
||||||
|
case REMOVE_RESULTS:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
7
client/reducers/root.js
Normal file
7
client/reducers/root.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
|
import results from './results';
|
||||||
|
|
||||||
|
export default combineReducers({
|
||||||
|
results,
|
||||||
|
});
|
||||||
15
client/store.js
Normal file
15
client/store.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import thunkMiddleware from 'redux-thunk';
|
||||||
|
import createLogger from 'redux-logger';
|
||||||
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
|
|
||||||
|
const loggerMiddleware = createLogger();
|
||||||
|
|
||||||
|
import rootReducer from './reducers/root';
|
||||||
|
|
||||||
|
export default createStore(
|
||||||
|
rootReducer,
|
||||||
|
applyMiddleware(
|
||||||
|
thunkMiddleware,
|
||||||
|
loggerMiddleware
|
||||||
|
)
|
||||||
|
);
|
||||||
3
client/util/formatTime.js
Normal file
3
client/util/formatTime.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default function formatDateTime(str) {
|
||||||
|
return str.split('T')[1].slice(0, -3);
|
||||||
|
}
|
||||||
@ -17,15 +17,22 @@
|
|||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
"cookie-parser": "^1.4.3",
|
"cookie-parser": "^1.4.3",
|
||||||
"dollr": "^0.1.2",
|
"dollr": "^0.1.2",
|
||||||
"dragula": "^3.7.2",
|
"dragula": "github:lohfu/dragula",
|
||||||
|
"easy-tz": "^0.1.1",
|
||||||
"express": "^4.14.1",
|
"express": "^4.14.1",
|
||||||
"express-session": "^1.15.1",
|
"express-session": "^1.15.1",
|
||||||
"jsx-node": "^0.2.2",
|
"jsx-node": "^0.2.2",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
|
"lowline": "^0.1.3",
|
||||||
"midwest": "github:thebitmill/midwest",
|
"midwest": "github:thebitmill/midwest",
|
||||||
"midwest-service-errors": "^0.2.0",
|
"midwest-service-errors": "^0.2.0",
|
||||||
"morgan": "^1.8.1",
|
"morgan": "^1.8.1",
|
||||||
"pg": "^6.1.2",
|
"pg": "^6.1.2",
|
||||||
|
"preact": "^7.2.0",
|
||||||
|
"react-dragula": "^1.1.17",
|
||||||
|
"redux": "^3.6.0",
|
||||||
|
"redux-logger": "^2.8.1",
|
||||||
|
"redux-thunk": "^2.2.0",
|
||||||
"require-dir": "^0.3.1",
|
"require-dir": "^0.3.1",
|
||||||
"superagent": "^3.5.0",
|
"superagent": "^3.5.0",
|
||||||
"useragent": "^2.1.12",
|
"useragent": "^2.1.12",
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
const format = require('easy-tz/cjs/format');
|
||||||
|
|
||||||
const request = require('superagent');
|
const request = require('superagent');
|
||||||
|
|
||||||
// import get from 'get-value';
|
// import get from 'get-value';
|
||||||
@ -50,15 +52,32 @@ function formatStation(json) {
|
|||||||
return `${encodeURIComponent(json.name)}|${json.id}|${types[json.type]}`
|
return `${encodeURIComponent(json.name)}|${json.id}|${types[json.type]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatTime(date) {
|
||||||
|
date = date || new Date();
|
||||||
|
|
||||||
|
return format(null, 'YYYY-MM-DD HH:mm', date);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
console.log(formatTime());
|
||||||
|
|
||||||
|
function formatLink(link) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatResult(result) {
|
||||||
|
return _.omit(result, 'Prices');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(new Date('2017-02-24T17:16:00'.split('T').join(' ')).toLocaleString());
|
||||||
|
|
||||||
const journeysPath = [ 'soap:Envelope', 'soap:Body', 'GetJourneyResponse', 'GetJourneyResult', 'Journeys', 'Journey']
|
const journeysPath = [ 'soap:Envelope', 'soap:Body', 'GetJourneyResponse', 'GetJourneyResult', 'Journeys', 'Journey']
|
||||||
// http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=malm%F6%20C|80000|0&selPointTo=landskrona|82000|0&LastStart=2017-02-23%2016:38
|
// http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=malm%F6%20C|80000|0&selPointTo=landskrona|82000|0&LastStart=2017-02-23%2016:38
|
||||||
router.post('/trip', (req, res, next) => {
|
router.post('/trip', (req, res, next) => {
|
||||||
request(`http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=${formatStation(stations[req.body.from])}&selPointTo=${formatStation(stations[req.body.to])}&LastStart=2017-02-23%2016:38`).then((response) =>{
|
request(`http://www.labs.skanetrafiken.se/v2.2/resultspage.asp?cmdaction=next&selPointFr=${formatStation(stations[req.body.from])}&selPointTo=${formatStation(stations[req.body.to])}&LastStart=${encodeURIComponent(formatTime(req.body.datetime))}`).then((response) =>{
|
||||||
const result = _.get(xml2json.toJson(response.text, { object: true }), journeysPath);
|
const result = _.get(xml2json.toJson(response.text, { object: true }), journeysPath);
|
||||||
|
|
||||||
result.forEach((obj) => {
|
result.forEach(formatResult);
|
||||||
delete obj.Prices
|
|
||||||
});
|
|
||||||
|
|
||||||
res.json(result);
|
res.json(result);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user