Skip to content

Commit

Permalink
#10 totally rework list item layout (code cleanup still needed).
Browse files Browse the repository at this point in the history
  • Loading branch information
antonvasilenko committed Nov 6, 2016
1 parent 8599b94 commit cef0c4c
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 89 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"start": "node node_modules/react-native/local-cli/cli.js start",
"start:release": "node_modules/.bin/react-native run-android --variant=release",
"serve": "node_modules/.bin/react-native run-android",
"build": "cd android && ./gradlew assembleRelease",
"build": "cd android && gradlew assembleRelease",
"timesync:win": "adb shell date -s SET $(get-date -format MMddhhmm.ss)"
},
"dependencies": {
Expand All @@ -16,6 +16,7 @@
"react-native": "0.32.0",
"react-native-android-statusbar": "^0.1.3",
"react-native-material-design": "^0.3.7",
"react-native-material-design-styles": "^0.2.6",
"react-redux": "^4.4.5",
"redux": "^3.6.0",
"redux-logger": "^2.6.1",
Expand Down
4 changes: 2 additions & 2 deletions src/components/ListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ export default class List extends Component {
primaryColor: 'rgba(0,0,0,.87)',
};

setNativeProps(nativeProps) {
/* setNativeProps(nativeProps) {
this.refRoot.setNativeProps(nativeProps);
}
} */

/* eslint-disable */
render() {
Expand Down
169 changes: 116 additions & 53 deletions src/scenes/Services/BuildPlanRow.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,123 @@
import React, { PropTypes } from 'react';
import {
Icon,
} from 'react-native-material-design';
import ListItem from '../../components/ListItem';
import React, { Component, PropTypes } from 'react';
import { StyleSheet, View, Text, TouchableWithoutFeedback } from 'react-native';
import RowSensor from './RowSensor';

const getIcon = item => {
switch (item.icon) {
case 'good':
return { name: 'cloud-done', color: 'googleGreen500' };
case 'warning':
return { name: 'cloud-done', color: 'googleYellow500' };
case 'error':
return { name: 'error', color: 'googleRed500' };
default:
return { name: 'cloud', color: 'paperBlueGrey300' };
}
};
const styles = StyleSheet.create({
listContainer: {
flexDirection: 'row',
paddingLeft: 0,
paddingRight: 8,
paddingTop: 0,
alignItems: 'flex-start',
},
leftContainer: {
alignSelf: 'center',
flexDirection: 'column',
marginRight: 8,
alignItems: 'center',
width: 50,
top: 0,
},
leftIconText: {
alignSelf: 'stretch',
textAlign: 'center',
fontWeight: 'bold',
textShadowColor: 'cyan',
borderWidth: 1,
borderColor: 'black',
},
rightContainer: {
flex: 1,
alignSelf: 'stretch',
flexDirection: 'column',
justifyContent: 'center',
// backgroundColor: 'magenta',
},
primaryTextContainer: {
flex: 1,
paddingRight: 4,
},
primaryText: {
color: 'rgba(0,0,0,.87)',
fontSize: 20,
fontWeight: '400',
},
contentContainer: {
flex: 2,
flexDirection: 'row',
alignItems: 'center',
// borderWidth: 1,
// borderColor: 'black',
},
contentItem: {
marginHorizontal: 1,
},
noContent: {
flex: 2,
justifyContent: 'center',
},
});

const renderIcon = item => {
const icon = getIcon(item);
return (<Icon name={icon.name} color={icon.color} />);
};
export default class List extends Component {

const renderSummary = item => {
const parts = [];
if (item.latestResult) {
parts.push(`build-${item.latestResult.buildNumber}`);
}
return parts.join(' ');
};
static propTypes = {
primaryText: PropTypes.string,
leftIcon: PropTypes.element,
leftIconText: PropTypes.string,
onPress: PropTypes.func,
onLeftIconClicked: PropTypes.func,
items: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
build: PropTypes.any,
deployStatus: PropTypes.string,
prtgStatus: PropTypes.string,
})),
};

const renderDeploymentsData = item => {
const parts = [];
if (item.latestDeployment) {
parts.push(`int-${item.latestDeployment.integration.planResultNumber} `);
parts.push(`prod-${item.latestDeployment.production.planResultNumber} `);
parts.push(`uptime-${item.latestDeployment.uptime.planResultNumber}`);
}
return parts.join(' ');
};
static defaultProps = {
items: [],
};

const renderDetails = item => ([
renderDeploymentsData(item),
].map(text => ({ text })));
render() {
const {
primaryText,
leftIcon,
leftIconText,
onLeftIconClicked,
items,
} = this.props;

const Plan = ({ data }) =>
<ListItem
lines={2}
primaryText={data.name}
secondaryText={renderSummary(data)}
secondaryTextMoreLine={renderDetails(data)}
leftIcon={renderIcon(data)}
/>;
const hasSensors = items && items.length > 0;

Plan.propTypes = {
data: PropTypes.object.isRequired,
};

export default Plan;
return (
<View
style={[styles.listContainer, { height: hasSensors ? 72 : 72 }]}
>
<TouchableWithoutFeedback onPress={onLeftIconClicked}>
<View style={styles.leftContainer}>
<View>{leftIcon}</View>
<Text style={styles.leftIconText}>{leftIconText}</Text>
</View>
</TouchableWithoutFeedback>
<View style={styles.rightContainer}>
<View style={styles.primaryTextContainer}>
<Text style={styles.primaryText}>{primaryText}</Text>
</View>
{hasSensors ?
<View style={styles.contentContainer}>
{items.map((child, idx) =>
<View key={idx} style={styles.contentItem}>
<RowSensor key={idx} {...child} />
</View>
)}
</View>
:
<View style={styles.noContent}>
<Text>no deployment info</Text>
</View>
}
</View>
</View>
);
}
}
66 changes: 66 additions & 0 deletions src/scenes/Services/BuildPlanRowComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { PropTypes } from 'react';
import {
Icon,
} from 'react-native-material-design';

