<commit_before>import React from "react";
import styled, { keyframes } from "styled-components";
import { Col } from "../Section";
import Link from "gatsby-link";
import Image from "gatsby-image";
import VideoBackground from "./VideoBackground";
import icon_outer from "./icon_outer.svg";
import icon_inner from "./icon_inner.svg";
import VisibilitySensor from "react-visibility-sensor";
const Description = styled.div`
    max-width: 250px;
    margin-top: 56px;
    box-sizing: border-box;
    h2 {
        font-weight: 300;
        line-height: 1.4;
        letter-spacing: -0.4px;
    }
    p:last-child {
        margin-bottom: 0;
    }
`;
const Tag = styled.div`
    padding: 3px 9px;
    line-height: 1.3em;
    border-bottom-right-radius: 4px;
    border-top-right-radius: 4px;
    height: 28px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    font-size: 12px;
    font-weight: 500;
    text-align: left;
    background-color: ${props =>
        props.theme == "dark"
            ? `rgba(255, 255, 255, 0.2)`
            : `rgba(0, 29, 96, 0.1)`};
`;

const InnerItem = styled.div`
    padding: 26px 26px 56px;
    position: relative;
    z-index: 1;
    min-height: 512px;
    display: flex;
    justify-content: space-between;
    flex-direction: column;
`;

const lightGradient = `linear-gradient(
    to right,
    rgba(255, 255, 255, 0.5),
    rgba(255, 255, 255, 0.4) 180px,
    rgba(255, 255, 255, 0) 290px
)`;

const darkGradient = `linear-gradient(
    to right,
    rgba(0, 0, 0, 0.5),
    rgba(0, 0, 0, 0.4) 180px,
    rgba(0, 0, 0, 0) 290px
)`;

const Overlay = styled.div`
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-image: ${props =>
        props.theme == "dark" ? darkGradient : lightGradient};
`;
const TagContainer = styled.div`
    display: flex;
    justify-content: space-between;
    @media (min-width: 590px) {
        max-width: 230px;
    }
`;

const WrapWithLink = ({ children, link }) =>
    link && link.indexOf("http") !== 0 ? (
        <Link
            to={link}
            style={{ display: "block", height: "100%", textDecoration: "none" }}
        >
            {children}
        </Link>
    ) : link ? (

            {children}

    ) : (

{children}

    );

const getDevicePixelRatio = function() {
    var ratio = 1;
    if (typeof window === "undefined") return ratio;
    // To account for zoom, change to use deviceXDPI instead of systemXDPI
    if (
        window.screen.systemXDPI !== undefined &&
        window.screen.logicalXDPI !== undefined &&
        window.screen.systemXDPI > window.screen.logicalXDPI
    ) {
        // Only allow for values > 1
        ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
    } else if (window.devicePixelRatio !== undefined) {
        ratio = window.devicePixelRatio;
    }
    if (ratio < 1) ratio = 1;
    return ratio;
};

const linkType = link =>
    link ? (link.indexOf("http") === 0 ? "external" : "internal") : false;

const getBackgroundImage = image => {
    return image
        ? `url("${image.file.url}?h=${512 * getDevicePixelRatio() || 1}&q=50")`
        : false;
};

const HoverOverlay = styled.div`
    position: absolute;
    z-index: 2;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    opacity: 0;
    transition: opacity 0.4s;
    &:before {
        position: absolute;
        opacity: 1;
        content: "";
        width: 90px;
        height: 90px;
        background-color: rgba(0, 0, 0, 0.2);
        border-radius: 90px;
        left: 50%;
        top: 50%;
        background-image: url(${props =>
            props.type === "external" ? icon_outer : icon_inner});
        background-repeat: no-repeat;
        background-position: center center;
        margin-left: -45px;
        margin-top: -45px;
        transform: translate(0, 10px);
        transition: transform 0.4s;
    }
    @media (min-width: 590px) {
        &:hover {
            background-color: rgba(0, 0, 0, 0.1);
            opacity: 1;
        }
        &:hover:before {
            transform: translate(0, 0);
        }
    }
`;
const HoverOverlayLink = styled.div`
    position: relative;
    top: 80%;
    display: inline-block;
    margin: 0 auto;
    padding: 10px 20px;
    font-size: 14px;
    border-radius: 27px;
    color: #fff;
    background-color: rgba(0, 0, 0, 0.2);
`;

const fadeIn = keyframes`
    from {
        transform: scale(0.95);
        opacity: 0;
    }

    to {
        transform: scale(1);
        opacity: 1;
    }
`;

const fadeOut = keyframes`
    from {
        transform: scale(1);
        opacity: 1;
    }

    to {
        transform: scale(0.95);
        opacity: 0;
    }
`;

const Fade = styled.div`
    visibility: ${props => (props.out ? "hidden" : "visible")};
    animation: ${props => (props.out ? fadeOut : fadeIn)} 0.3s linear;
    transition: visibility 0.3s linear;
`;

class ItemBase extends React.Component {
    constructor(props) {
        super(props);
        this.state =
            isVisible: true,
            isMounted: false
        };
        this.onVisibilityChange = this.onVisibilityChange.bind(this);
    }
    onVisibilityChange(isVisible) {
        // this.setState({ isVisible: true });
    }
    render() {
        const {
            link,
            cols,
            children,
            tag,
            secondary,
            className,
            theme,
            images,
            videoBackground,
            disableOverlay
        } = this.props;
        return (
            <VisibilitySensor
                partialVisibility={true}
                onChange={this.onVisibilityChange}
            >
                <Col cols={cols} style={{ padding: "4px" }}>
                    <Fade out={false}>
                        <WrapWithLink link={link}>

                                {videoBackground && (
                                    <VideoBackground
                                        videoUrl={videoBackground.file.url}
                                    />
                                )}
                                {!disableOverlay && <Overlay theme={theme} />}
                                {link && (
                                    <HoverOverlay type={linkType(link)}>
                                        {linkType(link) === "external" && (
                                            <HoverOverlayLink>
                                                go to

                                                {
                                                    link
                                                        .split("//")[1]
                                                        .split("/")[0]
                                                }
                                            </HoverOverlayLink>
                                        )}
                                    </HoverOverlay>
                                )}
                                <InnerItem>

                                        <TagContainer>
                                            {tag ? (
                                                <Tag theme={theme}>{tag}</Tag>
                                            ) : null}
                                            {secondary ? (

                                                    {secondary}

                                            ) : null}
                                        </TagContainer>
                                        <Description>{children}</Description>

                                        {images.image && images.image.sizes ? (
                                            <Image
                                                sizes={images.image.sizes}
                                                style={{
                                                    margin: "0 auto",
                                                    maxWidth: "200px",
                                                    width: "100%"
                                                }}
                                                // resolutions={images.image.resolutions}
                                            />
                                        ) : null}

                                </InnerItem>

                        </WrapWithLink>
                    </Fade>
                </Col>
            </VisibilitySensor>
        );
    }
}

