Commit 56682556 authored by Eugen Rochko's avatar Eugen Rochko

Add instance picker

parent b43b909d
......@@ -3,12 +3,18 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.16.2",
"gh-pages": "^0.12.0",
"react": "^15.5.3",
"react-custom-scrollbars": "^4.1.2",
"react-dom": "^15.5.3",
"react-motion": "^0.4.7",
"react-redux": "^5.0.5",
"react-router-dom": "^4.0.0",
"react-snapshot": "^1.1.0"
"react-snapshot": "^1.1.0",
"redux": "^3.7.1",
"redux-thunk": "^2.2.0",
"reselect": "^3.0.1"
},
"devDependencies": {
"node-sass": "^4.5.2",
......
......@@ -6,7 +6,7 @@ import {
} from 'react-router-dom';
import Features from './Features';
import Wizard from './Wizard';
import Wizard from './WizardContainer';
import githubLogo from './assets/github-logo.svg';
import mastodonLogo from './assets/mastodon-logo.svg';
......
import React from 'react';
import { fetchInstances } from './actions';
import WizardRow from './WizardRow';
import { Scrollbars } from 'react-custom-scrollbars';
const Wizard = () => (
<div>
Wizard
</div>
);
export default class Wizard extends React.Component {
export default Wizard;
componentDidMount () {
this.props.dispatch(fetchInstances());
}
render () {
const { instances } = this.props;
return (
<div className='wizard-page'>
<h2>Instance picker</h2>
<p>Each instance is a separate, independently owned gateway into the fediverse. You can talk to your friends regardless of which one you choose, but they have different moderation policies and interest groups.</p>
<div className='wizard'>
<div className='wizard-header'>
<div className='wizard-column'>Server</div>
<div className='wizard-column'>Stability</div>
<div className='wizard-column'>Population</div>
<div className='wizard-column'>Theme</div>
</div>
<Scrollbars className='wizard-content' style={{ height: 500 }}>
{instances.map(item =>
<WizardRow key={item._id} instance={item} />
)}
</Scrollbars>
</div>
<p>If you are interested in running your own instance &mdash; for your friends, family or organization &mdash; you can get started by reading the installation documentation. You only host your own users and the content that they subscribe to.</p>
<p><a href='https://github.com/tootsuite/documentation#running-mastodon' className='cta button alt'>Read the docs</a></p>
</div>
);
}
}
import Wizard from './Wizard';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
const getInstances = createSelector(
[state => state.instances],
instances => instances.filter(item => !item.dead && item.uptime > 0.70)
);
const mapStateToProps = state => ({
instances: getInstances(state),
});
export default connect(mapStateToProps)(Wizard);
import React from 'react';
const WizardRow = ({ instance }) => {
const theme = (instance.info && instance.info.theme) || 'General';
let stabilityColor, stabilityLabel,
populationColor, populationLabel;
if (instance.uptime > 0.98) {
stabilityLabel = 'Stable';
stabilityColor = 'green';
} else if (instance.uptime > 0.50) {
stabilityLabel = 'Intermittent'
stabilityColor = 'yellow';
} else {
stabilityLabel = 'Awful'
stabilityColor = 'red';
}
if (!instance.openRegistrations) {
populationLabel = 'Full';
populationColor = 'red';
} else if (instance.users > 20000) {
populationLabel = 'Medium';
populationColor = 'yellow';
} else {
populationLabel = 'New';
populationColor = 'green';
}
return (
<div className='wizard-row'>
<div className='wizard-column'>{instance.name}</div>
<div className='wizard-column'><span className={`indicator-text ${stabilityColor}`}><i className={`indicator ${stabilityColor}`} /> {stabilityLabel}</span></div>
<div className='wizard-column'><span className={`indicator-text ${populationColor}`}><i className={`indicator ${populationColor}`} /> {populationLabel}</span></div>
<div className='wizard-column'>{theme}</div>
</div>
);
};
export default WizardRow;
import axios from 'axios';
export const INSTANCES_FETCH_SUCCESS = 'INSTANCES_FETCH_SUCCESS';
export function fetchInstances() {
return (dispatch, getState) => {
if (getState().instances.length > 0) {
return;
}
axios.get('https://instances.mastodon.xyz/instances.json')
.then(response => dispatch(fetchInstancesSuccess(response.data)));
};
};
export function fetchInstancesSuccess(data) {
return {
type: INSTANCES_FETCH_SUCCESS,
data,
};
};
import React from 'react';
import { render } from 'react-snapshot';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
import App from './App';
import './index.css';
const store = createStore(reducer, applyMiddleware(thunk));
render(
<App />,
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
......@@ -5,3 +5,4 @@
@import 'scss/reset.scss';
@import 'scss/global.scss';
@import 'scss/App.scss';
@import 'scss/Wizard.scss';
import { INSTANCES_FETCH_SUCCESS } from './actions';
const initialState = {
instances: [],
};
export default function reducer(state = initialState, action) {
switch(action.type) {
case INSTANCES_FETCH_SUCCESS:
return { ...state, instances: action.data };
default:
return state;
}
};
@import './variables.scss';
.wizard-page {
max-width: 800px;
margin: 100px auto;
h2 {
font-family: 'Montserrat', sans-serif;
font-size: 21px;
margin-bottom: 20px;
color: $lighter;
}
p {
font-size: 16px;
line-height: 24px;
margin-bottom: 20px;
}
}
.wizard {
margin: 50px auto;
border: 1px solid darken($darkest, 4%);
background: lighten($darkest, 8%);
border-radius: 10px;
max-width: 800px;
.wizard-header {
display: flex;
border-bottom: 1px solid $darkest;
.wizard-column {
font-family: 'Montserrat', sans-serif;
font-weight: 500;
font-size: 14px;
color: $lighter;
border-right: 1px solid $darkest;
&:last-child {
border-right: 0;
}
}
}
.wizard-row {
display: flex;
font-size: 14px;
&:nth-child(even) {
background: lighten($darkest, 2%);
}
&:hover {
color: $lightest;
}
}
.wizard-column {
padding: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:nth-child(1n) {
width: 20%;
}
&:nth-child(2n), &:nth-child(3n) {
width: 17%;
}
&:nth-child(4n) {
width: 100% - 2*17% - 20%;
}
}
.wizard-content {
height: 500px;
overflow-y: hidden;
background: lighten($darkest, 4%);
color: $lighter;
.wizard-column {
cursor: pointer;
}
}
}
.indicator-text {
font-weight: 500;
.indicator {
margin-right: 5px;
}
&.green {
color: $success;
}
&.yellow {
color: #ca8f04;
}
&.red {
color: $error;
}
}
.indicator {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 14px;
&.green {
background: $success;
}
&.yellow {
background: #ca8f04;
}
&.red {
background: $error;
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment