<commit_before>'use strict';

import React, {
    Component,
    Image,
    Navigator,
    ScrollView,
    StyleSheet,
    Text,
    TouchableHighlight,
    TouchableOpacity,
    View
} from 'react-native';

import assign from 'object-assign';

const Icon = require('react-native-vector-icons/FontAwesome');
const fileTextIcon = (<Icon name="file-text-o" size={20} color="#FFFFFF"></Icon>);

const AppView = React.createClass({
  render() {
    return (
        <View style={styles.container}>
          <ScrollView contentContainerStyle={styles.scrollContainer}
                      automaticallyAdjustContentInsets={true}>
            <View key="content" style={styles.content}>
              <View key="app" style={styles.app}>
                <View key="appRow-1" style={styles.appRowTopBorder}>
                  <View key="appCol-1" style={styles.appCol}>
                    <Icon name="heart" size={20} color="#FC6165" style={styles.appItemIcon2}/>
                    <Text key="1" style={styles.appItemText}>亲密付</Text>
                  </View>
                  <View key="appCol-2" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-gupiao.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>股票</Text>
                  </View>
                  <View key="appCol-3" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-chanpinfenleishijie.png')}
                           style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>世界那么大</Text>
                  </View>
                  <View key="appCol-4" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-tianmao.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>天猫</Text>
                  </View>
                </View>
                <View key="appRow-2" style={styles.appRow}>
                  <View key="appCol-1" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-yuebao.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>余额宝</Text>
                  </View>
                  <View key="appCol-2" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-kuaidi.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>我的快递</Text>
                  </View>
                  <View key="appCol-3" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-jipiao.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>机票火车票</Text>
                  </View>
                  <View key="appCol-4" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-juanzeng.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>爱心捐赠</Text>
                  </View>
                </View>

                <View key="appRow-3" style={styles.appRow}>
                  <View key="appCol-1" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-yangchengtongchongzhi.png')}
                           style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>羊城通充值</Text>
                  </View>
                  <View key="appCol-2" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-xiaoyuanyiqiatong.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>校园一卡通</Text>
                  </View>
                  <View key="appCol-3" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-jiaoyujiaofei.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>教育缴费</Text>
                  </View>
                  <View key="appCol-4" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-juanzeng.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>爱心捐赠</Text>
                  </View>
                </View>
                <View key="appRow-4" style={styles.appRow}>
                  <View key="appCol-1" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-caipiao.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>彩票</Text>
                  </View>
                  <View key="appCol-2" style={styles.appCol}>
                    <Image source={require('../../../images/iconfont-licaixiaogongju.png')} style={styles.appItemIcon}/>
                    <Text key="1" style={styles.appItemText}>理财小工具</Text>
                  </View>
                  <View key="appCol-3" style={styles.appCol}>

                  </View>
                  <View key="appCol-4" style={styles.appCol}>

                  </View>
                </View>
              </View>

            </View>
          </ScrollView>
        </View>
    );
  },

  goto(name, com) {
    console.log('goto', this);
    this.props.navigator.push({
      name: name,
      component: com,
    });
  },
});

const styles = StyleSheet.create(assign({
  container: {
    flex: 1,
    backgroundColor: '#F5F5F9',
  },
  scrollContainer: {
    backgroundColor: '#F5F5F9',
    paddingBottom: 15,
    marginTop: -20,
  },
  content: {
    backgroundColor: '#F5F5F9',
    flex: 1,
  },
}, {
  app: {

  },
  appRow: {
    height: 75,
    flexDirection: 'row',
    backgroundColor: '#3F454F',
  },
  appRowTopBorder: {
    height: 75,
    flexDirection: 'row',
    backgroundColor: '#3F454F',
    borderTopWidth: 1,
    borderColor: '#E6E6E6',
  },
  appCol: {
    flex: 1,
    borderRightWidth: 1,
    borderBottomWidth: 1,
    borderColor: '#E6E6E6',
    backgroundColor: '#fff',
    alignItems: 'center',
    paddingTop: 15,
  },
  appItemIcon: {
    width: 24,
    height: 24,
  },
  appItemIcon2: {
    width: 24,
    height: 24,
    paddingTop: 2,
  },
  appItemText: {
    marginTop: 8,
    fontSize: 12
  },
  appItemTextMore: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: 'bold',
    color: '#ccc',
  },
}, {
  app: {
    marginTop: 84,
    paddingBottom: 50
  }
}));

export default AppView;<commit_msg>more app page<commit_after>'use strict';

import React, {
    Image,
    Navigator,
    ScrollView,
    StyleSheet,
    Text,
    TouchableHighlight,
    TouchableOpacity,
    View
} from 'react-native';

import assign from 'object-assign';
import AppList from './AppList';
import AppInfoView from './AppInfo';
import CommonStyles from '../../../styles/common';
import AppListStyles from '../../../styles/appList';

// 九宫格配置对象
const appListData = [
  [
    {
      title: '亲密付',
      icon: {
        name: 'heart',
        size: 20,
        color: '#FC6165',
      }
    },
    {
      title: '股票',
      image: {
        source: require('../../../images/iconfont-gupiao.png'),
      }
    },
    {
      title: '世界那么大',
      image: {
        source: require('../../../images/iconfont-chanpinfenleishijie.png'),
      }
    },
    {
      title: '天猫',
      image: {
        source: require('../../../images/iconfont-tianmao.png'),
      }
    },
  ],
  [
    {
      title: '余额宝',
      image: {
        source: require('../../../images/iconfont-yuebao.png'),
      }
    },
    {
      title: '我的快递',
      image: {
        source: require('../../../images/iconfont-kuaidi.png'),
      }
    },
    {
      title: '机票火车票',
      image: {
        source: require('../../../images/iconfont-jipiao.png'),
      }
    },
    {
      title: '爱心捐赠',
      image: {
        source: require('../../../images/iconfont-juanzeng.png'),
      }
    },
  ],
  [
    {
      title: '羊城通充值',
      image: {
        source: require('../../../images/iconfont-yangchengtongchongzhi.png'),
      }
    },
    {
      title: '校园一卡通',
      image: {
        source: require('../../../images/iconfont-xiaoyuanyiqiatong.png'),
      }
    },
    {
      title: '教育缴费',
      image: {
        source: require('../../../images/iconfont-jiaoyujiaofei.png'),
      }
    },
    {
      title: '爱心捐赠',
      image: {
        source: require('../../../images/iconfont-juanzeng.png'),
      }
    },
  ],
  [
    {
      title: '彩票',
      image: {
        source: require('../../../images/iconfont-caipiao.png'),
      }
    },
    {
      title: '理财小工具',
      image: {
        source: require('../../../images/iconfont-licaixiaogongju.png'),
      }
    },
    {

    },
    {

    }
  ]
];

const AppMoreView = React.createClass({
  handleAppClick(appInfo) {
    this.navigatorPush('app', appInfo.title, AppInfoView, appInfo.options);
  },

  render() {
    return (
        <View style={styles.container}>
          <ScrollView contentContainerStyle={styles.scrollContainerApp}
                      automaticallyAdjustContentInsets={true}>
            <View key="content" style={styles.content}>
              <View key="app" style={styles.app}>
                <AppList styles={styles}
                         data={appListData}
                         topBorder={false}
                         onAppPress={this.handleAppClick} />
              </View>
            </View>
          </ScrollView>
        </View>
    );
  },

  navigatorPush(name, title, component, options = {}) {
    this.props.navigator.push(assign({
      title: title,
      name: name,
      component: component,
    }, options));
  },
});

const styles = StyleSheet.create(assign(
    CommonStyles,
    AppListStyles,
    {
      app: {
        marginTop: 84,
        paddingBottom: 50
      }
    }
));

export default AppMoreView;
<|endoftext|>