export const Item = styled(ItemBase)`
    background-position: center center;
    background-size: cover;
    height: 100%;
    min-height: 512px;
    text-decoration: none;
    color: ${props => (props.theme == "dark" ? "#FFF" : "#001d60")};
    box-sizing: border-box;
    background-color: ${props =>
        props.theme == "dark" ? "#030303" : "#EBEBEB"};
    position: relative;
    transition: box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s;
    .hidden {
        display: none;
    }
    a {
        color: inherit;
    }
    &:hover {
        ${props =>
            props.link
                ? `
        z-index: 1;
    `
                : null};
    }
    @media (max-width: 580px) {
        min-height: 0;
        filter: saturate(1);
    }
`;
<commit_msg>revert<commit_after>import React from "react";
import styled, { keyframes } from "styled-components";
import { Col } from "../Section";
import Link from "gatsby-link";
import Image from "gatsby-image";
import VideoBackground from "./VideoBackground";
import icon_outer from "./icon_outer.svg";
import icon_inner from "./icon_inner.svg";
import VisibilitySensor from "react-visibility-sensor";
const Description = styled.div`
    max-width: 250px;
    margin-top: 56px;
    box-sizing: border-box;
    h2 {
        font-weight: 300;
        line-height: 1.4;
        letter-spacing: -0.4px;
    }
    p:last-child {
        margin-bottom: 0;
    }
`;
const Tag = styled.div`
    padding: 3px 9px;
    line-height: 1.3em;
    border-bottom-right-radius: 4px;
    border-top-right-radius: 4px;
    height: 28px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    font-size: 12px;
    font-weight: 500;
    text-align: left;
    background-color: ${props =>
        props.theme == "dark"
            ? `rgba(255, 255, 255, 0.2)`
            : `rgba(0, 29, 96, 0.1)`};
`;

const InnerItem = styled.div`
    padding: 26px 26px 56px;
    position: relative;
    z-index: 1;
    min-height: 512px;
    display: flex;
    justify-content: space-between;
    flex-direction: column;
`;

const lightGradient = `linear-gradient(
    to right,
    rgba(255, 255, 255, 0.5),
    rgba(255, 255, 255, 0.4) 180px,
    rgba(255, 255, 255, 0) 290px
)`;

const darkGradient = `linear-gradient(
    to right,
    rgba(0, 0, 0, 0.5),
    rgba(0, 0, 0, 0.4) 180px,
    rgba(0, 0, 0, 0) 290px
)`;

const Overlay = styled.div`
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-image: ${props =>
        props.theme == "dark" ? darkGradient : lightGradient};
`;
const TagContainer = styled.div`
    display: flex;
    justify-content: space-between;
    @media (min-width: 590px) {
        max-width: 230px;
    }
`;

const WrapWithLink = ({ children, link }) =>
    link && link.indexOf("http") !== 0 ? (
        <Link
            to={link}
            style={{ display: "block", height: "100%", textDecoration: "none" }}
        >
            {children}
        </Link>
    ) : link ? (

            {children}

    ) : (

{children}

    );

const getDevicePixelRatio = function() {
    var ratio = 1;
    if (typeof window === "undefined") return ratio;
    // To account for zoom, change to use deviceXDPI instead of systemXDPI
    if (
        window.screen.systemXDPI !== undefined &&
        window.screen.logicalXDPI !== undefined &&
        window.screen.systemXDPI > window.screen.logicalXDPI
    ) {
        // Only allow for values > 1
        ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
    } else if (window.devicePixelRatio !== undefined) {
        ratio = window.devicePixelRatio;
    }
    if (ratio < 1) ratio = 1;
    return ratio;
};

const linkType = link =>
    link ? (link.indexOf("http") === 0 ? "external" : "internal") : false;

const getBackgroundImage = image => {
    return image
        ? `url("${image.file.url}?h=${512 * getDevicePixelRatio() || 1}&q=50")`
        : false;
};

const HoverOverlay = styled.div`
    position: absolute;
    z-index: 2;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    opacity: 0;
    transition: opacity 0.4s;
    &:before {
        position: absolute;
        opacity: 1;
        content: "";
        width: 90px;
        height: 90px;
        background-color: rgba(0, 0, 0, 0.2);
        border-radius: 90px;
        left: 50%;
        top: 50%;
        background-image: url(${props =>
            props.type === "external" ? icon_outer : icon_inner});
        background-repeat: no-repeat;
        background-position: center center;
        margin-left: -45px;
        margin-top: -45px;
        transform: translate(0, 10px);
        transition: transform 0.4s;
    }
    @media (min-width: 590px) {
        &:hover {
            background-color: rgba(0, 0, 0, 0.1);
            opacity: 1;
        }
        &:hover:before {
            transform: translate(0, 0);
        }
    }
`;
const HoverOverlayLink = styled.div`
    position: relative;
    top: 80%;
    display: inline-block;
    margin: 0 auto;
    padding: 10px 20px;
    font-size: 14px;
    border-radius: 27px;
    color: #fff;
    background-color: rgba(0, 0, 0, 0.2);
`;

const fadeIn = keyframes`
    from {
        transform: scale(0.95);
        opacity: 0;
    }

    to {
        transform: scale(1);
        opacity: 1;
    }
`;

const fadeOut = keyframes`
    from {
        transform: scale(1);
        opacity: 1;
    }

    to {
        transform: scale(0.95);
        opacity: 0;
    }
`;

const Fade = styled.div`
    visibility: ${props => (props.out ? "hidden" : "visible")};
    animation: ${props => (props.out ? fadeOut : fadeIn)} 0.3s linear;
    transition: visibility 0.3s linear;
`;

class ItemBase extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isVisible: true,
            isMounted: false
        };
        this.onVisibilityChange = this.onVisibilityChange.bind(this);
    }
    onVisibilityChange(isVisible) {
        // this.setState({ isVisible: true });
    }
    render() {
        const {
            link,
            cols,
            children,
            tag,
            secondary,
            className,
            theme,
            images,
            videoBackground,
            disableOverlay
        } = this.props;
        return (
            <VisibilitySensor
                partialVisibility={true}
                onChange={this.onVisibilityChange}
            >
                <Col cols={cols} style={{ padding: "4px" }}>
                    <WrapWithLink link={link}>

                            {videoBackground && (
                                <VideoBackground
                                    videoUrl={videoBackground.file.url}
                                />
                            )}
                            {!disableOverlay && <Overlay theme={theme} />}
                            {link && (
                                <HoverOverlay type={linkType(link)}>
                                    {linkType(link) === "external" && (
                                        <HoverOverlayLink>
                                            go to

                                            {link.split("//")[1].split("/")[0]}
                                        </HoverOverlayLink>
                                    )}
                                </HoverOverlay>
                            )}
                            <InnerItem>

                                    <TagContainer>
                                        {tag ? (
                                            <Tag theme={theme}>{tag}</Tag>
                                        ) : null}
                                        {secondary ? (

                                                {secondary}

                                        ) : null}
                                    </TagContainer>
                                    <Description>{children}</Description>

                                    {images.image && images.image.sizes ? (
                                        <Image
                                            sizes={images.image.sizes}
                                            style={{
                                                margin: "0 auto",
                                                maxWidth: "200px",
                                                width: "100%"
                                            }}
                                            // resolutions={images.image.resolutions}
                                        />
                                    ) : null}

                            </InnerItem>

                    </WrapWithLink>
                </Col>
            </VisibilitySensor>
        );
    }
}

export const Item = styled(ItemBase)`
    background-position: center center;
    background-size: cover;
    height: 100%;
    min-height: 512px;
    text-decoration: none;
    color: ${props => (props.theme == "dark" ? "#FFF" : "#001d60")};
    box-sizing: border-box;
    background-color: ${props =>
        props.theme == "dark" ? "#030303" : "#EBEBEB"};
    position: relative;
    transition: box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.5s;
    .hidden {
        display: none;
    }
    a {
        color: inherit;
    }
    &:hover {
        ${props =>
            props.link
                ? `
        z-index: 1;
    `
                : null};
    }
    @media (max-width: 580px) {
        min-height: 0;
        filter: saturate(1);
    }
`;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
    StyleSheet,
    Text,
    View,
    TouchableHighlight,
    ListView
} from 'react-native';
// import styles from './styles';

