Skip to content

Commit

Permalink
feat(sync): add sync (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
maximilianoforlenza authored and navarroaxel committed Jan 27, 2018
1 parent 9d2ca1f commit db0ac9d
Show file tree
Hide file tree
Showing 24 changed files with 658 additions and 20 deletions.
5 changes: 5 additions & 0 deletions actions/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@indec/react-native-survey-commons/actions",
"private": true,
"main": "../src/actions/index.js"
}
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"dependencies": {},
"devDependencies": {
"@commitlint/cli": "^6.0.2",
"@indec/react-native-commons": "^0.1.5",
"@indec/heimdall": "^0.2.3",
"@indec/react-native-commons": "^0.1.6",
"@indec/react-native-md-textinput": "^3.0.1",
"@indec/react-native-table": "^0.1.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.2",
Expand All @@ -26,10 +28,13 @@
"husky": "^0.14.3",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"react-native": "^0.52.2"
"react-native": "^0.52.2",
"react-native-elements": "^0.19.0",
"react-redux": "^5.0.6",
"redux-saga": "^0.16.0"
},
"peerDependencies": {
"@indec/react-native-commons": ">=0.1.5",
"@indec/react-native-commons": ">=0.1.6",
"@indec/react-native-table": ">=0.1.0",
"lodash": "^4.17.0",
"prop-types": "^15.5.10",
Expand Down
5 changes: 5 additions & 0 deletions reducers/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@indec/react-native-survey-commons/reducers",
"private": true,
"main": "../src/reducers/index.js"
}
5 changes: 5 additions & 0 deletions sagas/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@indec/react-native-survey-commons/sagas",
"private": true,
"main": "../src/sagas/index.js"
}
5 changes: 5 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {PING_REQUESTED, NETWORK_STATUS_REQUESTED} from './network';
import {SYNC_REQUESTED} from './sync';

export {PING_REQUESTED, NETWORK_STATUS_REQUESTED};
export {SYNC_REQUESTED};
30 changes: 30 additions & 0 deletions src/actions/network.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const NETWORK_STATUS_REQUESTED = 'NETWORK_STATUS_REQUESTED';
export const NETWORK_STATUS_SUCCEEDED = 'NETWORK_STATUS_SUCCEEDED';

export const requestNetworkStatus = () => ({
type: NETWORK_STATUS_REQUESTED
});

export const receiveNetworkStatus = isConnected => ({
type: NETWORK_STATUS_SUCCEEDED,
isConnected
});

export const PING_REQUESTED = 'PING_REQUESTED';
export const PING_SUCCEEDED = 'PING_SUCCEEDED';
export const PING_FAILED = 'PING_FAILED';

export const requestPing = endpoint => ({
type: PING_REQUESTED,
endpoint
});

export const receivePing = pong => ({
type: PING_SUCCEEDED,
pong
});

export const handleErrorPing = e => ({
type: PING_FAILED,
message: e.message
});
39 changes: 39 additions & 0 deletions src/actions/sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export const SYNC_CLEAR_STATUS = 'SYNC_CLEAR_STATUS';
export const SYNC_REQUESTED = 'SYNC_REQUESTED';
export const SYNC_DATA_SENT = 'SYNC_DATA_SENT';
export const SYNC_DATA_RECEIVED = 'SYNC_DATA_RECEIVED';
export const SYNC_SUCCEEDED = 'SYNC_SUCCEEDED';
export const SYNC_FAILED = 'SYNC_FAILED';
export const SYNC_CLEAR_DATA = 'SYNC_CLEAR_DATA';

export const cleanSyncStatus = () => ({
type: SYNC_CLEAR_STATUS
});

export const requestSync = endpoint => ({
type: SYNC_REQUESTED,
endpoint
});

export const syncClearData = () => ({
type: SYNC_CLEAR_DATA
});

export const sendSyncData = count => ({
type: SYNC_DATA_SENT,
count
});

export const receiveSyncData = () => ({
type: SYNC_DATA_RECEIVED
});

export const completeSync = surveys => ({
type: SYNC_SUCCEEDED,
surveys
});

export const handleErrorSync = err => ({
type: SYNC_FAILED,
err: err.message
});
49 changes: 49 additions & 0 deletions src/components/Sync/NetworkStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {Icon, Text} from 'react-native-elements';
import {getFontAwesome} from '@indec/react-native-commons';

import styles from './styles';

const getConnectionIcon = isConnected => {
const icon = isConnected ? getFontAwesome('check', 'green') : getFontAwesome('times', 'red');
return (<Icon {...icon} size={32}/>);
};

const getServerStatusIcon = (isPinging, pong) => {
let icon;
if (isPinging) {
icon = getFontAwesome('refresh');
} else if (pong) {
icon = getFontAwesome('check', 'green');
} else {
icon = getFontAwesome('times', 'red');
}
return (<Icon {...icon} size={32}/>);
};

const NetworkStatus = ({isConnected, isPinging, pong}) => (
<View style={styles.network}>
<View style={styles.networkConnection}>
<Text style={styles.networkText}>
Conexión a internet
</Text>
{getConnectionIcon(isConnected)}
</View>
<View style={styles.networkConnection}>
<Text style={styles.networkText}>
Servidor online
</Text>
{getServerStatusIcon(isPinging, pong)}
</View>
</View>
);

NetworkStatus.propTypes = {
isConnected: PropTypes.bool.isRequired,
isPinging: PropTypes.bool.isRequired,
pong: PropTypes.shape({}).isRequired
};

export default NetworkStatus;
68 changes: 68 additions & 0 deletions src/components/Sync/SyncStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {Icon, Text} from 'react-native-elements';
import {getFontAwesome} from '@indec/react-native-commons';