<commit_before>import React, { useRef, useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { isEqual, orderBy } from "lodash";
import { NODE_VISIBLE } from "../../util/globals";
import { getColorByTitle, getTipColorAttribute } from "../../util/colorHelpers";
import { determineLegendMatch } from "../../util/tipRadiusHelpers";
import ErrorBoundary from "../../util/errorBoundry";
import Flex from "../framework/flex";
import Card from "../framework/card";
import Legend from "../tree/legend/legend";
import HoverPanel from "./hoverPanel";
import {
  createXScale,
  createYScale,
  groupMeasurements,
  clearMeasurementsSVG,
  drawMeasurementsSVG,
  drawMeansForColorBy,
  colorMeasurementsSVG,
  changeMeasurementsDisplay,
  svgContainerDOMId,
  toggleDisplay,
  addHoverPanelToMeasurementsAndMeans,
  addColorByAttrToGroupingLabel
} from "./measurementsD3";

/**
 * A custom React Hook that returns a memoized value that will only change
 * if a deep comparison using lodash.isEqual determines the value is not
 * equivalent to the previous value.
 * @param {*} value
 * @returns {*}
 */
const useDeepCompareMemo = (value) => {
  const ref = useRef();
  if (!isEqual(value, ref.current)) {
    ref.current = value;
  }
  return ref.current;
};

// Checks visibility against global NODE_VISIBLE
const isVisible = (visibility) => visibility === NODE_VISIBLE;

/**
 * A custom React Redux Selector that reduces the tree redux state to an object
 * with the terminal strain names and their corresponding properties that
 * are relevant for the Measurement's panel. Uses the colorScale redux state to
 * find the current color attribute per strain.
 *
 * tree.visiblity and tree.nodeColors need to be an arrays that have the same
 * order as tree.nodes
 * @param {Object} state
 * @returns {Object<string,Object>}
 */
const treeStrainPropertySelector = (state) => {
  const { tree, controls } = state;
  const { colorScale } = controls;
  const intitialTreeStrainProperty = {
    treeStrainVisibility: {},
    treeStrainColors: {}
  };
  return tree.nodes.reduce((treeStrainProperty, node, index) => {
    const { treeStrainVisibility, treeStrainColors } = treeStrainProperty;
    // Only store properties of terminal strain nodes
    if (!node.hasChildren) {
      treeStrainVisibility[node.name] = tree.visibility[index];
      // Only store colors for visible strains since only measurmeents
      // for visible strains will be displayed
      if (isVisible(tree.visibility[index])) {
        /*
        * If the color scale is continuous, we want to group by the legend value
        * instead of the specific strain attribute in order to combine all values
        * within the legend bounds into a single group.
        */
        let attribute = getTipColorAttribute(node, colorScale);
        if (colorScale.continuous) {
          const matchingLegendValue = colorScale.visibleLegendValues
            .find((legendValue) => determineLegendMatch(legendValue, node, colorScale));
          if (matchingLegendValue !== undefined) attribute = matchingLegendValue;
        }
        treeStrainColors[node.name] = {
          attribute,
          color: tree.nodeColors[index]
        };
      }
    }
    return treeStrainProperty;
  }, intitialTreeStrainProperty);
};

/**
 * Filters provided measurements to measurements of strains that are currently
 * visible in the tree adn that are included in the active measurements filters.
 *
 * Visibility is indicated by the numeric visibility value in the provided
 * treeStrainVisibility object for strain.
 *
 * Returns the active filters object and the filtered measurements
 * @param {Array<Object>} measurements
 * @param {Object<string,number>} treeStrainVisibility
 * @param {Object<string,Map>} filters
 * @returns {Object<Object, Array>}
 */
const filterMeasurements = (measurements, treeStrainVisibility, filters) => {
  // Find active filters to filter measurements
  const activeFilters = {};
  Object.entries(filters).forEach(([field, valuesMap]) => {
    activeFilters[field] = activeFilters[field] || [];
    valuesMap.forEach(({active}, fieldValue) => {
      // Save array of active values for the field filter
      if (active) activeFilters[field].push(fieldValue);
    });
  });

  return {
    activeFilters,
    filteredMeasurements: measurements.filter((measurement) => {
      // First check the strain is visible in the tree
      if (!isVisible(treeStrainVisibility[measurement.strain])) return false;
      // Then check that the measurement contains values for all active filters
      for (const [field, values] of Object.entries(activeFilters)) {
        if (values.length > 0 && !values.includes(measurement[field])) return false;
      }
      return true;
    })
  };
};

const MeasurementsPlot = ({height, width, showLegend, setPanelTitle}) => {
  // Use `lodash.isEqual` to deep compare object states to prevent unnecessary re-renderings of the component
  const { treeStrainVisibility, treeStrainColors } = useSelector((state) => treeStrainPropertySelector(state), isEqual);
  const colorings = useSelector((state) => state.metadata.colorings);
  const colorBy = useSelector((state) => state.controls.colorBy);
  const groupBy = useSelector((state) => state.controls.measurementsGroupBy);
  const filters = useSelector((state) => state.controls.measurementsFilters);
  const display = useSelector((state) => state.controls.measurementsDisplay);
  const showOverallMean = useSelector((state) => state.controls.measurementsShowOverallMean);
  const showThreshold = useSelector((state) => state.controls.measurementsShowThreshold);
  const collection = useSelector((state) => state.measurements.collectionToDisplay, isEqual);
  const { title, x_axis_label, threshold, fields, measurements, groupings } = collection;

  // Ref to access the D3 SVG
  const d3Ref = useRef(null);

  // State for storing data for the HoverPanel
  const [hoverData, setHoverData] = useState(null);

  // Filter and group measurements
  const {activeFilters, filteredMeasurements} = filterMeasurements(measurements, treeStrainVisibility, filters);
  const groupingOrderedValues = groupings.get(groupBy).values;
  // Default ordering of rows is the groupings value order from redux state
  let groupByValueOrder = groupingOrderedValues;
  // If there are active filters for the current group-by field, ordering is the user's filter order
  if (activeFilters[groupBy] && activeFilters[groupBy].length) {
    groupByValueOrder = activeFilters[groupBy];
  }
  const groupedMeasurements = groupMeasurements(filteredMeasurements, groupBy, groupByValueOrder);

  // Memoize D3 scale functions to allow deep comparison to work below for svgData
  const xScale = useMemo(() => createXScale(width, measurements), [width, measurements]);
  const yScale = useMemo(() => createYScale(), []);
  // Memoize all data needed for basic SVG to avoid extra re-drawings
  const svgData = useDeepCompareMemo({ xScale, yScale, x_axis_label, threshold, groupingOrderedValues, groupedMeasurements});
  // Memoize handleHover function to avoid extra useEffect calls
  const handleHover = useMemo(() => (data, dataType, mouseX, mouseY, colorByAttr=null) => {
    let newHoverData = null;
    if (data !== null) {
      // Set color-by attribute as title if provided
      const hoverTitle = colorByAttr !== null ? `Color by ${getColorByTitle(colorings, colorBy)} : ${colorByAttr}` : null;
      // Create a Map of data to save order of fields
      const newData = new Map();
      if (dataType === "measurement") {
        // Handle single measurement data
        // Filter out internal auspice fields (i.e. measurementsJitter and measurementsId)
        const displayFields = Object.keys(data).filter((field) => fields.has(field));
        // Order fields for display
        const fieldOrder = [...fields.keys()];
        const orderedFields = orderBy(displayFields, (field) => fieldOrder.indexOf(field));
        orderedFields.forEach((field) => {
          newData.set(fields.get(field).title, data[field]);
        });
      } else if (dataType === "mean") {
        // Handle mean and standard deviation data
        newData.set("mean", data.mean.toFixed(2));
        newData.set("standard deviation", data.standardDeviation ? data.standardDeviation.toFixed(2) : "N/A");
      } else {
        // Catch unknown data types
        console.error(`"Unknown data type for hover panel: ${dataType}`);
        // Display provided data without extra ordering or parsing
        Object.entries(data).forEach(([key, value]) => newData.set(key, value));
      }
      newHoverData = {
        hoverTitle,
        mouseX,
        mouseY,
        containerId: svgContainerDOMId,
        data: newData
      };
    }
    setHoverData(newHoverData);
  }, [fields, colorings, colorBy]);

  useEffect(() => {
    setPanelTitle(`${title || "Measurements"} (grouped by ${fields.get(groupBy).title})`);
  }, [setPanelTitle, title, fields, groupBy]);

  // Draw SVG from scratch
  useEffect(() => {
    clearMeasurementsSVG(d3Ref.current);
    drawMeasurementsSVG(d3Ref.current, svgData);
  }, [svgData]);

  // Color the SVG & redraw color-by means when SVG is re-drawn or when colors have changed
  useEffect(() => {
    addColorByAttrToGroupingLabel(d3Ref.current, treeStrainColors);
    colorMeasurementsSVG(d3Ref.current, treeStrainColors);
    drawMeansForColorBy(d3Ref.current, svgData, treeStrainColors);
    addHoverPanelToMeasurementsAndMeans(d3Ref.current, handleHover, treeStrainColors);
  }, [svgData, treeStrainColors, handleHover]);

  // Display raw/mean measurements when SVG is re-drawn, colors have changed, or display has changed
  useEffect(() => {
    changeMeasurementsDisplay(d3Ref.current, display);
  }, [svgData, treeStrainColors, display]);

  useEffect(() => {
    toggleDisplay(d3Ref.current, "overallMean", showOverallMean);
  }, [svgData, showOverallMean]);

  useEffect(() => {
    toggleDisplay(d3Ref.current, "threshold", showThreshold);
  }, [svgData, showThreshold]);

  const getSVGContainerStyle = () => {
    return {
      overflowY: "auto",
      position: "relative",
      height: height,
      width: width
    };
  };

  return (
    <>
      {showLegend &&
        <ErrorBoundary>
          <Legend right width={width}/>
        </ErrorBoundary>
      }

        {hoverData &&
          <HoverPanel
            hoverData={hoverData}
          />
        }
        <svg
          id="d3MeasurementsSVG"
          width="100%"
          ref={d3Ref}
        />

    </>
  );
};

const Measurements = ({height, width, showLegend}) => {
  const measurementsLoaded = useSelector((state) => state.measurements.loaded);
  const measurementsError = useSelector((state) => state.measurements.error);

  const [title, setTitle] = useState("Measurements");

  const getCardTitleStyle = () => {
    /**
     * Additional styles of Card title forces it to be in one line and display
     * ellipsis if the title is too long to prevent the long title from pushing
     * the Card into the next line when viewing in grid mode
     */
    return {
      width,
      display: "block",
      overflow: "hidden",
      whiteSpace: "nowrap",
      textOverflow: "ellipsis"
    };
  };

  return (
    <Card title={title} titleStyles={getCardTitleStyle()}>
      {measurementsLoaded &&
        (measurementsError ?
          <Flex style={{ height, width}} direction="column" justifyContent="center">

              {measurementsError}

          </Flex> :
          <MeasurementsPlot
            height={height}
            width={width}
            showLegend={showLegend}
            setPanelTitle={setTitle}
          />
        )
      }
    </Card>
  );
};

export default Measurements;
<commit_msg>measurements: keep tree strain colors regardless of visibility<commit_after>import React, { useRef, useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { isEqual, orderBy } from "lodash";
import { NODE_VISIBLE } from "../../util/globals";
import { getColorByTitle, getTipColorAttribute } from "../../util/colorHelpers";
import { determineLegendMatch } from "../../util/tipRadiusHelpers";
import ErrorBoundary from "../../util/errorBoundry";
import Flex from "../framework/flex";
import Card from "../framework/card";
import Legend from "../tree/legend/legend";
import HoverPanel from "./hoverPanel";
import {
  createXScale,
  createYScale,
  groupMeasurements,
  clearMeasurementsSVG,
  drawMeasurementsSVG,
  drawMeansForColorBy,
  colorMeasurementsSVG,
  changeMeasurementsDisplay,
  svgContainerDOMId,
  toggleDisplay,
  addHoverPanelToMeasurementsAndMeans,
  addColorByAttrToGroupingLabel
} from "./measurementsD3";

/**
 * A custom React Hook that returns a memoized value that will only change
 * if a deep comparison using lodash.isEqual determines the value is not
 * equivalent to the previous value.
 * @param {*} value
 * @returns {*}
 */
const useDeepCompareMemo = (value) => {
  const ref = useRef();
  if (!isEqual(value, ref.current)) {
    ref.current = value;
  }
  return ref.current;
};

// Checks visibility against global NODE_VISIBLE
const isVisible = (visibility) => visibility === NODE_VISIBLE;

/**
 * A custom React Redux Selector that reduces the tree redux state to an object
 * with the terminal strain names and their corresponding properties that
 * are relevant for the Measurement's panel. Uses the colorScale redux state to
 * find the current color attribute per strain.
 *
 * tree.visiblity and tree.nodeColors need to be an arrays that have the same
 * order as tree.nodes
 * @param {Object} state
 * @returns {Object<string,Object>}
 */
const treeStrainPropertySelector = (state) => {
  const { tree, controls } = state;
  const { colorScale } = controls;
  const intitialTreeStrainProperty = {
    treeStrainVisibility: {},
    treeStrainColors: {}
  };
  return tree.nodes.reduce((treeStrainProperty, node, index) => {
    const { treeStrainVisibility, treeStrainColors } = treeStrainProperty;
    // Only store properties of terminal strain nodes
    if (!node.hasChildren) {
      treeStrainVisibility[node.name] = tree.visibility[index];
      /*
      * If the color scale is continuous, we want to group by the legend value
      * instead of the specific strain attribute in order to combine all values
      * within the legend bounds into a single group.
      */
      let attribute = getTipColorAttribute(node, colorScale);
      if (colorScale.continuous) {
        const matchingLegendValue = colorScale.visibleLegendValues
          .find((legendValue) => determineLegendMatch(legendValue, node, colorScale));
        if (matchingLegendValue !== undefined) attribute = matchingLegendValue;
      }
      treeStrainColors[node.name] = {
        attribute,
        color: tree.nodeColors[index]
      };

    }
    return treeStrainProperty;
  }, intitialTreeStrainProperty);
};

/**
 * Filters provided measurements to measurements of strains that are currently
 * visible in the tree adn that are included in the active measurements filters.
 *
 * Visibility is indicated by the numeric visibility value in the provided
 * treeStrainVisibility object for strain.
 *
 * Returns the active filters object and the filtered measurements
 * @param {Array<Object>} measurements
 * @param {Object<string,number>} treeStrainVisibility
 * @param {Object<string,Map>} filters
 * @returns {Object<Object, Array>}
 */
const filterMeasurements = (measurements, treeStrainVisibility, filters) => {
  // Find active filters to filter measurements
  const activeFilters = {};
  Object.entries(filters).forEach(([field, valuesMap]) => {
    activeFilters[field] = activeFilters[field] || [];
    valuesMap.forEach(({active}, fieldValue) => {
      // Save array of active values for the field filter
      if (active) activeFilters[field].push(fieldValue);
    });
  });

  return {
    activeFilters,
    filteredMeasurements: measurements.filter((measurement) => {
      // First check the strain is visible in the tree
      if (!isVisible(treeStrainVisibility[measurement.strain])) return false;
      // Then check that the measurement contains values for all active filters
      for (const [field, values] of Object.entries(activeFilters)) {
        if (values.length > 0 && !values.includes(measurement[field])) return false;
      }
      return true;
    })
  };
};

const MeasurementsPlot = ({height, width, showLegend, setPanelTitle}) => {
  // Use `lodash.isEqual` to deep compare object states to prevent unnecessary re-renderings of the component
  const { treeStrainVisibility, treeStrainColors } = useSelector((state) => treeStrainPropertySelector(state), isEqual);
  const colorings = useSelector((state) => state.metadata.colorings);
  const colorBy = useSelector((state) => state.controls.colorBy);
  const groupBy = useSelector((state) => state.controls.measurementsGroupBy);
  const filters = useSelector((state) => state.controls.measurementsFilters);
  const display = useSelector((state) => state.controls.measurementsDisplay);
  const showOverallMean = useSelector((state) => state.controls.measurementsShowOverallMean);
  const showThreshold = useSelector((state) => state.controls.measurementsShowThreshold);
  const collection = useSelector((state) => state.measurements.collectionToDisplay, isEqual);
  const { title, x_axis_label, threshold, fields, measurements, groupings } = collection;

  // Ref to access the D3 SVG
  const d3Ref = useRef(null);

  // State for storing data for the HoverPanel
  const [hoverData, setHoverData] = useState(null);

  // Filter and group measurements
  const {activeFilters, filteredMeasurements} = filterMeasurements(measurements, treeStrainVisibility, filters);
  const groupingOrderedValues = groupings.get(groupBy).values;
  // Default ordering of rows is the groupings value order from redux state
  let groupByValueOrder = groupingOrderedValues;
  // If there are active filters for the current group-by field, ordering is the user's filter order
  if (activeFilters[groupBy] && activeFilters[groupBy].length) {
    groupByValueOrder = activeFilters[groupBy];
  }
  const groupedMeasurements = groupMeasurements(filteredMeasurements, groupBy, groupByValueOrder);

  // Memoize D3 scale functions to allow deep comparison to work below for svgData
  const xScale = useMemo(() => createXScale(width, measurements), [width, measurements]);
  const yScale = useMemo(() => createYScale(), []);
  // Memoize all data needed for basic SVG to avoid extra re-drawings
  const svgData = useDeepCompareMemo({ xScale, yScale, x_axis_label, threshold, groupingOrderedValues, groupedMeasurements});
  // Memoize handleHover function to avoid extra useEffect calls
  const handleHover = useMemo(() => (data, dataType, mouseX, mouseY, colorByAttr=null) => {
    let newHoverData = null;
    if (data !== null) {
      // Set color-by attribute as title if provided
      const hoverTitle = colorByAttr !== null ? `Color by ${getColorByTitle(colorings, colorBy)} : ${colorByAttr}` : null;
      // Create a Map of data to save order of fields
      const newData = new Map();
      if (dataType === "measurement") {
        // Handle single measurement data
        // Filter out internal auspice fields (i.e. measurementsJitter and measurementsId)
        const displayFields = Object.keys(data).filter((field) => fields.has(field));
        // Order fields for display
        const fieldOrder = [...fields.keys()];
        const orderedFields = orderBy(displayFields, (field) => fieldOrder.indexOf(field));
        orderedFields.forEach((field) => {
          newData.set(fields.get(field).title, data[field]);
        });
      } else if (dataType === "mean") {
        // Handle mean and standard deviation data
        newData.set("mean", data.mean.toFixed(2));
        newData.set("standard deviation", data.standardDeviation ? data.standardDeviation.toFixed(2) : "N/A");
      } else {
        // Catch unknown data types
        console.error(`"Unknown data type for hover panel: ${dataType}`);
        // Display provided data without extra ordering or parsing
        Object.entries(data).forEach(([key, value]) => newData.set(key, value));
      }
      newHoverData = {
        hoverTitle,
        mouseX,
        mouseY,
        containerId: svgContainerDOMId,
        data: newData
      };
    }
    setHoverData(newHoverData);
  }, [fields, colorings, colorBy]);

  useEffect(() => {
    setPanelTitle(`${title || "Measurements"} (grouped by ${fields.get(groupBy).title})`);
  }, [setPanelTitle, title, fields, groupBy]);

  // Draw SVG from scratch
  useEffect(() => {
    clearMeasurementsSVG(d3Ref.current);
    drawMeasurementsSVG(d3Ref.current, svgData);
  }, [svgData]);

  // Color the SVG & redraw color-by means when SVG is re-drawn or when colors have changed
  useEffect(() => {
    addColorByAttrToGroupingLabel(d3Ref.current, treeStrainColors);
    colorMeasurementsSVG(d3Ref.current, treeStrainColors);
    drawMeansForColorBy(d3Ref.current, svgData, treeStrainColors);
    addHoverPanelToMeasurementsAndMeans(d3Ref.current, handleHover, treeStrainColors);
  }, [svgData, treeStrainColors, handleHover]);

  // Display raw/mean measurements when SVG is re-drawn, colors have changed, or display has changed
  useEffect(() => {
    changeMeasurementsDisplay(d3Ref.current, display);
  }, [svgData, treeStrainColors, display]);

  useEffect(() => {
    toggleDisplay(d3Ref.current, "overallMean", showOverallMean);
  }, [svgData, showOverallMean]);

  useEffect(() => {
    toggleDisplay(d3Ref.current, "threshold", showThreshold);
  }, [svgData, showThreshold]);

  const getSVGContainerStyle = () => {
    return {
      overflowY: "auto",
      position: "relative",
      height: height,
      width: width
    };
  };

  return (
    <>
      {showLegend &&
        <ErrorBoundary>
          <Legend right width={width}/>
        </ErrorBoundary>
      }

        {hoverData &&
          <HoverPanel
            hoverData={hoverData}
          />
        }
        <svg
          id="d3MeasurementsSVG"
          width="100%"
          ref={d3Ref}
        />

    </>
  );
};

const Measurements = ({height, width, showLegend}) => {
  const measurementsLoaded = useSelector((state) => state.measurements.loaded);
  const measurementsError = useSelector((state) => state.measurements.error);

  const [title, setTitle] = useState("Measurements");

  const getCardTitleStyle = () => {
    /**
     * Additional styles of Card title forces it to be in one line and display
     * ellipsis if the title is too long to prevent the long title from pushing
     * the Card into the next line when viewing in grid mode
     */
    return {
      width,
      display: "block",
      overflow: "hidden",
      whiteSpace: "nowrap",
      textOverflow: "ellipsis"
    };
  };

  return (
    <Card title={title} titleStyles={getCardTitleStyle()}>
      {measurementsLoaded &&
        (measurementsError ?
          <Flex style={{ height, width}} direction="column" justifyContent="center">

              {measurementsError}

          </Flex> :
          <MeasurementsPlot
            height={height}
            width={width}
            showLegend={showLegend}
            setPanelTitle={setTitle}
          />
        )
      }
    </Card>
  );
};

export default Measurements;
<|endoftext|>


<commit_before>import React, {Component} from 'react'

import Icon from 'react-fa'
import {Card, CardListElement, CardListSection} from 'gComponents/utility/card/index.js'

import DropDown from 'gComponents/utility/drop-down/index.js'
import {PrivacyToggle} from './privacy-toggle/index'
import {SpaceName} from './spaceName'

import e from 'gEngine/engine'

import './header.css'

const EnableShareableLinkOption = ({onEnable}) => (

Shareable link disabled.

    Enable

)

const DisableOrRotateShareableLinkOption = ({shareableLinkUrl, onDisable, onRotate}) => (

Anyone with the shareable link will be able to view this model. They will not be able to edit the model.

{shareableLinkUrl}

    Disable
    Reset Link

)

const ShareableLinkOption = ({children, shareableLinkUrl, onEnable, onDisable, onRotate}) => (
  <DropDown
      headerText={'Shareable Link'}
      openLink={children}
      position={'left'}
      width={'wide'}
  >
    <CardListSection>
      {!shareableLinkUrl && <EnableShareableLinkOption onEnable={onEnable} />}
      {!!shareableLinkUrl &&
        <DisableOrRotateShareableLinkOption shareableLinkUrl={shareableLinkUrl} onDisable={onDisable} onRotate={onRotate} />
      }
    </CardListSection>
  </DropDown>
)

export class SpaceHeader extends Component {
  componentDidMount() { window.recorder.recordMountEvent(this) }
  componentWillUpdate() { window.recorder.recordRenderStartEvent(this) }
  componentDidUpdate() { window.recorder.recordRenderStopEvent(this) }
  componentWillUnmount() { window.recorder.recordUnmountEvent(this) }

  shouldComponentUpdate(nextProps, nextState) {
    if (!nextProps.editableByMe) { return false }

    return (
      this.props.name !== nextProps.name ||
      this.props.isPrivate !== nextProps.isPrivate ||
      this.props.editableByMe !== nextProps.editableByMe ||
      this.props.shareableLinkUrl !== nextProps.shareableLinkUrl
    )
  }

  render() {
    const {
      canBePrivate,
      name,
      ownerName,
      ownerPicture,
      ownerUrl,
      ownerIsOrg,
      isPrivate,
      editableByMe,
      shareableLinkUrl,
      onPublicSelect,
      onPrivateSelect,
      onSaveName,
      onEnableShareableLink,
      onDisableShareableLink,
      onRotateShareableLink,
    } = this.props

    let privacy_header = (<Icon name='globe'/> Public)
    if (isPrivate) {
      privacy_header = (<Icon name='lock'/> Private)
    }

    return (

              <SpaceName
                  name={name}
                  editableByMe={editableByMe}
                  onSave={onSaveName}
              />

            {(ownerIsOrg || !editableByMe)  &&

                {ownerName}

            }

            {isPrivate && editableByMe &&
              <ShareableLinkOption
                shareableLinkUrl={shareableLinkUrl}
                onEnable={onEnableShareableLink}
                onDisable={onDisableShareableLink}
                onRotate={onRotateShareableLink}
              >

                  <Icon name='link'/> Link

              </ShareableLinkOption>
            }

            {(isPrivate || editableByMe) &&
              <PrivacyToggle
                editableByMe={editableByMe}
                openLink={{privacy_header}}
                isPrivateSelectionInvalid={!canBePrivate}
                isPrivate={isPrivate}
                onPublicSelect={onPublicSelect}
                onPrivateSelect={onPrivateSelect}
              />
            }

    )
  }
}
<commit_msg>Repositioned link to be completely selectable<commit_after>import React, {Component} from 'react'

import Icon from 'react-fa'
import {Card, CardListElement, CardListSection} from 'gComponents/utility/card/index.js'

import DropDown from 'gComponents/utility/drop-down/index.js'
import {PrivacyToggle} from './privacy-toggle/index'
import {SpaceName} from './spaceName'

import e from 'gEngine/engine'

import './header.css'

const EnableShareableLinkOption = ({onEnable}) => (

Shareable link disabled.

    Enable

)

const DisableOrRotateShareableLinkOption = ({shareableLinkUrl, onDisable, onRotate}) => (

{shareableLinkUrl}

Anyone with the shareable link will be able to view this model. They will not be able to edit the model.

    Disable
    Reset Link

)

const ShareableLinkOption = ({children, shareableLinkUrl, onEnable, onDisable, onRotate}) => (
  <DropDown
      headerText={'Shareable Link'}
      openLink={children}
      position={'left'}
      width={'wide'}
  >
    <CardListSection>
      {!shareableLinkUrl && <EnableShareableLinkOption onEnable={onEnable} />}
      {!!shareableLinkUrl &&
        <DisableOrRotateShareableLinkOption shareableLinkUrl={shareableLinkUrl} onDisable={onDisable} onRotate={onRotate} />
      }
    </CardListSection>
  </DropDown>
)

export class SpaceHeader extends Component {
  componentDidMount() { window.recorder.recordMountEvent(this) }
  componentWillUpdate() { window.recorder.recordRenderStartEvent(this) }
  componentDidUpdate() { window.recorder.recordRenderStopEvent(this) }
  componentWillUnmount() { window.recorder.recordUnmountEvent(this) }

  shouldComponentUpdate(nextProps, nextState) {
    if (!nextProps.editableByMe) { return false }

    return (
      this.props.name !== nextProps.name ||
      this.props.isPrivate !== nextProps.isPrivate ||
      this.props.editableByMe !== nextProps.editableByMe ||
      this.props.shareableLinkUrl !== nextProps.shareableLinkUrl
    )
  }

  render() {
    const {
      canBePrivate,
      name,
      ownerName,
      ownerPicture,
      ownerUrl,
      ownerIsOrg,
      isPrivate,
      editableByMe,
      shareableLinkUrl,
      onPublicSelect,
      onPrivateSelect,
      onSaveName,
      onEnableShareableLink,
      onDisableShareableLink,
      onRotateShareableLink,
    } = this.props

    let privacy_header = (<Icon name='globe'/> Public)
    if (isPrivate) {
      privacy_header = (<Icon name='lock'/> Private)
    }

    return (

              <SpaceName
                  name={name}
                  editableByMe={editableByMe}
                  onSave={onSaveName}
              />

            {(ownerIsOrg || !editableByMe)  &&

                {ownerName}

            }

            {isPrivate && editableByMe &&
              <ShareableLinkOption
                shareableLinkUrl={shareableLinkUrl}
                onEnable={onEnableShareableLink}
                onDisable={onDisableShareableLink}
                onRotate={onRotateShareableLink}
              >

                  <Icon name='link'/> Link

              </ShareableLinkOption>
            }

            {(isPrivate || editableByMe) &&
              <PrivacyToggle
                editableByMe={editableByMe}
                openLink={{privacy_header}}
                isPrivateSelectionInvalid={!canBePrivate}
                isPrivate={isPrivate}
                onPublicSelect={onPublicSelect}
                onPrivateSelect={onPrivateSelect}
              />
            }

    )
  }
}
<|endoftext|>


<commit_before>const path = require("path");
const webpack = require("webpack");
const WebpackIsomorphicToolsPlugin = require("webpack-isomorphic-tools/plugin");
const getAssetPath = require("../lib/getAssetPath").default;

const buildWebpackEntries = require("../lib/buildWebpackEntries").default;
const detectEnvironmentVariables = require("../lib/detectEnvironmentVariables");

const getWebpackAdditions = require("../lib/getWebpackAdditions").default;
const {
  additionalLoaders,
  additionalPreLoaders,
  additionalExternals,
  additionalWebpackNodeConfig,
  vendor,
  plugins
} = getWebpackAdditions();

const webpackSharedConfig = require("./webpack-shared-config");

const ASSET_PATH = getAssetPath();

export function getExposedEnvironmentVariables(config) {
  const exposedEnvironmentVariables = {};

  // The config is consumed on both the server side and the client side.
  // However, we want developers to have access to environment
  // variables in there so they can override defaults with an environment
  // variable. For that reason we are going to perform static analysis on that
  // file to determine all of the environment variables that are used in that
  // file and make sure that webpack makes those available in the application.
  const configEnvVariables = detectEnvironmentVariables(config);
  configEnvVariables.push("NODE_ENV");
  configEnvVariables.forEach((v) => {
    exposedEnvironmentVariables[v] = JSON.stringify(process.env[v]);
  });

  return exposedEnvironmentVariables;
}

export function getEnvironmentPlugins(isProduction) {
  const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require("../config/webpack-isomorphic-tools-config"))
  .development(!isProduction);

  let environmentPlugins = [];

  if (isProduction) {
    environmentPlugins = environmentPlugins.concat([
      webpackIsomorphicToolsPlugin,
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]);
  }
  else {
    environmentPlugins = environmentPlugins.concat([
      webpackIsomorphicToolsPlugin,
      new webpack.HotModuleReplacementPlugin(),
    ]);
  }

  return environmentPlugins;
}

export default function (appRoot, appConfigFilePath, isProduction) {
  const OUTPUT_FILE = `app${isProduction ? "-[chunkhash]" : ""}.bundle.js`;
  const devtool = process.env.DEVTOOL || "inline-source-map";
  return {
    context: appRoot,
    devtool: isProduction ? null : devtool,
    entry: {
      ...buildWebpackEntries(isProduction),
      vendor: vendor
    },
    module: {
      loaders: [
        {
          test: /\.js$/,
          loader: "babel-loader",
          query: {
            plugins: [
              "babel-plugin-gluestick"
            ],
            presets: [
              "react",
              "es2015",
              "stage-0"
            ]
          },
          include: [
            path.join(appRoot, "src/config/application.js"),
          ]
        }
      ].concat(webpackSharedConfig.loaders, additionalLoaders),
      preLoaders: [
      // only place client specific preLoaders here
      ].concat(webpackSharedConfig.preLoaders, additionalPreLoaders),
    },
    node: {
      fs: "empty",
      ...additionalWebpackNodeConfig
    },
    output: {
      path: path.join(appRoot, "build"),
      filename: `[name]-${OUTPUT_FILE}`,
      chunkFilename: `[name]-chunk-${OUTPUT_FILE}`,
      publicPath: ASSET_PATH,
    },
    plugins: [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.NoErrorsPlugin(),
      new webpack.DefinePlugin({
        "process.env": getExposedEnvironmentVariables(appConfigFilePath)
      }),

      // Make it so *.server.js files return null in client
      new webpack.NormalModuleReplacementPlugin(/\.server(\.js)?$/, path.join(__dirname, "./serverFileMock.js")),

      new webpack.optimize.CommonsChunkPlugin("vendor", `vendor${isProduction ? "-[hash]" : ""}.bundle.js`),
    ].concat(getEnvironmentPlugins(isProduction), webpackSharedConfig.plugins, plugins),
    resolve: {
      ...webpackSharedConfig.resolve
    },
    externals: {
      ...additionalExternals
    }
  };

}
<commit_msg>Set source-map as default production devtool<commit_after>const path = require("path");
const webpack = require("webpack");
const WebpackIsomorphicToolsPlugin = require("webpack-isomorphic-tools/plugin");
const getAssetPath = require("../lib/getAssetPath").default;

const buildWebpackEntries = require("../lib/buildWebpackEntries").default;
const detectEnvironmentVariables = require("../lib/detectEnvironmentVariables");

const getWebpackAdditions = require("../lib/getWebpackAdditions").default;
const {
  additionalLoaders,
  additionalPreLoaders,
  additionalExternals,
  additionalWebpackNodeConfig,
  vendor,
  plugins
} = getWebpackAdditions();

const webpackSharedConfig = require("./webpack-shared-config");

const ASSET_PATH = getAssetPath();

export function getExposedEnvironmentVariables(config) {
  const exposedEnvironmentVariables = {};

  // The config is consumed on both the server side and the client side.
  // However, we want developers to have access to environment
  // variables in there so they can override defaults with an environment
  // variable. For that reason we are going to perform static analysis on that
  // file to determine all of the environment variables that are used in that
  // file and make sure that webpack makes those available in the application.
  const configEnvVariables = detectEnvironmentVariables(config);
  configEnvVariables.push("NODE_ENV");
  configEnvVariables.forEach((v) => {
    exposedEnvironmentVariables[v] = JSON.stringify(process.env[v]);
  });

  return exposedEnvironmentVariables;
}

export function getEnvironmentPlugins(isProduction) {
  const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require("../config/webpack-isomorphic-tools-config"))
  .development(!isProduction);

  let environmentPlugins = [];

  if (isProduction) {
    environmentPlugins = environmentPlugins.concat([
      webpackIsomorphicToolsPlugin,
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]);
  }
  else {
    environmentPlugins = environmentPlugins.concat([
      webpackIsomorphicToolsPlugin,
      new webpack.HotModuleReplacementPlugin(),
    ]);
  }

  return environmentPlugins;
}