export default class List extends Component {
    constructor(props) {
        super(props);
        const ds = new ListView.DataSource({
            rowHasChanged: (r1, r2) => r1 !== r2,
        })

        console.log('setting state in List constructor', props.data)
        this.state = {
            data: props.data,
            dataSource: ds.cloneWithRows(props.data)
        }
    }

    // componentWillUpdate(nextProps) {
    //     console.log("this.state.data", this.state.data);
    //     console.log("nextProps", nextProps);
    //     if (this.state.data.length !== nextProps.data.length) {
    //     //     console.log('setting new state in list...')
    //         this.setState({
    //             data: nextProps.data,
    //             dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
    //         })
    //     }
    // }

    shouldComponentUpdate(nextProps, nextState) {
        console.log("this.state.data", this.state.data);
        console.log("nextProps", nextProps);
        console.log("nextState", nextState);

        if (nextProps.data.length === 0) {
            console.log('set state to 0')
            this.setState({
                data: [],
                dataSource: this.state.dataSource.cloneWithRows([])
            })

            return true;
        }

        if (this.state.data.length !== nextProps.data.length) {
        //     console.log('setting new state in list...')
            this.setState({
                data: nextProps.data,
                dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
            })

            return true;
        }

        return false;
    }

    renderRow = (item) => {
        console.log('this.props', this.props)
        const Component = this.props.listItemToRender;

        // console.log("item", item);
        // console.log("this.props.parentData", this.props.parentData);
        const { givenName, familyName, recordID } = item;
        const fullName = `${givenName} ${familyName || ''}`;

        return (
            <View style={styles.contact}>
                <Text style={styles.name}>{fullName}</Text>
                <TouchableHighlight
                    style={styles.cancel}
                    onPress={() => {
                        const newArray = this.state.data.slice();

                        this.setState({
                            data: newArray,
                            dataSource: this.state.dataSource.cloneWithRows(newArray),
                        });

                        this.props.removeContactToBeDelete(this.props.data, item.recordID)
                    }}
                >
                    <Text style={styles.icon}>X</Text>
                </TouchableHighlight>
            </View>

        )
    }

    render() {
        return (
            <View style={styles.container}>
                <ListView
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow}
                    enableEmptySections={true}
                />
            </View>
        )
    }
}

function Contact(props) {
    console.log("contact props", props);
    const { givenName, familyName, recordID } = props.item;
    const fullName = `${givenName} ${familyName || ''}`;

    return (
        <View style={styles.contact} key={recordID}>
            <Text style={styles.name}>{fullName}</Text>
            <TouchableHighlight
                style={styles.cancel}
                onPress={() => props.removeContactToBeDelete(props.contactsToDelete, props.item.recordID)}
            >
                <Text style={styles.icon}>X</Text>
            </TouchableHighlight>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    contact: {
        padding: 20,
        borderTopWidth: 1,
        borderTopColor: '#ddd',
        position: 'relative',
        flexDirection: 'row',
        justifyContent: 'space-between'
    },
    name: {
        fontSize: 16,
    },
    icon: {
        width: 32,
        height: 32,
        fontWeight: 'bold',
    }
})

// import React, { Component } from 'react';
// import { View, ListView } from 'react-native';
// import styles from './styles';

// export default class List extends Component {
//     constructor(props) {
//         super(props);
//         const ds = new ListView.DataSource({
//             rowHasChanged: (r1, r2) => r1 !== r2,
//         })

//         console.log('setting state in List constructor', props.data)
//         this.state = {
//             data: props.data,
//             dataSource: ds.cloneWithRows(props.data)
//         }
//     }

//     // componentWillUpdate(nextProps) {
//     //     console.log("this.state.data", this.state.data);
//     //     console.log("nextProps", nextProps);
//     //     if (this.state.data.length !== nextProps.data.length) {
//     //     //     console.log('setting new state in list...')
//     //         this.setState({
//     //             data: nextProps.data,
//     //             dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
//     //         })
//     //     }
//     // }

//     shouldComponentUpdate(nextProps, nextState) {
//         console.log("this.state.data", this.state.data);
//         console.log("nextProps", nextProps);
//         console.log("nextState", nextState);

//         if (nextProps.data.length === 0) {
//             console.log('set state to 0')
//             this.setState({
//                 data: [],
//                 dataSource: this.state.dataSource.cloneWithRows([])
//             })

//             return true;
//         }

//         if (this.state.data.length !== nextProps.data.length) {
//         //     console.log('setting new state in list...')
//             this.setState({
//                 data: nextProps.data,
//                 dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
//             })

//             return true;
//         }

//         return false;
//     }

//     renderRow = (item) => {
//         const Component = this.props.listItemToRender;

//         console.log("item", item);
//         console.log("this.props.parentData", this.props.parentData);
//         return (
//             <Component
//                 {...this.props.parentData}
//                 item={item}
//                 navigator={this.props.navigator}
//                 route={this.props.route}
//             />
//         )
//     }

//     render() {
//         return (
//             <View style={styles.container}>
//                 <ListView
//                     dataSource={this.state.dataSource}
//                     renderRow={this.renderRow}
//                     enableEmptySections={true}
//                 />
//             </View>
//         )
//     }
// }
<commit_msg>on removeContact press set state of the listView to be an array filtered by the item clicked<commit_after>import React, { Component } from 'react';
import {
    StyleSheet,
    Text,
    View,
    TouchableHighlight,
    ListView
} from 'react-native';
// import styles from './styles';

export default class List extends Component {
    constructor(props) {
        super(props);
        const ds = new ListView.DataSource({
            rowHasChanged: (r1, r2) => r1 !== r2,
        })

        console.log('setting state in List constructor', props.data)
        this.state = {
            data: props.data,
            dataSource: ds.cloneWithRows(props.data)
        }
    }

    // componentWillUpdate(nextProps) {
    //     console.log("this.state.data", this.state.data);
    //     console.log("nextProps", nextProps);
    //     if (this.state.data.length !== nextProps.data.length) {
    //     //     console.log('setting new state in list...')
    //         this.setState({
    //             data: nextProps.data,
    //             dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
    //         })
    //     }
    // }

    // shouldComponentUpdate(nextProps, nextState) {
    //     console.log("this.state.data", this.state.data);
    //     console.log("nextProps", nextProps);
    //     console.log("nextState", nextState);

    //     if (nextProps.data.length === 0) {
    //         console.log('set state to 0')
    //         this.setState({
    //             data: [],
    //             dataSource: this.state.dataSource.cloneWithRows([])
    //         })

    //         return true;
    //     }

    //     if (this.state.data.length !== nextProps.data.length) {
    //     //     console.log('setting new state in list...')
    //         this.setState({
    //             data: nextProps.data,
    //             dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
    //         })

    //         return true;
    //     }

    //     return false;
    // }

    renderRow = (item) => {
        console.log('this.props', this.props)
        console.log('this.state', this.state)
        const Component = this.props.listItemToRender;

        // console.log("item", item);
        // console.log("this.props.parentData", this.props.parentData);
        const { givenName, familyName, recordID } = item;
        const fullName = `${givenName} ${familyName || ''}`;

        return (
            <View style={styles.contact}>
                <Text style={styles.name}>{fullName}</Text>
                <TouchableHighlight
                    style={styles.cancel}
                    onPress={() => {
                        const newArray = this.state.data.filter(contact => contact.recordID !== item.recordID);

                        this.setState({
                            data: newArray,
                            dataSource: this.state.dataSource.cloneWithRows(newArray),
                        });

                        this.props.removeContactToBeDelete(this.props.data, item.recordID)
                    }}
                >
                    <Text style={styles.icon}>X</Text>
                </TouchableHighlight>
            </View>

        )
    }