import BuildPlanRow from './BuildPlanRow';


const getIcon = item => {
switch (item.icon) {
case 'good':
return { name: 'cloud-done', color: 'googleGreen500' };
case 'warning':
return { name: 'cloud-done', color: 'googleYellow500' };
case 'error':
return { name: 'error', color: 'googleRed500' };
default:
return { name: 'cloud', color: 'paperBlueGrey300' };
}
};

const renderIcon = item => {
const icon = getIcon(item);
return (<Icon name={icon.name} color={icon.color} />);
};

const mapBuildNumber = item => {
if (item && item.lastBuild) {
return item.lastBuild.toString();
}
return '';
};

const prtgStatus = (alive) => {
if (alive === undefined) return 'unknown';
return alive ? 'good' : 'error';
};

const mapSensorData = (deployment) => ({
name: deployment.name,
build: (deployment.build || '???').toString(),
deployStatus: deployment.latest ? 'good' : 'warning',
prtgStatus: prtgStatus(deployment.alive),
});

const getSensorsData = (data) => {
if (data && data.deployments) {
const res = data.deployments.map(mapSensorData);
return res;
}
return [];
};

const BuildPlanRowComponent = ({ data }) =>
<BuildPlanRow
primaryText={data.name}
leftIconText={mapBuildNumber(data)}
leftIcon={renderIcon(data)}
items={getSensorsData(data)}
/>;

BuildPlanRowComponent.propTypes = {
data: PropTypes.object.isRequired,
};

export default BuildPlanRowComponent;
70 changes: 70 additions & 0 deletions src/scenes/Services/RowSensor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { PropTypes } from 'react';
import {
StyleSheet,
View,
Text,
} from 'react-native';
import {
Icon, COLOR,
} from 'react-native-material-design';

const styles = StyleSheet.create({
rowSensor: {
flexDirection: 'row',
alignItems: 'center',

paddingVertical: 1,
paddingHorizontal: 5,

borderRadius: 10,
borderWidth: 2,
borderStyle: 'solid',
},
buildContainer: {
padding: 2,
},
build: {
fontWeight: '500',
fontSize: 14,
},
});

const color = name => COLOR[name].color;

const mapStatusToColorName = (status) => {
switch (status) {
case 'good':
return 'googleGreen500';
case 'warning':
return 'googleYellow500';
case 'error':
return 'googleRed500';
default:
return 'paperBlueGrey300';
}
};

const mapStatusToColor = status => color(mapStatusToColorName(status));

const mapSensorIcon = status => ({
name: 'network-check',
color: mapStatusToColorName(status),
});

const RowSensor = ({ name, build, deployStatus, prtgStatus }) =>
<View style={[styles.rowSensor, { borderColor: mapStatusToColor(deployStatus) }]}>
<Text>{name.toUpperCase()}.</Text>
<View style={[styles.buildContainer]}>
<Text style={[styles.build]}>{build}</Text>
</View>
<Icon size={20} {...mapSensorIcon(prtgStatus)} />
</View>;

RowSensor.propTypes = {
name: PropTypes.string.isRequired,
build: PropTypes.string,
deployStatus: PropTypes.string,
prtgStatus: PropTypes.string,
};

export default RowSensor;
2 changes: 1 addition & 1 deletion src/scenes/Services/ServicesScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
COLOR, TYPO,
} from 'react-native-material-design';

import BuildPlanRow from './BuildPlanRow';
import BuildPlanRow from './BuildPlanRowComponent';

const styles = StyleSheet.create({
divider: {
Expand Down

0 comments on commit cef0c4c

Please sign in to comment.