export default function (appRoot, appConfigFilePath, isProduction) {
  const OUTPUT_FILE = `app${isProduction ? "-[chunkhash]" : ""}.bundle.js`;
  const devtool = process.env.DEVTOOL || "inline-source-map";
  return {
    context: appRoot,
    devtool: isProduction ? "source-map" : devtool,
    entry: {
      ...buildWebpackEntries(isProduction),
      vendor: vendor
    },
    module: {
      loaders: [
        {
          test: /\.js$/,
          loader: "babel-loader",
          query: {
            plugins: [
              "babel-plugin-gluestick"
            ],
            presets: [
              "react",
              "es2015",
              "stage-0"
            ]
          },
          include: [
            path.join(appRoot, "src/config/application.js"),
          ]
        }
      ].concat(webpackSharedConfig.loaders, additionalLoaders),
      preLoaders: [
      // only place client specific preLoaders here
      ].concat(webpackSharedConfig.preLoaders, additionalPreLoaders),
    },
    node: {
      fs: "empty",
      ...additionalWebpackNodeConfig
    },
    output: {
      path: path.join(appRoot, "build"),
      filename: `[name]-${OUTPUT_FILE}`,
      chunkFilename: `[name]-chunk-${OUTPUT_FILE}`,
      publicPath: ASSET_PATH,
    },
    plugins: [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.NoErrorsPlugin(),
      new webpack.DefinePlugin({
        "process.env": getExposedEnvironmentVariables(appConfigFilePath)
      }),

      // Make it so *.server.js files return null in client
      new webpack.NormalModuleReplacementPlugin(/\.server(\.js)?$/, path.join(__dirname, "./serverFileMock.js")),

      new webpack.optimize.CommonsChunkPlugin("vendor", `vendor${isProduction ? "-[hash]" : ""}.bundle.js`),
    ].concat(getEnvironmentPlugins(isProduction), webpackSharedConfig.plugins, plugins),
    resolve: {
      ...webpackSharedConfig.resolve
    },
    externals: {
      ...additionalExternals
    }
  };

}
<|endoftext|>


<commit_before>//Geometries

Map.setCenter(-88, 41.8, 9)

function multi (feature){
  //Reduce number of vertices in geometry; the number is to specify maximum error in meters
  var simple = feature.simplify(1000);
  //Find centroid of geometry
  var center = simple.centroid();
  //Create buffer around geometry; the number represents the width of buffer in meters
  var buff = center.buffer(500);
  //return variable from function
  return buff
}

//Load Feature Collection of the dissolved boundary of Chicago stored in assets
var Chic=ee.FeatureCollection('users/tirthankar25/chicago_diss');
//Load Feature Collection of the neighborhood-scale Chicago data stored in assets
//var Chic_coll=ee.FeatureCollection('users/tirthankar25/chicago');
//Map function over Feature Collection
//var Res=Chic_coll.map(multi);
//Add the layer to the map
//Map.addLayer(Res)

Map.addLayer(Chic, {},'Chicago dissolved')
//Find the rectangle that emcompasses the southernmost, westernmost, easternmost, and northernmost
//points of the feature
//var bound = Chic.geometry().bounds();
//Find the polygon covering the extremities of the feature
//var convex = Chic.geometry().convexHull();
//Map.addLayer(bound, {},'Chicago bounds');
//Map.addLayer(convex, {},'Chicago convex hull');

//Find the area common to two or more features
//var Intersect=bound.intersection(convex,100);
//Map.addLayer(Intersect, {},'Bound and convex intersection');

//Find the area encompassing two or more features; number is the maximum error in meters
//var Union=bound.union(convex,100);
//Map.addLayer(Union, {},'Bound and convex union');

//Find area of feature
//var Ar=Chic.geometry().area();
//Find length of line geometry
//var length=Chic.geometry().length();
//Find permeter of feature
//var peri=Chic.geometry().perimeter();
//print (peri)

//Features

//Create Geometry
var var_Geometry=ee.Geometry.Polygon(0,0, 40,30, 20, 20, 0, 0);
//Create Feature from Geometry
var var_Feature = ee.Feature(var_Geometry, {Name: ["Feature name","Supreme"], Size: [500, 1000]});
//Get values of a property
//var Arr=var_Feature.get('Size');
//print (Arr)
//Select a subset of properties and rename them
var var_Featurenew = var_Feature.select(["Name"], ["Descriptor"]);
print(var_Featurenew)

//Images

Map.setCenter(-88, 41.8, 9)
var Raw = ee.ImageCollection('MODIS/006/MYD11A2');
var ROI = ee.FeatureCollection('users/tirthankar25/chicago');
print(Raw)
var bandsel=Raw.select(0)
//var bandsel=Raw.select('LST_Day_1km')

//var filtered=Raw.filterDate('2002-12-30','2004-4-27');
//print(filtered)
//var limited=Raw.limit(50);
//print(limited)

//print(bandsel)
var mean=bandsel.mean();
Map.addLayer(mean);
//var clipped=mean.clip(ROI);
//var calculate=clipped.multiply(.02).subtract(273.15);
//Map.addLayer(calculate,{min: 30, max: 40, palette: ['blue', 'green', 'red']},'LST')
//var mask=calculate.gt(30.8)
//Map.addLayer(mask,{},"mask")
//var Masked=clipped.mask(mask)
//Map.addLayer(Masked,{min: 20, max: 30, palette: ['blue', 'green', 'red']},'LST_masked')

//var filtered=Raw.filterDate('2002-12-30','2004-4-27');
//print(filtered)

//Image to table example

var urban=ee.FeatureCollection('users/tirthankar25/chicago');
//Function to find mean of pixels in region of interest
var regions = function(image){ return image.reduceRegions({collection: urban, reducer: ee.Reducer.mean(), scale: 1000, }); }
//Load image
var image=ee.ImageCollection('MODIS/MYD13A1').filterDate('2002-07-08', '2017-07-08').mean().select("NDVI");
print(image)
//.select("Albedo_BSA_shortwave").multiply(.001)
//.select('avg_rad')
//.select('cf_cvg')
//.select('ET').multiply(.1)
var Final = regions(image);

//var Final=Final.select(['mean','nbhd_code', 'nbhd'],['Albedo','nbhd_code', 'nbhd']);
//Export image
Export.table.toDrive({
collection: Final,  description: 'NDVI_all',  fileFormat: 'CSV'
});

//Timelapse example (based on google API example)

var TheGEOMETRY = ee.Geometry.Rectangle([55.1, 25, 55.4, 25.4]);
Map.addLayer(TheGEOMETRY)
var AllIMAGES   = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
//Filter row and path such that they cover Dubai.
.filter(ee.Filter.eq('WRS_PATH', 160))
  .filter(ee.Filter.eq('WRS_ROW', 43))
   // Filter cloudy scenes
  .filter(ee.Filter.lt('CLOUD_COVER', 30))
  // Get required years of imagery.
  .filterDate('1984-01-01','2012-12-30')
  // Select 3-band imagery for the video.
  .select(['B4', 'B3', 'B2'])
  //Make the data 8 bit
  .map(function(image) {

    return image.multiply(512).uint8();
  });

Export.video.toDrive({
  collection: AllIMAGES,
  //Name of file
  description: 'Dubai_timelapse',
  //Quality of video
  dimensions: 720,
  //FPS of video
  framesPerSecond: 8,
  //Region of export
  region: TheGEOMETRY
});<commit_msg>Update Sample.js<commit_after>//  Geometries

Map.setCenter(-88, 41.8, 9)

function multi (feature){
  //  Reduce number of vertices in geometry; the number is to specify maximum error in meters
  var simple = feature.simplify(1000);
  //  Find centroid of geometry
  var center = simple.centroid();
  //  Create buffer around geometry; the number represents the width of buffer in meters
  var buff = center.buffer(500);
  //  return variable from function
  return buff}

//  Load Feature Collection of the dissolved boundary of Chicago stored in assets
var Chic=ee.FeatureCollection('users/tirthankar25/chicago_diss');
//  Load Feature Collection of the neighborhood-scale Chicago data stored in assets
//  var Chic_coll=ee.FeatureCollection('users/tirthankar25/chicago');
//  Map function over Feature Collection
//  var Res=Chic_coll.map(multi);
//  Add the layer to the map
/ /Map.addLayer(Res)

Map.addLayer(Chic, {},'Chicago dissolved')
//  Find the rectangle that emcompasses the southernmost, westernmost, easternmost, and northernmost
//  points of the feature
//  var bound = Chic.geometry().bounds();
//  Find the polygon covering the extremities of the feature
//  var convex = Chic.geometry().convexHull();
//  Map.addLayer(bound, {},'Chicago bounds');
//  Map.addLayer(convex, {},'Chicago convex hull');

//  Find the area common to two or more features
//  var Intersect=bound.intersection(convex,100);
//  Map.addLayer(Intersect, {},'Bound and convex intersection');

//  Find the area encompassing two or more features; number is the maximum error in meters
//  var Union=bound.union(convex,100);
//  Map.addLayer(Union, {},'Bound and convex union');

//  Find area of feature
//  var Ar=Chic.geometry().area();
//  Find length of line geometry
//  var length=Chic.geometry().length();
//  Find permeter of feature
//  var peri=Chic.geometry().perimeter();
//  print (peri)

//  Features

//  Create Geometry
var var_Geometry=ee.Geometry.Polygon(0,0, 40,30, 20, 20, 0, 0);
//  Create Feature from Geometry
var var_Feature = ee.Feature(var_Geometry, {Name: ["Feature name","Supreme"], Size: [500, 1000]});
//  Get values of a property
//  var Arr=var_Feature.get('Size');
//  print (Arr)
//  Select a subset of properties and rename them
var var_Featurenew = var_Feature.select(["Name"], ["Descriptor"]);
print(var_Featurenew)

//  Images

Map.setCenter(-88, 41.8, 9)
var Raw = ee.ImageCollection('MODIS/006/MYD11A2');
var ROI = ee.FeatureCollection('users/tirthankar25/chicago');
print(Raw)
var bandsel=Raw.select(0)
//  var bandsel=Raw.select('LST_Day_1km')

//  var filtered=Raw.filterDate('2002-12-30','2004-4-27');
//  print(filtered)
//  var limited=Raw.limit(50);
//  print(limited)

//  print(bandsel)
var mean=bandsel.mean();
Map.addLayer(mean);
//  var clipped=mean.clip(ROI);
//  var calculate=clipped.multiply(.02).subtract(273.15);
//  Map.addLayer(calculate,{min: 30, max: 40, palette: ['blue', 'green', 'red']},'LST')
//  var mask=calculate.gt(30.8)
//  Map.addLayer(mask,{},"mask")
//  var Masked=clipped.mask(mask)
//  Map.addLayer(Masked,{min: 20, max: 30, palette: ['blue', 'green', 'red']},'LST_masked')

//  var filtered=Raw.filterDate('2002-12-30','2004-4-27');
//  print(filtered)

//  Image to table example

var urban=ee.FeatureCollection('users/tirthankar25/chicago');
//  Function to find mean of pixels in region of interest
var regions = function(image){ return image.reduceRegions({collection: urban, reducer: ee.Reducer.mean(), scale: 1000, }); }
//  Load image
var image=ee.ImageCollection('MODIS/MYD13A1').filterDate('2002-07-08', '2017-07-08').mean().select("NDVI");
print(image)
//  .select("Albedo_BSA_shortwave").multiply(.001)
//  .select('avg_rad')
//  .select('cf_cvg')
//  .select('ET').multiply(.1)
var Final = regions(image);

//  var Final=Final.select(['mean','nbhd_code', 'nbhd'],['Albedo','nbhd_code', 'nbhd']);
//  Export image
Export.table.toDrive({
collection: Final,  description: 'NDVI_all',  fileFormat: 'CSV'});

//  Timelapse example (based on google API example)

var TheGEOMETRY = ee.Geometry.Rectangle([55.1, 25, 55.4, 25.4]);
Map.addLayer(TheGEOMETRY)
var AllIMAGES   = ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
//  Filter row and path such that they cover Dubai.
.filter(ee.Filter.eq('WRS_PATH', 160))
  .filter(ee.Filter.eq('WRS_ROW', 43))
   // Filter cloudy scenes
  .filter(ee.Filter.lt('CLOUD_COVER', 30))
  // Get required years of imagery.
  .filterDate('1984-01-01','2012-12-30')
  // Select 3-band imagery for the video.
  .select(['B4', 'B3', 'B2'])
  //  Make the data 8 bit
  .map(function(image) {

    return image.multiply(512).uint8()});

Export.video.toDrive({
  collection: AllIMAGES,
  //  Name of file
  description: 'Dubai_timelapse',
  //  Quality of video
  dimensions: 720,
  //  FPS of video
  framesPerSecond: 8,
  //  Region of export
  region: TheGEOMETRY});
<|endoftext|>


<commit_before>// Lists

'use strict';

// Search `[-+*][\n ]`, returns next pos arter marker on success
// or -1 on fail.
function skipBulletListMarker(state, startLine) {
  var marker, pos, max;

  pos = state.bMarks[startLine] + state.tShift[startLine];
  max = state.eMarks[startLine];

  if (pos >= max) { return -1; }

  marker = state.src.charCodeAt(pos++);
  // Check bullet
  if (marker !== 0x2A/* * */ &&
      marker !== 0x2D/* - */ &&
      marker !== 0x2B/* + */) {
    return -1;
  }

  if (pos < max && state.src.charCodeAt(pos) !== 0x20) {
    // " 1.test " - is not a list item
    return -1;
  }

  return pos;
}

// Search `\d+[.)][\n ]`, returns next pos arter marker on success
// or -1 on fail.
function skipOrderedListMarker(state, startLine) {
  var ch,
      pos = state.bMarks[startLine] + state.tShift[startLine],
      max = state.eMarks[startLine];

  if (pos + 1 >= max) { return -1; }

  ch = state.src.charCodeAt(pos++);

  if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1; }

  for (;;) {
    // EOL -> fail
    if (pos >= max) { return -1; }

    ch = state.src.charCodeAt(pos++);

    if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
      continue;
    }

    // found valid marker
    if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
      break;
    }

    return -1;
  }

  if (pos < max && state.src.charCodeAt(pos) !== 0x20/* space */) {
    // " 1.test " - is not a list item
    return -1;
  }
  return pos;
}