    render() {
        return (
            <View style={styles.container}>
                <ListView
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow}
                    enableEmptySections={true}
                />
            </View>
        )
    }
}

function Contact(props) {
    console.log("contact props", props);
    const { givenName, familyName, recordID } = props.item;
    const fullName = `${givenName} ${familyName || ''}`;

    return (
        <View style={styles.contact} key={recordID}>
            <Text style={styles.name}>{fullName}</Text>
            <TouchableHighlight
                style={styles.cancel}
                onPress={() => props.removeContactToBeDelete(props.contactsToDelete, props.item.recordID)}
            >
                <Text style={styles.icon}>X</Text>
            </TouchableHighlight>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    contact: {
        padding: 20,
        borderTopWidth: 1,
        borderTopColor: '#ddd',
        position: 'relative',
        flexDirection: 'row',
        justifyContent: 'space-between'
    },
    name: {
        fontSize: 16,
    },
    icon: {
        width: 32,
        height: 32,
        fontWeight: 'bold',
    }
})

// import React, { Component } from 'react';
// import { View, ListView } from 'react-native';
// import styles from './styles';

// export default class List extends Component {
//     constructor(props) {
//         super(props);
//         const ds = new ListView.DataSource({
//             rowHasChanged: (r1, r2) => r1 !== r2,
//         })

//         console.log('setting state in List constructor', props.data)
//         this.state = {
//             data: props.data,
//             dataSource: ds.cloneWithRows(props.data)
//         }
//     }

//     // componentWillUpdate(nextProps) {
//     //     console.log("this.state.data", this.state.data);
//     //     console.log("nextProps", nextProps);
//     //     if (this.state.data.length !== nextProps.data.length) {
//     //     //     console.log('setting new state in list...')
//     //         this.setState({
//     //             data: nextProps.data,
//     //             dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
//     //         })
//     //     }
//     // }

//     shouldComponentUpdate(nextProps, nextState) {
//         console.log("this.state.data", this.state.data);
//         console.log("nextProps", nextProps);
//         console.log("nextState", nextState);

//         if (nextProps.data.length === 0) {
//             console.log('set state to 0')
//             this.setState({
//                 data: [],
//                 dataSource: this.state.dataSource.cloneWithRows([])
//             })

//             return true;
//         }

//         if (this.state.data.length !== nextProps.data.length) {
//         //     console.log('setting new state in list...')
//             this.setState({
//                 data: nextProps.data,
//                 dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
//             })

//             return true;
//         }

//         return false;
//     }

//     renderRow = (item) => {
//         const Component = this.props.listItemToRender;

//         console.log("item", item);
//         console.log("this.props.parentData", this.props.parentData);
//         return (
//             <Component
//                 {...this.props.parentData}
//                 item={item}
//                 navigator={this.props.navigator}
//                 route={this.props.route}
//             />
//         )
//     }

//     render() {
//         return (
//             <View style={styles.container}>
//                 <ListView
//                     dataSource={this.state.dataSource}
//                     renderRow={this.renderRow}
//                     enableEmptySections={true}
//                 />
//             </View>
//         )
//     }
// }
<|endoftext|>


<commit_before>/* global TraceKit, timing */
import Ember from 'ember';
import config from 'ember-cli-erraroo/erraroo/config';

const logger = Ember.Logger;

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  }

  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}

function normalizeFrame(frame) {
  // reject this frame if there is no url
  if (!frame.url) {
    return;
  }

  // reject this frame if there is no column
  if (!frame.column) {
    return;
  }

  // reject this frame if there is no column
  if (!frame.line) {
    return;
  }

  return {
    column: frame.column,
    func: frame.func,
    line: frame.line,
    url: frame.url,
  };
}

function normalizedPlugins() {
  const normal = [];
  const plugins = (window.navigator.plugins || []);
  for(let i = 0; i < plugins.length; i++) {
    normal.push(normalizedPlugin(plugins[i]));
  }

  return normal;
}

function normalizedPlugin(plugin) {
  return {name: plugin.name, description: plugin.description};
}

let logs = [];
const MAX_LOG_SIZE = 100;

const Erraroo = Ember.Object.extend({
  log: function(message, level) {
    if (logs.length > MAX_LOG_SIZE) {
      logs.shift();
    }

    logs.push({
      timestamp: (new Date()).getTime(),
      message: message,
      level: level || 'info',
    });

    if (config.debug) {
      logger.debug(message);
    }
  },

  makeRequest: function(kind, data) {
    return Ember.$.ajax({
      url: config.endpoint,
      data: this.makePayload(kind, data),
      dataType: 'json',
      method: 'POST',
      headers: {
        'X-Token': config.token,
      }
    });
  },

  makePayload: function(kind, data) {
    return JSON.stringify({
      client: {
        name: 'ember-cli-erraroo',
        version: config.version,
      },
      data: data,
      kind: kind,
      session: config.sessionId,
    });
  },

  beforeInitialize: function(env) {
    if (Ember.isNone(env)) {
      config.enabled = false;
      return;
    }

    if (Ember.isNone(env.token)) {
      logger.warn("Please set your project token on ErrarooENV.token = 'xxx' in config/environment.js");
      return;
    }

    Ember.merge(config, env);
    config.enabled = true;
    config.sessionId = guid();

    TraceKit.remoteFetching = false;
    TraceKit.collectWindowErrors = true;
  },

  initialize: function(instance) {
    const { container } = instance;

    if (config.enabled) {
      this.install(instance);
      const router = container.lookup('router:main');
      router.on('willTransition', (t) => this.willTransition(t));

      if (config.collectTimingData) {
        this.collectTimingData();
      }
    }
  },

  install: function(instance) {
    logger.debug('installing');

    const { container } = instance;

    const that = this;
    that.instance = instance;
    that.container = container;
    that.router = container.lookup('router:main');

    TraceKit.report.subscribe(function reportError(errorReport) {
      that.reportError(errorReport);
    });

    var oldEmberOnerror = Ember.onerror || Ember.K;
    Ember.onerror = function(error) {
      try {
        TraceKit.report(error);
      } catch(ex) {
        if (ex !== error) {
          throw ex;
        }
      }

      logger.error('Ember.onerror', error);
      return oldEmberOnerror(error);
    };

    Ember.RSVP.on('error', function(error) {
      try {
        TraceKit.report(error);
      } catch(ex) {
        if (ex !== error) {
          throw ex;
        }
      }

      logger.error('Ember.RSVP.onerror', error);
    });
  },

  reportError: function(error) {
    this.log(error.message, 'error');

    if (error.stack) {
      var frames = [];
      for(var j = 0; j < error.stack.length; j++) {
        var frame = normalizeFrame(error.stack[j]);
        if (frame) {
          frames.push(frame);
        }
      }

      error.stack = frames;
    }

    var request = {
      language: window.navigator.language,
      libaries: this.libaries(),
      plugins: normalizedPlugins(),
      useragent: window.navigator.userAgent,
      userdata: this.get('userdata'),
      url: window.location.href,
      trace: error,
      logs: logs,
    };

    this.makeRequest('js.error', request);
  },

  libaries: function() {
    return Ember.libraries._registry || [];
  },

  collectTimingData: function() {
    const that = this;
    setTimeout(function() {
      that.makeRequest('js.timing', timing.getTimes());
    }, 5000);
  },

  willTransition: function(transition) {
    const target = transition.targetName;
    let current = this.router.get('currentRouteName');
    if (Ember.isNone(current)) {
      current = "root";
    }

    this.log('Transition ' + current + ' => ' + transition.targetName, 'transition');
  },

  reportApplicationRouteError: function(error, transition) {
    const err = {
      name: "Error while processing route: "+ transition.targetName,
    };

    if (error.errors) {
      error = error.errors[0];
      err.message =  `${error.title} ${error.status} ${error.detail}`;
    } else {
      err.message = `Error ${error.status} ${error.responseText}`;
    }

    this.reportError(err);
  }
});

const erraroo = Erraroo.create();
export default erraroo;
<commit_msg>jshint, no need to prefix with transition<commit_after>/* global TraceKit, timing */
import Ember from 'ember';
import config from 'ember-cli-erraroo/erraroo/config';

const logger = Ember.Logger;

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  }

  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}

function normalizeFrame(frame) {
  // reject this frame if there is no url
  if (!frame.url) {
    return;
  }

  // reject this frame if there is no column
  if (!frame.column) {
    return;
  }

  // reject this frame if there is no column
  if (!frame.line) {
    return;
  }

  return {
    column: frame.column,
    func: frame.func,
    line: frame.line,
    url: frame.url,
  };
}

function normalizedPlugins() {
  const normal = [];
  const plugins = (window.navigator.plugins || []);
  for(let i = 0; i < plugins.length; i++) {
    normal.push(normalizedPlugin(plugins[i]));
  }

  return normal;
}

function normalizedPlugin(plugin) {
  return {name: plugin.name, description: plugin.description};
}

let logs = [];
const MAX_LOG_SIZE = 100;

const Erraroo = Ember.Object.extend({
  log: function(message, level) {
    if (logs.length > MAX_LOG_SIZE) {
      logs.shift();
    }

    logs.push({
      timestamp: (new Date()).getTime(),
      message: message,
      level: level || 'info',
    });

    if (config.debug) {
      logger.debug(message);
    }
  },

  makeRequest: function(kind, data) {
    return Ember.$.ajax({
      url: config.endpoint,
      data: this.makePayload(kind, data),
      dataType: 'json',
      method: 'POST',
      headers: {
        'X-Token': config.token,
      }
    });
  },

  makePayload: function(kind, data) {
    return JSON.stringify({
      client: {
        name: 'ember-cli-erraroo',
        version: config.version,
      },
      data: data,
      kind: kind,
      session: config.sessionId,
    });
  },

  beforeInitialize: function(env) {
    if (Ember.isNone(env)) {
      config.enabled = false;
      return;
    }

    if (Ember.isNone(env.token)) {
      logger.warn("Please set your project token on ErrarooENV.token = 'xxx' in config/environment.js");
      return;
    }

    Ember.merge(config, env);
    config.enabled = true;
    config.sessionId = guid();

    TraceKit.remoteFetching = false;
    TraceKit.collectWindowErrors = true;
  },

  initialize: function(instance) {
    const { container } = instance;

    if (config.enabled) {
      this.install(instance);
      const router = container.lookup('router:main');
      router.on('willTransition', (t) => this.willTransition(t));

      if (config.collectTimingData) {
        this.collectTimingData();
      }
    }
  },

  install: function(instance) {
    logger.debug('installing');

    const { container } = instance;

    const that = this;
    that.instance = instance;
    that.container = container;
    that.router = container.lookup('router:main');

    TraceKit.report.subscribe(function reportError(errorReport) {
      that.reportError(errorReport);
    });

    var oldEmberOnerror = Ember.onerror || Ember.K;
    Ember.onerror = function(error) {
      try {
        TraceKit.report(error);
      } catch(ex) {
        if (ex !== error) {
          throw ex;
        }
      }

      logger.error('Ember.onerror', error);
      return oldEmberOnerror(error);
    };

    Ember.RSVP.on('error', function(error) {
      try {
        TraceKit.report(error);
      } catch(ex) {
        if (ex !== error) {
          throw ex;
        }
      }

      logger.error('Ember.RSVP.onerror', error);
    });
  },

  reportError: function(error) {
    this.log(error.message, 'error');

    if (error.stack) {
      var frames = [];
      for(var j = 0; j < error.stack.length; j++) {
        var frame = normalizeFrame(error.stack[j]);
        if (frame) {
          frames.push(frame);
        }
      }

      error.stack = frames;
    }

    var request = {
      language: window.navigator.language,
      libaries: this.libaries(),
      plugins: normalizedPlugins(),
      useragent: window.navigator.userAgent,
      userdata: this.get('userdata'),
      url: window.location.href,
      trace: error,
      logs: logs,
    };

    this.makeRequest('js.error', request);
  },

  libaries: function() {
    return Ember.libraries._registry || [];
  },

  collectTimingData: function() {
    const that = this;
    setTimeout(function() {
      that.makeRequest('js.timing', timing.getTimes());
    }, 5000);
  },

  willTransition: function(transition) {
    let current = this.router.get('currentRouteName');
    if (Ember.isNone(current)) {
      current = "root";
    }

    this.log(current + ' => ' + transition.targetName, 'transition');
  },

  reportApplicationRouteError: function(error, transition) {
    const err = {
      name: "Error while processing route: "+ transition.targetName,
    };

    if (error.errors) {
      error = error.errors[0];
      err.message =  `${error.title} ${error.status} ${error.detail}`;
    } else {
      err.message = `Error ${error.status} ${error.responseText}`;
    }

    this.reportError(err);
  }
});

const erraroo = Erraroo.create();
export default erraroo;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ObjectToJSON = {
  __proto__: Visitor.create(),

  visitFunction: function(o) {
    return o.toString();
  },

  visitObject: function(o) {
    this.push({
      model_: (o.model_.package ? o.model_.package + '.' : '') + o.model_.name
    });
    this.__proto__.visitObject.call(this, o);
    return this.pop();
  },
  visitProperty: function(o, prop) {
    prop.propertyToJSON(this, this.top(), o);
  },

  visitMap: function(o) {
    this.push({});
    Visitor.visitMap.call(this, o);
    return this.pop();
  },
  visitMapElement: function(key, value) { this.top()[key] = this.visit(value); },

  visitArray: function(o) {
    this.push([]);
    this.__proto__.visitArray.call(this, o);
    return this.pop();
  },
  visitArrayElement: function (arr, i) { this.top().push(this.visit(arr[i])); }
};

var JSONToObject = {
  __proto__: ObjectToJSON.create(),

  visitString: function(o) {
    try {
      return o.substr(0, 9) === 'function(' ?
        eval('(' + o + ')') :
        o ;
    } catch (x) {
      console.log(x, o);
      return o;
    }
  },

  visitObject: function(o) {
    var model   = X.lookup(o.model_);
    if ( ! model ) throw new Error('Unknown Model: ' + o.model_);
    var obj     = model.create();

    //    o.forEach((function(value, key) {
    // Workaround for crbug.com/258522
    Object_forEach(o, (function(value, key) {
      if ( key !== 'model_' ) obj[key] = this.visit(value);
    }).bind(this));

    return obj;
  },

  // Substitute in-place
  visitArray: Visitor.visitArray,
  visitArrayElement: function (arr, i) { arr[i] = this.visit(arr[i]); }
};