import {syncStatus as syncStatusEnum} from '../../constants';
import styles from './styles';

const getSyncStatus = syncStatus => {
switch (syncStatus) {
case syncStatusEnum.LOADING_DATA:
return (
<View style={styles.syncStatusRow}>
<Icon {...getFontAwesome('gear')} size={32}/>
<Text style={styles.syncStatusText}>Cargando datos...</Text>
<Icon {...getFontAwesome('gear')} size={32}/>
</View>
);
case syncStatusEnum.SENDING_DATA:
return (
<View style={styles.syncStatusRow}>
<Icon {...getFontAwesome('gear')} size={32}/>
<Text>Enviando datos...</Text>
<Icon {...getFontAwesome('gear')} size={32}/>
</View>
);
case syncStatusEnum.SAVING_DATA:
return (
<View style={styles.syncStatusRow}>
<Icon {...getFontAwesome('gear')} size={32}/>
<Text>Guardando datos...</Text>
<Icon {...getFontAwesome('gear')} size={32}/>
</View>
);
case syncStatusEnum.COMPLETED:
return (
<View style={styles.syncStatusRow}>
<Icon {...getFontAwesome('check')} size={32}/>
<Text>Sincronizado</Text>
<Icon {...getFontAwesome('check')} size={32}/>
</View>
);
case syncStatusEnum.HAS_ERROR:
return (
<View style={styles.syncStatusRow}>
<Icon {...getFontAwesome('times')} size={32}/>
<Text>No sincronizado</Text>
<Icon {...getFontAwesome('times')} size={32}/>
</View>
);
case syncStatusEnum.NOT_STARTED:
default:
return null;
}
};

const SyncStatus = ({syncStatus}) => (
<Fragment>
{getSyncStatus(syncStatus)}
</Fragment>
);

SyncStatus.propTypes = {
syncStatus: PropTypes.string.isRequired
};

export default SyncStatus;
108 changes: 108 additions & 0 deletions src/components/Sync/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {View} from 'react-native';
import {Text} from 'react-native-elements';
import {Button, Col, getFontAwesome, Grid} from '@indec/react-native-commons';

import NetworkStatus from './NetworkStatus';
import SyncStatus from './SyncStatus';
import {requestNetworkStatus, requestPing} from '../../actions/network';
import {cleanSyncStatus, requestSync} from '../../actions/sync';

import styles from './styles';

class Sync extends Component {
static propTypes = {
cleanSyncStatus: PropTypes.func.isRequired,
requestPing: PropTypes.func.isRequired,
requestNetworkStatus: PropTypes.func.isRequired,
requestSync: PropTypes.func.isRequired,
isPinging: PropTypes.bool,
isConnected: PropTypes.bool.isRequired,
surveys: PropTypes.arrayOf(PropTypes.shape({})),
endpoint: PropTypes.string.isRequired,
pong: PropTypes.shape({}),
syncStatus: PropTypes.string.isRequired
};

static defaultProps = {
isPinging: false,
surveys: 0,
pong: {}
};

constructor(props) {
super(props);
this.state = {
syncPressed: false
};
}

componentDidMount() {
const {endpoint} = this.props;
this.props.requestPing(endpoint);
this.props.requestNetworkStatus();
this.props.cleanSyncStatus();
}

handleSync() {
const {endpoint} = this.props;
this.setState({syncPressed: true});
this.props.requestSync(endpoint);
}

render() {
const {
isConnected,
isPinging,
pong,
surveys,
syncStatus
} = this.props;
return (
<Grid>
<Col>
<View style={styles.syncRow}>
<NetworkStatus isConnected={isConnected} isPinging={isPinging} pong={pong}/>
</View>
<View style={styles.syncRow}>
<Text style={styles.surveyCount}>
{surveys.length} encuesta(s) para enviar.
</Text>
</View>
<View style={styles.syncRow}>
<SyncStatus syncStatus={syncStatus}/>
</View>
<View style={{marginLeft: 15, marginRight: 15}}>
<Button
disabled={this.state.syncPressed}
large
primary
backgroundColor="#4fb3bf"
icon={getFontAwesome('refresh')}
title="Sincronizar"
onPress={() => this.handleSync()}
/>
</View>
</Col>
</Grid>
);
}
}

export default connect(
state => ({
isPinging: state.network.isPinging,
pong: state.network.pong,
isConnected: state.network.isConnected,
syncStatus: state.sync.status,
surveys: state.sync.surveys
}),
dispatch => ({
cleanSyncStatus: () => dispatch(cleanSyncStatus()),
requestPing: endpoint => dispatch(requestPing(endpoint)),
requestNetworkStatus: () => dispatch(requestNetworkStatus()),
requestSync: endpoint => dispatch(requestSync(endpoint))
})
)(Sync);
48 changes: 48 additions & 0 deletions src/components/Sync/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {StyleSheet} from 'react-native';

export default StyleSheet.create({
tableHeader: {
paddingTop: 20,
paddingBottom: 20,
flexDirection: 'row',
justifyContent: 'space-around'
},
tableRow: {
marginLeft: 15,
paddingTop: 10,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
syncRow: {
padding: 20,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
surveyCount: {
fontSize: 30
},
syncStatusRow: {
padding: 20,
flexDirection: 'row',
justifyContent: 'space-around'
},
syncStatusText: {
padding: 8
},
network: {
flex: 1,
padding: 20,
flexDirection: 'row',
justifyContent: 'space-between'
},
networkConnection: {
flexDirection: 'row',
padding: 10,
backgroundColor: '#e8e8e8'
},
networkText: {
padding: 6
}
});
Loading

0 comments on commit db0ac9d

Please sign in to comment.