module.exports = function list(state, startLine, endLine, silent) {
  var nextLine,
      indent,
      oldTShift,
      oldIndent,
      oldTight,
      oldParentType,
      start,
      posAfterMarker,
      max,
      indentAfterMarker,
      markerValue,
      markerCharCode,
      isOrdered,
      contentStart,
      listTokIdx,
      prevEmptyEnd,
      listLines,
      itemLines,
      tight = true,
      terminatorRules = state.parser._rulesListTerm,
      i, l, terminate, level, tokens;

  // Detect list type and position after marker
  if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
    isOrdered = true;
  } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {
    isOrdered = false;
  } else {
    return false;
  }

  if (state.level >= state.options.maxNesting) { return false; }

  // We should terminate list on style change. Remember first one to compare.
  markerCharCode = state.src.charCodeAt(posAfterMarker - 1);

  // For validation mode we can terminate immediately
  if (silent) { return true; }

  // Start list
  listTokIdx = state.tokens.length;

  if (isOrdered) {
    start = state.bMarks[startLine] + state.tShift[startLine];
    markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));

    state.tokens.push({
      type: 'ordered_list_open',
      order: markerValue,
      lines: listLines = [ startLine, 0 ],
      level: state.level++
    });

  } else {
    state.tokens.push({
      type: 'bullet_list_open',
      lines: listLines = [ startLine, 0 ],
      level: state.level++
    });
  }

  //
  // Iterate list items
  //

  nextLine = startLine;
  prevEmptyEnd = false;

  while (nextLine < endLine) {
    contentStart = state.skipSpaces(posAfterMarker);
    max = state.eMarks[nextLine];

    if (contentStart >= max) {
      // trimming space in "-    \n  3" case, indent is 1 here
      indentAfterMarker = 1;
    } else {
      indentAfterMarker = contentStart - posAfterMarker;
    }

    // If we have more than 4 spaces, the indent is 1
    // (the rest is just indented code block)
    if (indentAfterMarker > 4) { indentAfterMarker = 1; }

    // If indent is less than 1, assume that it's one, example:
    //  "-\n  test"
    if (indentAfterMarker < 1) { indentAfterMarker = 1; }

    // "  -  test"
    //  ^^^^^ - calculating total length of this thing
    indent = (posAfterMarker - state.bMarks[nextLine]) + indentAfterMarker;

    // Run subparser & write tokens
    state.tokens.push({
      type: 'list_item_open',
      lines: itemLines = [ startLine, 0 ],
      level: state.level++
    });

    //nextLine++;

    oldIndent = state.blkIndent;
    oldTight = state.tight;
    oldTShift = state.tShift[startLine];
    oldParentType = state.parentType;
    state.tShift[startLine] = contentStart - state.bMarks[startLine];
    state.blkIndent = indent;
    state.tight = true;
    state.parentType = 'list';

    state.parser.tokenize(state, startLine, endLine, true);

    // If any of list item is tight, mark list as tight
    if (!state.tight || prevEmptyEnd) {
      tight = false;
    }
    // Item become loose if finish with empty line,
    // but we should filter last element, because it means list finish
    prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);

    state.blkIndent = oldIndent;
    state.tShift[startLine] = oldTShift;
    state.tight = oldTight;
    state.parentType = oldParentType;

    state.tokens.push({
      type: 'list_item_close',
      level: --state.level
    });

    nextLine = startLine = state.line;
    itemLines[1] = nextLine;
    contentStart = state.bMarks[startLine];

    if (nextLine >= endLine) { break; }

    if (state.isEmpty(nextLine)) {
      break;
    }

    //
    // Try to check if list is terminated or continued.
    //
    if (state.tShift[nextLine] < state.blkIndent) { break; }

    // fail if terminating block found
    terminate = false;
    for (i = 0, l = terminatorRules.length; i < l; i++) {
      if (terminatorRules[i](state, nextLine, endLine, true)) {
        terminate = true;
        break;
      }
    }
    if (terminate) { break; }

    // fail if list has another type
    if (isOrdered) {
      posAfterMarker = skipOrderedListMarker(state, nextLine);
      if (posAfterMarker < 0) { break; }
    } else {
      posAfterMarker = skipBulletListMarker(state, nextLine);
      if (posAfterMarker < 0) { break; }
    }

    if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break; }
  }

  // Finilize list
  state.tokens.push({
    type: isOrdered ? 'ordered_list_close' : 'bullet_list_close',
    level: --state.level
  });
  listLines[1] = nextLine;

  state.line = nextLine;

  // mark paragraphs tight if needed
  if (tight) {
    level = state.level + 2;
    tokens = state.tokens;

    for (i = listTokIdx + 2, l = tokens.length - 2; i < l; i++) {
      if (tokens[i].level === level && tokens[i].type === 'paragraph_open') {
        tokens[i].tight = true;
        i += 2;
        tokens[i].tight = true;
      }
    }
  }

  return true;
};
<commit_msg>Moved tight paragraphs marking to separate fn<commit_after>// Lists

'use strict';

// Search `[-+*][\n ]`, returns next pos arter marker on success
// or -1 on fail.
function skipBulletListMarker(state, startLine) {
  var marker, pos, max;

  pos = state.bMarks[startLine] + state.tShift[startLine];
  max = state.eMarks[startLine];

  if (pos >= max) { return -1; }

  marker = state.src.charCodeAt(pos++);
  // Check bullet
  if (marker !== 0x2A/* * */ &&
      marker !== 0x2D/* - */ &&
      marker !== 0x2B/* + */) {
    return -1;
  }

  if (pos < max && state.src.charCodeAt(pos) !== 0x20) {
    // " 1.test " - is not a list item
    return -1;
  }

  return pos;
}

// Search `\d+[.)][\n ]`, returns next pos arter marker on success
// or -1 on fail.
function skipOrderedListMarker(state, startLine) {
  var ch,
      pos = state.bMarks[startLine] + state.tShift[startLine],
      max = state.eMarks[startLine];

  if (pos + 1 >= max) { return -1; }

  ch = state.src.charCodeAt(pos++);

  if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1; }

  for (;;) {
    // EOL -> fail
    if (pos >= max) { return -1; }

    ch = state.src.charCodeAt(pos++);

    if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
      continue;
    }

    // found valid marker
    if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
      break;
    }

    return -1;
  }

  if (pos < max && state.src.charCodeAt(pos) !== 0x20/* space */) {
    // " 1.test " - is not a list item
    return -1;
  }
  return pos;
}

function markTightParagraphs(state, idx) {
  var i, l,
      level = state.level + 2;

  for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
    if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
      state.tokens[i + 2].tight = true;
      state.tokens[i].tight = true;
      i += 2;
    }
  }
}

module.exports = function list(state, startLine, endLine, silent) {
  var nextLine,
      indent,
      oldTShift,
      oldIndent,
      oldTight,
      oldParentType,
      start,
      posAfterMarker,
      max,
      indentAfterMarker,
      markerValue,
      markerCharCode,
      isOrdered,
      contentStart,
      listTokIdx,
      prevEmptyEnd,
      listLines,
      itemLines,
      tight = true,
      terminatorRules = state.parser._rulesListTerm,
      i, l, terminate;

  // Detect list type and position after marker
  if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
    isOrdered = true;
  } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {
    isOrdered = false;
  } else {
    return false;
  }

  if (state.level >= state.options.maxNesting) { return false; }

  // We should terminate list on style change. Remember first one to compare.
  markerCharCode = state.src.charCodeAt(posAfterMarker - 1);

  // For validation mode we can terminate immediately
  if (silent) { return true; }

  // Start list
  listTokIdx = state.tokens.length;

  if (isOrdered) {
    start = state.bMarks[startLine] + state.tShift[startLine];
    markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));

    state.tokens.push({
      type: 'ordered_list_open',
      order: markerValue,
      lines: listLines = [ startLine, 0 ],
      level: state.level++
    });

  } else {
    state.tokens.push({
      type: 'bullet_list_open',
      lines: listLines = [ startLine, 0 ],
      level: state.level++
    });
  }

  //
  // Iterate list items
  //

  nextLine = startLine;
  prevEmptyEnd = false;

  while (nextLine < endLine) {
    contentStart = state.skipSpaces(posAfterMarker);
    max = state.eMarks[nextLine];

    if (contentStart >= max) {
      // trimming space in "-    \n  3" case, indent is 1 here
      indentAfterMarker = 1;
    } else {
      indentAfterMarker = contentStart - posAfterMarker;
    }

    // If we have more than 4 spaces, the indent is 1
    // (the rest is just indented code block)
    if (indentAfterMarker > 4) { indentAfterMarker = 1; }

    // If indent is less than 1, assume that it's one, example:
    //  "-\n  test"
    if (indentAfterMarker < 1) { indentAfterMarker = 1; }

    // "  -  test"
    //  ^^^^^ - calculating total length of this thing
    indent = (posAfterMarker - state.bMarks[nextLine]) + indentAfterMarker;

    // Run subparser & write tokens
    state.tokens.push({
      type: 'list_item_open',
      lines: itemLines = [ startLine, 0 ],
      level: state.level++
    });

    //nextLine++;

    oldIndent = state.blkIndent;
    oldTight = state.tight;
    oldTShift = state.tShift[startLine];
    oldParentType = state.parentType;
    state.tShift[startLine] = contentStart - state.bMarks[startLine];
    state.blkIndent = indent;
    state.tight = true;
    state.parentType = 'list';

    state.parser.tokenize(state, startLine, endLine, true);

    // If any of list item is tight, mark list as tight
    if (!state.tight || prevEmptyEnd) {
      tight = false;
    }
    // Item become loose if finish with empty line,
    // but we should filter last element, because it means list finish
    prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);

    state.blkIndent = oldIndent;
    state.tShift[startLine] = oldTShift;
    state.tight = oldTight;
    state.parentType = oldParentType;

    state.tokens.push({
      type: 'list_item_close',
      level: --state.level
    });

    nextLine = startLine = state.line;
    itemLines[1] = nextLine;
    contentStart = state.bMarks[startLine];

    if (nextLine >= endLine) { break; }

    if (state.isEmpty(nextLine)) {
      break;
    }

    //
    // Try to check if list is terminated or continued.
    //
    if (state.tShift[nextLine] < state.blkIndent) { break; }

    // fail if terminating block found
    terminate = false;
    for (i = 0, l = terminatorRules.length; i < l; i++) {
      if (terminatorRules[i](state, nextLine, endLine, true)) {
        terminate = true;
        break;
      }
    }
    if (terminate) { break; }

    // fail if list has another type
    if (isOrdered) {
      posAfterMarker = skipOrderedListMarker(state, nextLine);
      if (posAfterMarker < 0) { break; }
    } else {
      posAfterMarker = skipBulletListMarker(state, nextLine);
      if (posAfterMarker < 0) { break; }
    }

    if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break; }
  }

  // Finilize list
  state.tokens.push({
    type: isOrdered ? 'ordered_list_close' : 'bullet_list_close',
    level: --state.level
  });
  listLines[1] = nextLine;

  state.line = nextLine;

  // mark paragraphs tight if needed
  if (tight) {
    markTightParagraphs(state, listTokIdx);
  }

  return true;
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { ScrollView, Text, View } from 'react-native';
import styles from '../helpers/Styles';
import { createHeader } from '../helpers/NavigationOptions';

export default class ProfittiInfoScreen extends Component {
  static navigationOptions = {
    header: createHeader('Profitti')
  };