CLASS({
  name: 'FilteredDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: '
Internal use only.
',

  properties: [
    {
      name: 'query',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      return this.delegate.select(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    removeAll: function(sink, options) {
      return this.delegate.removeAll(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    listen: function(sink, options) {
      return this.SUPER(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    toString: function() {
      return this.delegate + '.where(' + this.query + ')';
    }
  }
});

CLASS({
  name: 'OrderedDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'comparator',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      if ( options ) {
        if ( ! options.order )
          options = { __proto__: options, order: this.comparator };
      } else {
        options = {order: this.comparator};
      }

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.orderBy(' + this.comparator + ')';
    }
  }

});

CLASS({
  name: 'LimitedDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'count',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      if ( options ) {
        if ( 'limit' in options ) {
          options = {
            __proto__: options,
            limit: Math.min(this.count, options.limit)
          };
        } else {
          options = { __proto__: options, limit: this.count };
        }
      }
      else {
        options = { limit: this.count };
      }

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.limit(' + this.count + ')';
    }
  }
});

CLASS({
  name: 'SkipDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'skip',
      required: true,
      postSet: function() {
        if ( this.skip !== Math.floor(this.skip) )
          console.warn('skip() called with non-integer value: ' + this.skip);
      }
    }
  ],
  methods: {
    select: function(sink, options) {
      options = options ? { __proto__: options, skip: this.skip } : { skip: this.skip };

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.skip(' + this.skip + ')';
    }
  }
});

CLASS({
  name: 'RelationshipDAO',
  extendsModel: 'FilteredDAO_',
  documentation: 'Adapts a DAO based on a Relationship.',

  properties: [
    {
      name: 'relatedProperty',
      required: true
    },
    {
      name: 'relativeID',
      required: true
    },
    {
      name: 'query',
      lazyFactory: function() {
        return AND(NEQ(this.relatedProperty, ''),
            EQ(this.relatedProperty, this.relativeID));
      }
    },
  ],

  methods: [
    function put(obj, sink) {
      obj[this.relatedProperty.name] = this.relativeID;
      this.SUPER(obj, sink);
    }
  ]
});

function atxn(afunc) {
  return function(ret) {
    if ( GLOBAL.__TXN__ ) {
      afunc.apply(this, arguments);
    } else {
      GLOBAL.__TXN__ = {};
      var a = argsToArray(arguments);
      a[0] = function() {
        GLOBAL.__TXN__ = undefined;
        ret();
      };
      afunc.apply(this, a);
    }
  };
}

CLASS({
  name: 'AbstractDAO',

  documentation: function() {/*
    The base for most DAO implementations, $$DOC{ref:'.'} provides basic facilities for
    $$DOC{ref:'.where'}, $$DOC{ref:'.limit'}, $$DOC{ref:'.skip'}, and $$DOC{ref:'.orderBy'}
    operations, and provides for notifications of updates through $$DOC{ref:'.listen'}.
  */},

  properties: [
    {
      name: 'daoListeners_',
      transient: true,
      hidden: true,
      factory: function() { return []; },
      compareProperty: function() { return 0; },
    }
  ],

  methods: {
    update: function(expr) { /* Applies a change to the DAO contents. */
      return this.select(UPDATE(expr, this));
    },

    select: function(sink, options) {
      /* Template method. Override to copy the contents of this DAO (filtered or ordered as
      necessary) to sink. */
    },
    remove: function(query, sink) {
      /* Template method. Override to remove matching items and put them into sink if supplied. */
    },

    pipe: function(sink, options) { /* A $$DOC{ref:'.select'} followed by $$DOC{ref:'.listen'}.
           Dump our contents to sink, then send future changes there as well. */
      sink = this.decorateSink_(sink, options, true);

      var fc   = this.createFlowControl_();
      var self = this;

      this.select({
        put: function() {
          sink.put && sink.put.apply(sink, arguments);
        },
        remove: function() {
          sink.remove && sink.remove.apply(sink, arguments);
        },
        error: function() {
          sink.error && sink.error.apply(sink, arguments);
        },
        eof: function() {
          if ( fc.stopped ) {
            sink.eof && sink.eof();
          } else {
            self.listen(sink, options);
          }
        }
      }, options, fc);
    },

    decorateSink_: function(sink, options, isListener, disableLimit) {
      if ( options ) {
        if ( ! disableLimit ) {
          if ( options.limit ) sink = limitedSink(options.limit, sink);
          if ( options.skip )  sink = skipSink(options.skip, sink);
        }

        if ( options.order && ! isListener ) {
          sink = orderedSink(options.order, sink);
        }

        if ( options.query ) {
          sink = predicatedSink(
            options.query.partialEval ?
              options.query.partialEval() :
              options.query,
            sink) ;
        }
      }

      return sink;
    },

    createFlowControl_: function() {
      return {
        stop: function() { this.stopped = true; },
        error: function(e) { this.errorEvt = e; }
      };
    },

    where: function(query) { /* Return a DAO that contains a filtered subset of this one. */
      // only use X if we are an invalid instance without a this.Y
      return (this.Y || X).lookup('FilteredDAO_').create({query: query, delegate: this});
    },

    limit: function(count) { /* Return a DAO that contains a count limited subset of this one. */
      return (this.Y || X).lookup('LimitedDAO_').create({count:count, delegate:this});
    },

    skip: function(skip) { /* Return a DAO that contains a subset of this one, skipping initial items. */
      return (this.Y || X).lookup('SkipDAO_').create({skip:skip, delegate:this});
    },

    orderBy: function() { /* Return a DAO that contains a subset of this one, ordered as specified. */
      return (this.Y || X).lookup('OrderedDAO_').create({ comparator: arguments.length == 1 ? arguments[0] : argsToArray(arguments), delegate: this });
    },

    listen: function(sink, options) { /* Send future changes to sink. */
      this.daoListeners_.push(this.decorateSink_(sink, options, true));
    },

    unlisten: function(sink) { /* Stop sending updates to the given sink. */
      var ls = this.daoListeners_;
//      if ( ! ls.length ) console.warn('Phantom DAO unlisten: ', this, sink);
      for ( var i = 0; i < ls.length ; i++ ) {
        if ( ls[i].$UID === sink.$UID ) {
          ls.splice(i, 1);
          return true;
        }
      }
      console.assert(! DEBUG, 'Phantom DAO unlisten: ', this, sink);
    },

    // Default removeAll: calls select() with the same options and
    // calls remove() for all returned values.
    removeAll: function(sink, options) { /* Default $$DOC{ref:'.removeAll'}: calls
            $$DOC{ref:'.select'} with the same options and calls $$DOC{ref:'.remove'}
             for all returned values. */
      var self = this;
      var future = afuture();
      this.select({
        put: function(obj) {
          self.remove(obj, { remove: sink && sink.remove });
        }
      })(function() {
        sink && sink.eof();
        future.set();
      });
      return future.get;
    },

    /**
     * Notify all listeners of update to DAO.
     * @param fName the name of the method in the listeners to call.
     *        possible values: 'put', 'remove'
     **/
    notify_: function(fName, args) {
      // console.log(this.name_, ' ***** notify ', fName, ' args: ', args, ' listeners: ', this.daoListeners_);
      for( var i = 0 ; i < this.daoListeners_.length ; i++ ) {
        var l = this.daoListeners_[i];
        var fn = l[fName];
        if ( fn ) {
          // Create flow-control object
          args[2] = {
            stop: (function(fn, l) {
              return function() { fn(l); };
            })(this.unlisten.bind(this), l),
            error: function(e) { /* Don't care. */ }
          };
          try {
            fn.apply(l, args);
          } catch(err) {
            if ( err !== this.UNSUBSCRIBE_EXCEPTION ) {
              console.error('Error delivering event (removing listener): ', fName, err);
              if ( DEBUG ) console.error(err.stack); // TODO: make a NO_DEBUGGER flag for mobile debugger mode?
            }
            this.unlisten(l);
          }
        }
      }
    },

  }
});

