Add decentralized services
This commit is contained in:
parent
d2422d5036
commit
c7d0adf780
19 changed files with 346 additions and 19 deletions
13
frontend/package-lock.json
generated
Normal file
13
frontend/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "eva-frontend",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"classnames": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,26 +3,27 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^3.9.3",
|
||||
"@material-ui/icons": "^3.0.2",
|
||||
"leaflet": "^1.4.0",
|
||||
"@material-ui/core": "^4.9.1",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"classnames": "^2.2.6",
|
||||
"leaflet": "^1.6.0",
|
||||
"moment": "^2.24.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-leaflet": "^2.2.1",
|
||||
"react-redux": "^6.0.1",
|
||||
"react-router-dom": "^5.0.0",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-leaflet": "^2.6.1",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-tap-event-plugin": "^3.0.3",
|
||||
"react-virtualized": "^9.21.0",
|
||||
"redux": "^4.0.1",
|
||||
"react-virtualized": "^9.21.2",
|
||||
"redux": "^4.0.5",
|
||||
"redux-actions": "^2.6.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rrule": "^2.6.0",
|
||||
"superagent": "^5.0.2"
|
||||
"rrule": "^2.6.4",
|
||||
"superagent": "^5.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-scripts": "2.1.8"
|
||||
"react-scripts": "3.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { MuiThemeProvider } from '@material-ui/core/styles';
|
|||
import theme from './style/theme';
|
||||
import store from './redux/store';
|
||||
import IndexContainer from './views/Index';
|
||||
import ServicesList from "./views/ServicesList";
|
||||
import SpaceList from './views/SpaceList';
|
||||
import UrlListView from './views/UrlListView';
|
||||
import layout from './layout';
|
||||
|
|
@ -19,6 +20,7 @@ const App = () => (
|
|||
<Router>
|
||||
<div>
|
||||
<Route path="/list" component={layout(<SpaceList />)} />
|
||||
<Route path="/services" component={layout(<ServicesList />)} />
|
||||
<Route path="/urls" component={layout(<UrlListView />)} />
|
||||
<Route exact path="/" component={layout(<IndexContainer />)} />
|
||||
</div>
|
||||
|
|
@ -27,4 +29,4 @@ const App = () => (
|
|||
</MuiThemeProvider>
|
||||
);
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class Map extends React.Component {
|
|||
style={{ width: '100vw', height: 'calc(50vh - 60px)', margin: 0, padding: 0, maxWidth: '100%' }}
|
||||
>
|
||||
<TileLayer
|
||||
url="https://spaceapi.ccc.de/map/tiles/{z}/{x}/{y}.png"
|
||||
url="/map/tiles/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{this.props.spacedata.items.map(
|
||||
spacedata => (
|
||||
|
|
|
|||
100
frontend/src/components/ServiceList.jsx
Normal file
100
frontend/src/components/ServiceList.jsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import React from 'react';
|
||||
import Table from '@material-ui/core/Table';
|
||||
import TableBody from '@material-ui/core/TableBody';
|
||||
import TableRow from '@material-ui/core/TableRow';
|
||||
import TableCell from '@material-ui/core/TableCell';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { serviceStruct } from '../redux/modules/services';
|
||||
import {withStyles} from "@material-ui/core";
|
||||
|
||||
const styles = theme => ({
|
||||
table: {
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
border: 0,
|
||||
},
|
||||
flexContainer: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
tableRow: {},
|
||||
tableRowHover: {
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.grey[600],
|
||||
},
|
||||
},
|
||||
tableRowEven: {
|
||||
backgroundColor: theme.palette.grey[700],
|
||||
},
|
||||
tableCell: {
|
||||
flex: 1,
|
||||
color: '#fff',
|
||||
border: 0,
|
||||
},
|
||||
noClick: {
|
||||
cursor: 'initial',
|
||||
},
|
||||
});
|
||||
|
||||
const formatType = type => {
|
||||
if (type.indexOf("[") === 0) {
|
||||
return type.substring(type.indexOf(" ") + 1, type.length - 1);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
export class ServiceList extends React.Component {
|
||||
static propTypes = {
|
||||
fetchServices: PropTypes.func.isRequired,
|
||||
services: serviceStruct,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
services: {
|
||||
items: [],
|
||||
},
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchServices();
|
||||
}
|
||||
|
||||
render() {
|
||||
const items = this.props.services.items.sort(
|
||||
(a, b) => formatType(a.type).toUpperCase().localeCompare(formatType(b.type).toUpperCase())
|
||||
);
|
||||
return (
|
||||
<div style={{ paddingTop:'60px' }}>
|
||||
<Table>
|
||||
<TableBody>
|
||||
{items
|
||||
.map((service, index) => (
|
||||
<TableRow key={service.name} className={classNames({
|
||||
[this.props.classes.tableRowEven]: index % 2
|
||||
})} >
|
||||
<TableCell style={{ color: '#fff', border: 0 }}>
|
||||
{service.name}
|
||||
</TableCell>
|
||||
<TableCell style={{ color: '#fff', border: 0 }}>
|
||||
{formatType(service.type)}
|
||||
</TableCell>
|
||||
<TableCell style={{ color: '#fff', border: 0 }}>
|
||||
<a
|
||||
href={service.url}
|
||||
style={{ textDecoration: 'none', color: 'white' }}
|
||||
>
|
||||
{service.url}
|
||||
</a>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(ServiceList);
|
||||
|
|
@ -71,6 +71,12 @@ class MyToolbar extends React.Component {
|
|||
>
|
||||
Spaces
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => window.location.href = '/services'}
|
||||
containerElement={<Link to="/services" />}
|
||||
>
|
||||
Services
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => window.location.href = 'http://ccc.de/de/imprint'}
|
||||
>
|
||||
|
|
|
|||
13
frontend/src/containers/ServiceList.jsx
Normal file
13
frontend/src/containers/ServiceList.jsx
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { actions as serviceActions } from '../redux/modules/services';
|
||||
import Component from '../components/ServiceList';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
services: state.services,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
...serviceActions,
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Component);
|
||||
44
frontend/src/redux/modules/services.js
Normal file
44
frontend/src/redux/modules/services.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import request from 'superagent';
|
||||
import { createAction, handleActions } from 'redux-actions';
|
||||
import config from '../../api/config';
|
||||
|
||||
export const serviceElementStruct = PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
url: PropTypes.string.isRequired,
|
||||
});
|
||||
export const itemsStruct = PropTypes.arrayOf(serviceElementStruct);
|
||||
export const serviceStruct = PropTypes.shape({
|
||||
items: itemsStruct,
|
||||
});
|
||||
|
||||
const SERVICES_FETCHED = 'SERVICES_FETCHED';
|
||||
|
||||
export const fetched = createAction(SERVICES_FETCHED, result => result);
|
||||
|
||||
export const fetchServices = () => (dispatch) => {
|
||||
request
|
||||
.get(`${config.api.url}/services`)
|
||||
.set('Content-Type', 'application/json')
|
||||
.end(
|
||||
(err, res) => {
|
||||
if (!err) {
|
||||
dispatch(fetched(res.body));
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
fetchServices,
|
||||
};
|
||||
|
||||
export default handleActions({
|
||||
[SERVICES_FETCHED]: (state, { payload }) => (
|
||||
{
|
||||
...state,
|
||||
items: payload,
|
||||
}
|
||||
),
|
||||
}, { items: [] });
|
||||
|
|
@ -2,9 +2,11 @@ import { combineReducers } from 'redux';
|
|||
import spacedataReducer from './modules/spacedata';
|
||||
import calendarsReducer from './modules/calendar';
|
||||
import spaceUrlsReducer from './modules/spaceurl';
|
||||
import servicesReducer from './modules/services';
|
||||
|
||||
export default combineReducers({
|
||||
spacedata: spacedataReducer,
|
||||
calendars: calendarsReducer,
|
||||
spaceurls: spaceUrlsReducer,
|
||||
services: servicesReducer,
|
||||
});
|
||||
|
|
|
|||
10
frontend/src/views/ServicesList.jsx
Normal file
10
frontend/src/views/ServicesList.jsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react';
|
||||
import ServiceList from '../containers/ServiceList';
|
||||
|
||||
const ServiceListView = () => (
|
||||
<div>
|
||||
<ServiceList />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ServiceListView;
|
||||
Loading…
Add table
Add a link
Reference in a new issue