  render() {
    return (
      <ScrollView style={styles.background}>
        <View style={styles.container}>
          <Text style={[styles.text, styles.title]}>Puheenjohtajan terveiset</Text>
          <Text style={styles.text}>Arvon tradenomikollega,</Text>
          <Text style={styles.text}>onnittelen sinua, sillä edessäsi on maailman ensimmäinen
            tradenomiopiskelijaliiton laulukirja. En tiedä tuoksuuko edessä oleva kappaleesi tuoreelle painomusteelle
            vai sitseillä läikkyneelle snapsille, mutta tärkeintä ovat tulevat laulukerrat ja hyvät hetket, joita tämän
            kirjan ääressä tulet viettämään.</Text>
          <Text style={styles.text}>Opiskelijalaulujen perinteet ovat olleet keskuudessamme jo
            pitkään, mutta vasta vuonna 2014 aloimme koota laulukirjaa niin tutuista kuin hieman tuoreemmistakin
            veisuista. Kokoamistyöstä tahdon erityisesti kiittää Tradenomiopiskelijaliiton vuoden 2014 liittohallitusta,
            joka teki Elias Lönnrotin kaltaista työtä kulkiessaan ja kerätessään lauluja kansien väliin. Suuri kiitos
            menee myös niille tradenomiopiskelijoille, jotka esittivät kappaleita tai ovat yksinkertaisesti olleet
            mukana laulamassa niitä. Lauluperinteemme ja kirjamme voima syntyy sen ahkerasta käytöstä, joten
            laulakaa!</Text>
          <Text style={[styles.text, styles.textTight]}>Anssi Ketopaikka</Text>
          <Text style={[styles.text, styles.textTight]}>puheenjohtaja</Text>
          <Text style={[styles.text]}>Tradenomiopiskelijaliitto TROL ry</Text>
        </View>

        <View style={[styles.container, styles.containerLast]}>
          <Text style={[styles.text, styles.title]}>Laulukirjatyöryhmän terveiset</Text>
          <Text style={styles.text}>Ave, tradenomi!</Text>
          <Text style={styles.text}>Käsissäsi on pala historiaa: Tradenomiopiskelijaliitto TROL
            ry:n ensimmäinen laulukirja, Profitti. Profitti on tärkeä palanen tradenomi-identiteetin ja -perinteen
            ainaisessa kehityksessä. Sen kansien sisään on koottu tradenomiopiskelijoiden lauluja sekä
            paikallisyhdistysten perinteitä ympäri Suomen, ja kiitos tästä kuuluu kaikille työhön
            osallistuneille.</Text>
          <Text style={styles.text}>Profitin myötä tradenomiopiskelijoiden kulttuuri saa yhden
            fyysisen muodon. Nyt voimme puhua meidän lauluista, meidän laulukirjasta ja meidän opiskelijakulttuurista.
            Tämän historiallisen teoksen myötä osa meidän yhteistä kulttuuriamme on ajan hampaan ja muistia pimentävien
            iltojen tavoittamattomissa. Samalla myös sinun vastuusi, hyvä lukija, tämän kulttuuriperinnön vaalimiseen ja
            levittämiseen on suurempi kuin koskaan.</Text>
          <Text style={styles.text}>Kaikki ne hienot hetket, joissa tämä kirja on mukana, on osa
            tuota tradenomiopiskelijoiden kulttuuriperintöä. Me laulukirjatyöryhmän jäsenet luotammekin sinuun, että
            otat Profitista ja opiskeluajastasi kaiken irti!</Text>
          <Text style={[styles.text, styles.textTight]}>“To you from failing hands we throw the torch,</Text>
          <Text style={styles.text}>be yours to hold it high.” - In Flanders Fields</Text>
          <Text style={[styles.text, styles.textTight]}>Laulukirjatyöryhmä</Text>
          <Text style={[styles.text, styles.textTight]}>Osmo Ahonen</Text>
          <Text style={[styles.text, styles.textTight]}>Hannes Leppäkangas</Text>
          <Text style={[styles.text]}>Teemu Tiilikainen</Text>
        </View>
      </ScrollView>
    );
  }
}
<commit_msg>Add years to Profitti info page<commit_after>import React, { Component } from 'react';
import { ScrollView, Text, View } from 'react-native';
import styles from '../helpers/Styles';
import { createHeader } from '../helpers/NavigationOptions';

export default class ProfittiInfoScreen extends Component {
  static navigationOptions = {
    header: createHeader('Profitti')
  };