// Experimental, convert all functions into sinks
Function.prototype.put    = function() { this.apply(this, arguments); };
Function.prototype.remove = function() { this.apply(this, arguments); };
Function.prototype.reset = function() { this.call(this); };
//Function.prototype.error  = function() { this.apply(this, arguments); };
//Function.prototype.eof    = function() { this.apply(this, arguments); };
<commit_msg>Closed #428: Not fixing FutureDAO for now, changing the phantom unsub assert to a warn.<commit_after>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ObjectToJSON = {
  __proto__: Visitor.create(),

  visitFunction: function(o) {
    return o.toString();
  },

  visitObject: function(o) {
    this.push({
      model_: (o.model_.package ? o.model_.package + '.' : '') + o.model_.name
    });
    this.__proto__.visitObject.call(this, o);
    return this.pop();
  },
  visitProperty: function(o, prop) {
    prop.propertyToJSON(this, this.top(), o);
  },

  visitMap: function(o) {
    this.push({});
    Visitor.visitMap.call(this, o);
    return this.pop();
  },
  visitMapElement: function(key, value) { this.top()[key] = this.visit(value); },

  visitArray: function(o) {
    this.push([]);
    this.__proto__.visitArray.call(this, o);
    return this.pop();
  },
  visitArrayElement: function (arr, i) { this.top().push(this.visit(arr[i])); }
};

var JSONToObject = {
  __proto__: ObjectToJSON.create(),

  visitString: function(o) {
    try {
      return o.substr(0, 9) === 'function(' ?
        eval('(' + o + ')') :
        o ;
    } catch (x) {
      console.log(x, o);
      return o;
    }
  },

  visitObject: function(o) {
    var model   = X.lookup(o.model_);
    if ( ! model ) throw new Error('Unknown Model: ' + o.model_);
    var obj     = model.create();

    //    o.forEach((function(value, key) {
    // Workaround for crbug.com/258522
    Object_forEach(o, (function(value, key) {
      if ( key !== 'model_' ) obj[key] = this.visit(value);
    }).bind(this));

    return obj;
  },

  // Substitute in-place
  visitArray: Visitor.visitArray,
  visitArrayElement: function (arr, i) { arr[i] = this.visit(arr[i]); }
};

CLASS({
  name: 'FilteredDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: '
Internal use only.
',

  properties: [
    {
      name: 'query',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      return this.delegate.select(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    removeAll: function(sink, options) {
      return this.delegate.removeAll(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    listen: function(sink, options) {
      return this.SUPER(sink, options ? {
        __proto__: options,
        query: options.query ?
          AND(this.query, options.query) :
          this.query
      } : {query: this.query});
    },
    toString: function() {
      return this.delegate + '.where(' + this.query + ')';
    }
  }
});

CLASS({
  name: 'OrderedDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'comparator',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      if ( options ) {
        if ( ! options.order )
          options = { __proto__: options, order: this.comparator };
      } else {
        options = {order: this.comparator};
      }

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.orderBy(' + this.comparator + ')';
    }
  }

});

CLASS({
  name: 'LimitedDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'count',
      required: true
    }
  ],
  methods: {
    select: function(sink, options) {
      if ( options ) {
        if ( 'limit' in options ) {
          options = {
            __proto__: options,
            limit: Math.min(this.count, options.limit)
          };
        } else {
          options = { __proto__: options, limit: this.count };
        }
      }
      else {
        options = { limit: this.count };
      }

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.limit(' + this.count + ')';
    }
  }
});

CLASS({
  name: 'SkipDAO_',
  extendsModel: 'foam.dao.ProxyDAO',

  documentation: function() {/*

Internal use only.

      */},

  properties: [
    {
      name: 'skip',
      required: true,
      postSet: function() {
        if ( this.skip !== Math.floor(this.skip) )
          console.warn('skip() called with non-integer value: ' + this.skip);
      }
    }
  ],
  methods: {
    select: function(sink, options) {
      options = options ? { __proto__: options, skip: this.skip } : { skip: this.skip };

      return this.delegate.select(sink, options);
    },
    toString: function() {
      return this.delegate + '.skip(' + this.skip + ')';
    }
  }
});

CLASS({
  name: 'RelationshipDAO',
  extendsModel: 'FilteredDAO_',
  documentation: 'Adapts a DAO based on a Relationship.',

  properties: [
    {
      name: 'relatedProperty',
      required: true
    },
    {
      name: 'relativeID',
      required: true
    },
    {
      name: 'query',
      lazyFactory: function() {
        return AND(NEQ(this.relatedProperty, ''),
            EQ(this.relatedProperty, this.relativeID));
      }
    },
  ],

  methods: [
    function put(obj, sink) {
      obj[this.relatedProperty.name] = this.relativeID;
      this.SUPER(obj, sink);
    }
  ]
});

function atxn(afunc) {
  return function(ret) {
    if ( GLOBAL.__TXN__ ) {
      afunc.apply(this, arguments);
    } else {
      GLOBAL.__TXN__ = {};
      var a = argsToArray(arguments);
      a[0] = function() {
        GLOBAL.__TXN__ = undefined;
        ret();
      };
      afunc.apply(this, a);
    }
  };
}