  render() {
    return (
      <ScrollView style={styles.background}>
        <View style={styles.container}>
          <Text style={[styles.text, styles.title]}>Puheenjohtajan terveiset</Text>
          <Text style={styles.text}>Arvon tradenomikollega,</Text>
          <Text style={styles.text}>onnittelen sinua, sillä edessäsi on maailman ensimmäinen
            tradenomiopiskelijaliiton laulukirja. En tiedä tuoksuuko edessä oleva kappaleesi tuoreelle painomusteelle
            vai sitseillä läikkyneelle snapsille, mutta tärkeintä ovat tulevat laulukerrat ja hyvät hetket, joita tämän
            kirjan ääressä tulet viettämään.</Text>
          <Text style={styles.text}>Opiskelijalaulujen perinteet ovat olleet keskuudessamme jo
            pitkään, mutta vasta vuonna 2014 aloimme koota laulukirjaa niin tutuista kuin hieman tuoreemmistakin
            veisuista. Kokoamistyöstä tahdon erityisesti kiittää Tradenomiopiskelijaliiton vuoden 2014 liittohallitusta,
            joka teki Elias Lönnrotin kaltaista työtä kulkiessaan ja kerätessään lauluja kansien väliin. Suuri kiitos
            menee myös niille tradenomiopiskelijoille, jotka esittivät kappaleita tai ovat yksinkertaisesti olleet
            mukana laulamassa niitä. Lauluperinteemme ja kirjamme voima syntyy sen ahkerasta käytöstä, joten
            laulakaa!</Text>
          <Text style={[styles.text, styles.textTight]}>Anssi Ketopaikka</Text>
          <Text style={[styles.text, styles.textTight]}>Puheenjohtaja 2014</Text>
          <Text style={[styles.text]}>Tradenomiopiskelijaliitto TROL ry</Text>
        </View>

        <View style={[styles.container, styles.containerLast]}>
          <Text style={[styles.text, styles.title]}>Laulukirjatyöryhmän terveiset</Text>
          <Text style={styles.text}>Ave, tradenomi!</Text>
          <Text style={styles.text}>Käsissäsi on pala historiaa: Tradenomiopiskelijaliitto TROL
            ry:n ensimmäinen laulukirja, Profitti. Profitti on tärkeä palanen tradenomi-identiteetin ja -perinteen
            ainaisessa kehityksessä. Sen kansien sisään on koottu tradenomiopiskelijoiden lauluja sekä
            paikallisyhdistysten perinteitä ympäri Suomen, ja kiitos tästä kuuluu kaikille työhön
            osallistuneille.</Text>
          <Text style={styles.text}>Profitin myötä tradenomiopiskelijoiden kulttuuri saa yhden
            fyysisen muodon. Nyt voimme puhua meidän lauluista, meidän laulukirjasta ja meidän opiskelijakulttuurista.
            Tämän historiallisen teoksen myötä osa meidän yhteistä kulttuuriamme on ajan hampaan ja muistia pimentävien
            iltojen tavoittamattomissa. Samalla myös sinun vastuusi, hyvä lukija, tämän kulttuuriperinnön vaalimiseen ja
            levittämiseen on suurempi kuin koskaan.</Text>
          <Text style={styles.text}>Kaikki ne hienot hetket, joissa tämä kirja on mukana, on osa
            tuota tradenomiopiskelijoiden kulttuuriperintöä. Me laulukirjatyöryhmän jäsenet luotammekin sinuun, että
            otat Profitista ja opiskeluajastasi kaiken irti!</Text>
          <Text style={[styles.text, styles.textTight]}>“To you from failing hands we throw the torch,</Text>
          <Text style={styles.text}>be yours to hold it high.” - In Flanders Fields</Text>
          <Text style={[styles.text, styles.textTight]}>Laulukirjatyöryhmä 2014</Text>
          <Text style={[styles.text, styles.textTight]}>Osmo Ahonen</Text>
          <Text style={[styles.text, styles.textTight]}>Hannes Leppäkangas</Text>
          <Text style={[styles.text]}>Teemu Tiilikainen</Text>
        </View>
      </ScrollView>
    );
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import Wizard from 'components/MaterialDashboardPro/Wizard'
import Step1 from './WizardSteps/Step1'
import Step2 from './WizardSteps/Step2'
import Step3 from './WizardSteps/Step3'

// redux
import { connect } from 'react-redux'
import { createWallet, setWalletSaved } from 'store/modules/components/CreateWallet'
import { setAcceptTermsAndConditions } from 'store/modules/components/SignupWizard'
import { readMyReputation } from 'store/modules/data/reputation'
import { setWallet, setWalletToCreatedWallet } from 'store/modules/data/wallet'
import { toastr } from 'react-redux-toastr'
import { push } from 'react-router-redux'
import { submit } from 'redux-form'

// helpers
import { downloadWallet as downloadWalletFile } from 'helpers/wallet'
import { get, pick, isEmpty } from 'lodash'
import { geocode } from 'helpers/geocode';
import profileProvider from 'helpers/profileProvider';

class SignupWizard extends Component {
  constructor(props) {
    super(props);

    this.state = {
      signupType: undefined, // "user" or "business"
      profile: {}
    };
  }

  componentDidMount() {
    this.refreshReputation()
  }

  componentWillReceiveProps(newProps) {
    const newDidID = get(newProps, 'wallet.did.didDocument.id', null)
    const oldDidID = get(this.props, 'wallet.did.didDocument.id', null)
    if (newDidID !== oldDidID) {
      this.refreshReputation()
    }
  }

  refreshReputation() {
    if (!this.props.reputationLoading) this.props.readMyReputation()
  }

  async downloadWallet() {
    console.log('downloadWallet executing SignupWizard index.js file.');
    const { wallet, walletCreated, setWalletSaved } = this.props

    if (wallet && wallet.did) {
      downloadWalletFile(pick(wallet, ['did', 'bitcoinMnemonic', 'testnet']))
    } else {
      let profile = { ...this.state.profile };

      if (profile.businesslocation) {
        // Pre-cache geo coords for location.
        // TODO: perhaps this could be done on the marketplace server, to ensure coords line up with the location text.
        try {
          let coords = await geocode(profile.businesslocation);

          if (coords) {
            profile = {
              ...profile,
              businesslocationgeo: {
                latitude: coords.latitude,
                longitude: coords.longitude,
                bounds: coords.bounds
              }
            }
          }
        } catch (err) {
          // Let's not break up the signup flow with API errors.
          console.error(err);
        }
      }

      profileProvider.setProfile(walletCreated.did.publicDidDocument.id, {
        ...profile,
        'AIRDROP_LEVEL': 'ZERO'
      });

      downloadWalletFile(walletCreated)
    }

    setWalletSaved(true)
  }

  areWalletKeysSaved() {
    const { walletSaved } = this.props
    return walletSaved
  }

  validate(step) {
    const { wallet, crawlerRunning, acceptedTerms } = this.props
    if (crawlerRunning) return false
    if (step === 0 && !acceptedTerms && !(this.areWalletKeysSaved() || (wallet && wallet.did))) {
      toastr.warning(
        'Terms and Conditions',
        'Please read and accept the Terms and Conditions before continuing'
      )
      return false
    }
    if (step === 1 && !(this.areWalletKeysSaved() || (wallet && wallet.did))) {
      toastr.warning(
        'Please save your Wallet Keys',
        'Once you have saved the file you will be able to continue'
      )
      return false
    }
    return true
  }

  onChangeStep(from, to) {
    const { walletCreated, createWallet } = this.props
    if (to === 1 && !walletCreated) {
      createWallet()
    }
  }

  onSignupTypeChange = (signupType) => {
    this.setState({
      signupType: signupType
    });
  }

  onProfileFieldChange = (fieldName, fieldValue) => {
    console.log("onProfileFieldChange executing for fieldName: "+fieldName+" with fieldValue: "+fieldValue)
    this.setState(state => {
      state.profile[fieldName] = fieldValue;
      return state;
    });
  }

  finishClicked() {
    const { walletCreated } = this.props

    // Check if signup is in progress
    if (get(walletCreated, 'did.publicDidDocument.id')) {
      this.props.setWalletToCreatedWallet() // logs in user
      // update user vendor profile on marketplace
      const isBusiness = this.state.signupType === "business"
      profileProvider.updateProfile(walletCreated.did.publicDidDocument.id, {
        'type': isBusiness ? 'business' : 'individual'
      });
    }

    toastr.success(
      'Congratulations',
      'You have completed the first airdrop task and earned 1 Chlu bonus token. You will be awarded the Chlu token post our public sale'
    )
  }

  render() {
    const { wallet, crawlerRunning } = this.props
    const initialStep = wallet.did ? 1 : 0

    return (
      <Wizard
        validate={this.validate.bind(this)}
        currentStep={initialStep}
        onChangeStep={this.onChangeStep.bind(this)}
        finishButtonClick={this.finishClicked.bind(this)}
        nextButtonDisabled={crawlerRunning}
        previousButtonDisabled={crawlerRunning}
        steps={[
          {
            stepName: 'Step 1: Create Your Account',
            stepComponent: Step1,
            stepId: 'get started',
            stepProps: {
              ...this.props,
              onSignupTypeChange: this.onSignupTypeChange,
              onProfileFieldChange: this.onProfileFieldChange
            }
          },
          {
            stepName: this.state.signupType === "business" ? 'Step 2: Import Existing Reviews' : 'Step 2: Become A Trusted Reviewer',
            stepComponent: this.state.signupType === "business" ? Step3 : Step2,
            stepId: 'about',
            stepProps: {
              ...this.props,
              onProfileFieldChange: this.onProfileFieldChange,
              downloadWallet: this.downloadWallet.bind(this)
            }
          }
        ]}
        title="Let's Get Started"
        subtitle='Follow The Three Easy Steps Below To Begin'
      />
    )
  }
}

const mapStateToProps = store => ({
  loading: store.components.createWallet.loading,
  walletSaved: store.components.createWallet.walletSaved,
  walletCreated: store.components.createWallet.walletCreated,
  wallet: store.data.wallet,
  reviews: store.data.reputation.reviews,
  reputationLoading: store.data.reputation.loading,
  crawlerRunning: store.data.crawler.running,
  acceptedTerms: store.components.signupWizard.acceptedTerms
})

const mapDispatchToProps = {
  createWallet,
  setWallet,
  setWalletSaved,
  setWalletToCreatedWallet,
  readMyReputation,
  setAcceptTermsAndConditions,
  push,
  submit
}

export default connect(mapStateToProps, mapDispatchToProps)(SignupWizard)
<commit_msg>add note about redirect on signup finish<commit_after>import React, { Component } from 'react'
import Wizard from 'components/MaterialDashboardPro/Wizard'
import Step1 from './WizardSteps/Step1'
import Step2 from './WizardSteps/Step2'
import Step3 from './WizardSteps/Step3'

// redux
import { connect } from 'react-redux'
import { createWallet, setWalletSaved } from 'store/modules/components/CreateWallet'
import { setAcceptTermsAndConditions } from 'store/modules/components/SignupWizard'
import { readMyReputation } from 'store/modules/data/reputation'
import { setWallet, setWalletToCreatedWallet } from 'store/modules/data/wallet'
import { toastr } from 'react-redux-toastr'
import { push } from 'react-router-redux'
import { submit } from 'redux-form'

// helpers
import { downloadWallet as downloadWalletFile } from 'helpers/wallet'
import { get, pick, isEmpty } from 'lodash'
import { geocode } from 'helpers/geocode';
import profileProvider from 'helpers/profileProvider';

class SignupWizard extends Component {
  constructor(props) {
    super(props);

    this.state = {
      signupType: undefined, // "user" or "business"
      profile: {}
    };
  }

  componentDidMount() {
    this.refreshReputation()
  }

  componentWillReceiveProps(newProps) {
    const newDidID = get(newProps, 'wallet.did.didDocument.id', null)
    const oldDidID = get(this.props, 'wallet.did.didDocument.id', null)
    if (newDidID !== oldDidID) {
      this.refreshReputation()
    }
  }

  refreshReputation() {
    if (!this.props.reputationLoading) this.props.readMyReputation()
  }

  async downloadWallet() {
    console.log('downloadWallet executing SignupWizard index.js file.');
    const { wallet, walletCreated, setWalletSaved } = this.props

    if (wallet && wallet.did) {
      downloadWalletFile(pick(wallet, ['did', 'bitcoinMnemonic', 'testnet']))
    } else {
      let profile = { ...this.state.profile };

      if (profile.businesslocation) {
        // Pre-cache geo coords for location.
        // TODO: perhaps this could be done on the marketplace server, to ensure coords line up with the location text.
        try {
          let coords = await geocode(profile.businesslocation);

          if (coords) {
            profile = {
              ...profile,
              businesslocationgeo: {
                latitude: coords.latitude,
                longitude: coords.longitude,
                bounds: coords.bounds
              }
            }
          }
        } catch (err) {
          // Let's not break up the signup flow with API errors.
          console.error(err);
        }
      }

      profileProvider.setProfile(walletCreated.did.publicDidDocument.id, {
        ...profile,
        'AIRDROP_LEVEL': 'ZERO'
      });

      downloadWalletFile(walletCreated)
    }

    setWalletSaved(true)
  }

  areWalletKeysSaved() {
    const { walletSaved } = this.props
    return walletSaved
  }

  validate(step) {
    const { wallet, crawlerRunning, acceptedTerms } = this.props
    if (crawlerRunning) return false
    if (step === 0 && !acceptedTerms && !(this.areWalletKeysSaved() || (wallet && wallet.did))) {
      toastr.warning(
        'Terms and Conditions',
        'Please read and accept the Terms and Conditions before continuing'
      )
      return false
    }
    if (step === 1 && !(this.areWalletKeysSaved() || (wallet && wallet.did))) {
      toastr.warning(
        'Please save your Wallet Keys',
        'Once you have saved the file you will be able to continue'
      )
      return false
    }
    return true
  }

  onChangeStep(from, to) {
    const { walletCreated, createWallet } = this.props
    if (to === 1 && !walletCreated) {
      createWallet()
    }
  }

  onSignupTypeChange = (signupType) => {
    this.setState({
      signupType: signupType
    });
  }

  onProfileFieldChange = (fieldName, fieldValue) => {
    console.log("onProfileFieldChange executing for fieldName: "+fieldName+" with fieldValue: "+fieldValue)
    this.setState(state => {
      state.profile[fieldName] = fieldValue;
      return state;
    });
  }

  finishClicked() {
    const { walletCreated } = this.props

    // Check if signup is in progress
    if (get(walletCreated, 'did.publicDidDocument.id')) {
      this.props.setWalletToCreatedWallet() // logs in user
      // update user vendor profile on marketplace
      const isBusiness = this.state.signupType === "business"
      profileProvider.updateProfile(walletCreated.did.publicDidDocument.id, {
        'type': isBusiness ? 'business' : 'individual'
      });
    }

    toastr.success(
      'Congratulations',
      `You have completed the first airdrop task and earned 1 Chlu bonus token.
       You will be awarded the Chlu token post our public sale`
    )
    // TODO: redirect user depending on their type: business goes to reviews about me, individual goes to search
  }

  render() {
    const { wallet, crawlerRunning } = this.props
    const initialStep = wallet.did ? 1 : 0

    return (
      <Wizard
        validate={this.validate.bind(this)}
        currentStep={initialStep}
        onChangeStep={this.onChangeStep.bind(this)}
        finishButtonClick={this.finishClicked.bind(this)}
        nextButtonDisabled={crawlerRunning}
        previousButtonDisabled={crawlerRunning}
        steps={[
          {
            stepName: 'Step 1: Create Your Account',
            stepComponent: Step1,
            stepId: 'get started',
            stepProps: {
              ...this.props,
              onSignupTypeChange: this.onSignupTypeChange,
              onProfileFieldChange: this.onProfileFieldChange
            }
          },
          {
            stepName: this.state.signupType === "business" ? 'Step 2: Import Existing Reviews' : 'Step 2: Become A Trusted Reviewer',
            stepComponent: this.state.signupType === "business" ? Step3 : Step2,
            stepId: 'about',
            stepProps: {
              ...this.props,
              onProfileFieldChange: this.onProfileFieldChange,
              downloadWallet: this.downloadWallet.bind(this)
            }
          }
        ]}
        title="Let's Get Started"
        subtitle='Follow The Three Easy Steps Below To Begin'
      />
    )
  }
}

const mapStateToProps = store => ({
  loading: store.components.createWallet.loading,
  walletSaved: store.components.createWallet.walletSaved,
  walletCreated: store.components.createWallet.walletCreated,
  wallet: store.data.wallet,
  reviews: store.data.reputation.reviews,
  reputationLoading: store.data.reputation.loading,
  crawlerRunning: store.data.crawler.running,
  acceptedTerms: store.components.signupWizard.acceptedTerms
})

const mapDispatchToProps = {
  createWallet,
  setWallet,
  setWalletSaved,
  setWalletToCreatedWallet,
  readMyReputation,
  setAcceptTermsAndConditions,
  push,
  submit
}

export default connect(mapStateToProps, mapDispatchToProps)(SignupWizard)
<|endoftext|>


<commit_before>/* jQuery UI dialog clickoutside */

/*
The MIT License (MIT)

Copyright (c) 2013 - AGENCE WEB COHERACTIO

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

$.widget( "ui.dialog", $.ui.dialog, {
  options: {
    clickOutside: false, // Determine if clicking outside the dialog shall close it
    clickOutsideTrigger: "" // Element (id or class) that triggers the dialog opening
  },

  open: function() {
    var clickOutsideTriggerEl = $( this.options.clickOutsideTrigger );
    var that = this;

    if (this.options.clickOutside){
      // Add document wide click handler for the current dialog namespace
      $(document).on( "click.ui.dialogClickOutside" + that.eventNamespace, function(event){
        if ( $(event.target).closest($(clickOutsideTriggerEl)).length == 0 && $(event.target).closest($(that.uiDialog)).length == 0){
          that.close();
        }
      });
    }

    this._super(); // Invoke parent open method
  },

  close: function() {
    var that = this;

    // Remove document wide click handler for the current dialog
    $(document).off( "click.ui.dialogClickOutside" + that.eventNamespace );

    this._super(); // Invoke parent close method
  },

});
<commit_msg>SONAR ISSUES<commit_after>/* jQuery UI dialog clickoutside */

/*
The MIT License (MIT)

Copyright (c) 2013 - AGENCE WEB COHERACTIO

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

$.widget( 'ui.dialog', $.ui.dialog, {
    options: {
        // Determine if clicking outside the dialog shall close it
        clickOutside: false,
        // Element (id or class) that triggers the dialog opening
        clickOutsideTrigger: ''
    },
      open: function() {
          var clickOutsideTriggerEl = $( this.options.clickOutsideTrigger ),
              that = this;
            if (this.options.clickOutside){
                  // Add document wide click handler for the current dialog namespace
                  $(document).on( 'click.ui.dialogClickOutside' + that.eventNamespace, function(event){
                      var $target = $(event.target);
                      if ( $target.closest($(clickOutsideTriggerEl)).length === 0 &&
                           $target.closest($(that.uiDialog)).length === 0){
                        that.close();
                      }
                  });
            }
            // Invoke parent open method
            this._super();
      },
      close: function() {
        // Remove document wide click handler for the current dialog
        $(document).off( 'click.ui.dialogClickOutside' + this.eventNamespace );
        // Invoke parent close method
        this._super();
      },
});<|endoftext|>