CLASS({
  name: 'AbstractDAO',

  documentation: function() {/*
    The base for most DAO implementations, $$DOC{ref:'.'} provides basic facilities for
    $$DOC{ref:'.where'}, $$DOC{ref:'.limit'}, $$DOC{ref:'.skip'}, and $$DOC{ref:'.orderBy'}
    operations, and provides for notifications of updates through $$DOC{ref:'.listen'}.
  */},

  properties: [
    {
      name: 'daoListeners_',
      transient: true,
      hidden: true,
      factory: function() { return []; },
      compareProperty: function() { return 0; },
    }
  ],

  methods: {
    update: function(expr) { /* Applies a change to the DAO contents. */
      return this.select(UPDATE(expr, this));
    },

    select: function(sink, options) {
      /* Template method. Override to copy the contents of this DAO (filtered or ordered as
      necessary) to sink. */
    },
    remove: function(query, sink) {
      /* Template method. Override to remove matching items and put them into sink if supplied. */
    },

    pipe: function(sink, options) { /* A $$DOC{ref:'.select'} followed by $$DOC{ref:'.listen'}.
           Dump our contents to sink, then send future changes there as well. */
      sink = this.decorateSink_(sink, options, true);

      var fc   = this.createFlowControl_();
      var self = this;

      this.select({
        put: function() {
          sink.put && sink.put.apply(sink, arguments);
        },
        remove: function() {
          sink.remove && sink.remove.apply(sink, arguments);
        },
        error: function() {
          sink.error && sink.error.apply(sink, arguments);
        },
        eof: function() {
          if ( fc.stopped ) {
            sink.eof && sink.eof();
          } else {
            self.listen(sink, options);
          }
        }
      }, options, fc);
    },

    decorateSink_: function(sink, options, isListener, disableLimit) {
      if ( options ) {
        if ( ! disableLimit ) {
          if ( options.limit ) sink = limitedSink(options.limit, sink);
          if ( options.skip )  sink = skipSink(options.skip, sink);
        }

        if ( options.order && ! isListener ) {
          sink = orderedSink(options.order, sink);
        }

        if ( options.query ) {
          sink = predicatedSink(
            options.query.partialEval ?
              options.query.partialEval() :
              options.query,
            sink) ;
        }
      }

      return sink;
    },

    createFlowControl_: function() {
      return {
        stop: function() { this.stopped = true; },
        error: function(e) { this.errorEvt = e; }
      };
    },

    where: function(query) { /* Return a DAO that contains a filtered subset of this one. */
      // only use X if we are an invalid instance without a this.Y
      return (this.Y || X).lookup('FilteredDAO_').create({query: query, delegate: this});
    },

    limit: function(count) { /* Return a DAO that contains a count limited subset of this one. */
      return (this.Y || X).lookup('LimitedDAO_').create({count:count, delegate:this});
    },

    skip: function(skip) { /* Return a DAO that contains a subset of this one, skipping initial items. */
      return (this.Y || X).lookup('SkipDAO_').create({skip:skip, delegate:this});
    },

    orderBy: function() { /* Return a DAO that contains a subset of this one, ordered as specified. */
      return (this.Y || X).lookup('OrderedDAO_').create({ comparator: arguments.length == 1 ? arguments[0] : argsToArray(arguments), delegate: this });
    },

    listen: function(sink, options) { /* Send future changes to sink. */
      this.daoListeners_.push(this.decorateSink_(sink, options, true));
    },

    unlisten: function(sink) { /* Stop sending updates to the given sink. */
      var ls = this.daoListeners_;
//      if ( ! ls.length ) console.warn('Phantom DAO unlisten: ', this, sink);
      for ( var i = 0; i < ls.length ; i++ ) {
        if ( ls[i].$UID === sink.$UID ) {
          ls.splice(i, 1);
          return true;
        }
      }
      if ( DEBUG ) console.warn('Phantom DAO unlisten: ', this, sink);
    },

    // Default removeAll: calls select() with the same options and
    // calls remove() for all returned values.
    removeAll: function(sink, options) { /* Default $$DOC{ref:'.removeAll'}: calls
            $$DOC{ref:'.select'} with the same options and calls $$DOC{ref:'.remove'}
             for all returned values. */
      var self = this;
      var future = afuture();
      this.select({
        put: function(obj) {
          self.remove(obj, { remove: sink && sink.remove });
        }
      })(function() {
        sink && sink.eof();
        future.set();
      });
      return future.get;
    },

    /**
     * Notify all listeners of update to DAO.
     * @param fName the name of the method in the listeners to call.
     *        possible values: 'put', 'remove'
     **/
    notify_: function(fName, args) {
      // console.log(this.name_, ' ***** notify ', fName, ' args: ', args, ' listeners: ', this.daoListeners_);
      for( var i = 0 ; i < this.daoListeners_.length ; i++ ) {
        var l = this.daoListeners_[i];
        var fn = l[fName];
        if ( fn ) {
          // Create flow-control object
          args[2] = {
            stop: (function(fn, l) {
              return function() { fn(l); };
            })(this.unlisten.bind(this), l),
            error: function(e) { /* Don't care. */ }
          };
          try {
            fn.apply(l, args);
          } catch(err) {
            if ( err !== this.UNSUBSCRIBE_EXCEPTION ) {
              console.error('Error delivering event (removing listener): ', fName, err);
              if ( DEBUG ) console.error(err.stack); // TODO: make a NO_DEBUGGER flag for mobile debugger mode?
            }
            this.unlisten(l);
          }
        }
      }
    },

  }
});

// Experimental, convert all functions into sinks
Function.prototype.put    = function() { this.apply(this, arguments); };
Function.prototype.remove = function() { this.apply(this, arguments); };
Function.prototype.reset = function() { this.call(this); };
//Function.prototype.error  = function() { this.apply(this, arguments); };
//Function.prototype.eof    = function() { this.apply(this, arguments); };
<|endoftext|>


<commit_before>var browserify = require('browserify'),
    fs = require('fs'),
    resumer = require('resumer'),
    path = require('path'),
    childProcess = require("child_process"),
    exec = childProcess.exec,
    stream = require('stream'),
    defaults = {
        installDirectory: './globalify_modules',
        version: 'x.x.x'
    };

module.exports = function globalify(settings, callback){

    settings = settings || {};

    for(var key in defaults){
        settings[key] = settings[key] || defaults[key];
    }

    var moduleName = settings.module,
        version = settings.version,
        outputFileName = moduleName + '-' + version.replace(/\./g,'-') + '.js',
        outputStream = stream.PassThrough(),
        bundleStream;

    function globalifyModule(moduleName, callback){

        var stream = resumer().queue('window["' + (settings.globalVariable || moduleName) + '"] = require("' + moduleName + '");').end();
        var b = browserify({
            entries: [stream],
            basedir: path.resolve(process.cwd(), settings.installDirectory)
        });

        bundleStream = b.bundle(callback).pipe(outputStream);
    }

    function installModule(moduleName, version, callback){
        var installDirectory = path.resolve(process.cwd(), settings.installDirectory),
            packagePath = path.join(installDirectory, 'package.json');

        if(!fs.existsSync(installDirectory)){
            fs.mkdirSync(installDirectory);
        }

        if(!fs.existsSync(packagePath)){
            fs.writeFileSync(packagePath, JSON.stringify({
                name:'globalify-modules'
            }));
        };

        exec('npm install ' + moduleName + '@"' + version + '"',
        {
            cwd: installDirectory
        },
        function(error){
            callback(error);
        });
    }

    installModule(moduleName, version, function(error){
        if(error){
            callback(error);
            return;
        }
        globalifyModule(moduleName, callback);
    });

    return outputStream;
}<commit_msg>switched to API version of NPM<commit_after>var browserify = require('browserify'),
    fs = require('fs'),
    npm = require('npm'),
    resumer = require('resumer'),
    path = require('path'),
    stream = require('stream'),
    defaults = {
        installDirectory: './globalify_modules',
        version: 'x.x.x'
    };

module.exports = function globalify(settings, callback){

    settings = settings || {};

    for(var key in defaults){
        settings[key] = settings[key] || defaults[key];
    }

    var moduleName = settings.module,
        version = settings.version,
        outputFileName = moduleName + '-' + version.replace(/\./g,'-') + '.js',
        outputStream = stream.PassThrough(),
        bundleStream;

    function globalifyModule(moduleName, callback){

        var stream = resumer().queue('window["' + (settings.globalVariable || moduleName) + '"] = require("' + moduleName + '");').end();
        var b = browserify({
            entries: [stream],
            basedir: path.resolve(process.cwd(), settings.installDirectory)
        });

        bundleStream = b.bundle(callback).pipe(outputStream);
    }

    function npmInstall(module, version, callback){
        var nameAndVersion = module + (version ? '@"' + version + '"' : '');
        npm.commands.install([nameAndVersion], function (error, data) {
            callback(error);
        });
    }

    function installModule(moduleName, version, callback){
        var installDirectory = path.resolve(process.cwd(), settings.installDirectory),
            packagePath = path.join(installDirectory, 'package.json');

        if(!fs.existsSync(installDirectory)){
            fs.mkdirSync(installDirectory);
        }

        if(!fs.existsSync(packagePath)){
            fs.writeFileSync(packagePath, JSON.stringify({
                name:'globalify-modules'
            }));
        }

        npm.load({
                prefix: installDirectory
            },
            function(error) {
                if(!version || version === 'x.x.x'){
                    npmInstall(moduleName, null, callback);
                }else{
                    npmInstall(moduleName, version, callback);
                }
            }
        );
    }

    installModule(moduleName, version, function(error){
        if(error){
            callback(error);
            return;
        }
        globalifyModule(moduleName, callback);
    });

    return outputStream;
}<|endoftext|>