<commit_before>
import React from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Button,
          Animated } from 'react-native';

export default class MuralInfoPage extends React.Component {

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

    toggleShowDescription() {
      this.setState({descriptionVisible: !this.state.descriptionVisible})
    }

    render() {
        return (
            <View style = {styles.container}>
              <OpacityView style = {styles.darkOverlay} visible = {this.state.descriptionVisible}/>
              <View style = {styles.textContainer}>
                <View style = {styles.top}>
                  <View style = {styles.info}>
                    <View>
                      <Text style = {styles.name}>Mural Name</Text>
                    </View>
                    <View>
                      <Text style = {styles.artist}>Artist Name</Text>
                    </View>
                  </View>
                  <View style = {styles.button}>
                    <Button title = "CLICK ME" onPress = {this.toggleShowDescription.bind(this)} />
                  </View>
                </View>
                <DrawerView style = {styles.description} visible = {this.state.descriptionVisible}>
                  <Text>This is the description w00t</Text>
                </DrawerView>
              </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  textContainer: {
    flex: 1,
    marginTop: '10%',
    padding: 20,
    backgroundColor: 'transparent'
  },
  top: {
    display: 'flex',
    flexDirection: 'row'
  },
  info: {
    flex: 4,
    justifyContent: 'center',
    alignItems: 'flex-start'
  },
  button: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  name: {
    fontSize: 36
  },
  artist: {
    fontSize: 24
  },
  description: {
    marginTop: 50
  },
  darkOverlay: {
    position: 'absolute',
    height: '100%',
    width: '100%',
    backgroundColor: 'grey',
  }
});

// A view that transitions from hidden to visible and back
class OpacityView extends React.Component {

  constructor(props) {
    super(props)
    opacity = 0.0;
    if (props.visible) {
      opacity = 1.0
    }
    this.state = {
      opacity: new Animated.Value(opacity)
    };
  }

  componentWillReceiveProps(nextProps) {

    toValue = 0.0
    if (nextProps.visible) {
      toValue = 1.0
    }

    Animated.timing(                  // Animate over time
      this.state.opacity,            // The animated value to drive
      {
        toValue: toValue,                   // Animate to opacity: 1 (opaque)
        duration: 1 * 500,              // Make it take a while
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { opacity } = this.state;

    let style = StyleSheet.flatten([this.props.style, {opacity: opacity}])

    return (
      <Animated.View                 // Special animatable View
        style={style}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

// A view that transitions from hidden to visible by rising
// Hidden : margin-top = a big number
// Visible : margin-top = 0
class DrawerView extends React.Component {

  constructor(props) {
    super(props)
    margin = 1000;
    if (props.visible) {
      margin = 0
    }
    this.state = {
      margin: new Animated.Value(margin)
    };
  }

  componentWillReceiveProps(nextProps) {

    toValue = 1000
    if (nextProps.visible) {
      toValue = 0
    }

    Animated.timing(
      this.state.margin,
      {
        toValue: toValue,
        duration: 1 * 500,
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { margin } = this.state;

    let style = StyleSheet.flatten([this.props.style, {marginTop: margin}])

    return (
      <Animated.View                 // Special animatable View
        style={style}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

<commit_msg>Changed some of the style stuff<commit_after>
import React from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Button,
          Animated } from 'react-native';

export default class MuralInfoPage extends React.Component {

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

    toggleShowDescription() {
      this.setState({descriptionVisible: !this.state.descriptionVisible})
    }

    render() {
        return (
            <View style = {styles.container}>
              <Image style={{flex: 1, position: "absolute", resizeMode: 'cover', height: '100%', width: '100%'}} source={{uri: "https://www.creativesalem.com/wp-content/uploads/2017/09/809f86cc5e7a3b2eb09158dcd3404c77.jpg"}} />
              <OpacityView style = {styles.darkOverlay} visible = {this.state.descriptionVisible}/>
              <View style = {styles.textContainer}>
                <View style = {styles.top}>
                  <View style = {styles.info}>
                    <View>
                      <Text style = {styles.name}>Mural Name</Text>
                    </View>
                    <View>
                      <Text style = {styles.artist}>Artist Name</Text>
                    </View>
                  </View>
                  <View style = {styles.button}>
                    <Button title = "CLICK ME" onPress = {this.toggleShowDescription.bind(this)} />
                  </View>
                </View>
                <DrawerView style = {styles.description} visible = {this.state.descriptionVisible}>
                  <Text style = {{color: 'white'}}>This is the description w00t</Text>
                </DrawerView>
              </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  textContainer: {
    flex: 1,
    marginTop: '10%',
    padding: 20,
    backgroundColor: 'transparent'
  },
  top: {
    display: 'flex',
    flexDirection: 'row'
  },
  info: {
    flex: 4,
    justifyContent: 'center',
    alignItems: 'flex-start'
  },
  button: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  name: {
    color: 'white',
    textShadowColor: 'black',
    textShadowOffset: {width : 1, height: 1},
    fontSize: 36
  },
  artist: {
    color: 'white',
    textShadowOffset: {width : 1, height: 1},
    fontSize: 24
  },
  description: {
    marginTop: 50
  },
  darkOverlay: {
    position: 'absolute',
    height: '100%',
    width: '100%',
    backgroundColor: 'grey',
  }
});

// A view that transitions from hidden to visible and back
class OpacityView extends React.Component {

  constructor(props) {
    super(props)
    opacity = 0.0;
    if (props.visible) {
      opacity = .7
    }
    this.state = {
      opacity: new Animated.Value(opacity)
    };
  }

  componentWillReceiveProps(nextProps) {

    toValue = 0.0
    if (nextProps.visible) {
      toValue = .7
    }

    Animated.timing(                  // Animate over time
      this.state.opacity,            // The animated value to drive
      {
        toValue: toValue,                   // Animate to opacity: 1 (opaque)
        duration: 1 * 500,              // Make it take a while
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { opacity } = this.state;

    let style = StyleSheet.flatten([this.props.style, {opacity: opacity}])

    return (
      <Animated.View                 // Special animatable View
        style={style}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

// A view that transitions from hidden to visible by rising
// Hidden : margin-top = a big number
// Visible : margin-top = 0
class DrawerView extends React.Component {

  constructor(props) {
    super(props)
    margin = 1000;
    if (props.visible) {
      margin = 0
    }
    this.state = {
      margin: new Animated.Value(margin)
    };
  }

  componentWillReceiveProps(nextProps) {

    toValue = 1000
    if (nextProps.visible) {
      toValue = 0
    }

    Animated.timing(
      this.state.margin,
      {
        toValue: toValue,
        duration: 1 * 500,
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { margin } = this.state;

    let style = StyleSheet.flatten([this.props.style, {marginTop: margin}])

    return (
      <Animated.View                 // Special animatable View
        style={style}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}
<|endoftext|>


<commit_before>// moment.js language configuration
// language : chinese
// author : suupic : https://github.com/suupic
// author : Zeno Zeng : https://github.com/zenozeng

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['moment'], factory); // AMD
    } else if (typeof exports === 'object') {
        factory(require('../moment')); // Node
    } else {
        factory(window.moment); // Browser global
    }
}(function (moment) {
    moment.lang('zh-cn', {
        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
        weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"),
        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
        longDateFormat : {
            LT : "Ah点mm",
            L : "YYYY年MMMD日",
            LL : "YYYY年MMMD日",
            LLL : "YYYY年MMMD日LT",
            LLLL : "YYYY年MMMD日ddddLT",
            l : "YYYY年MMMD日",
            ll : "YYYY年MMMD日",
            lll : "YYYY年MMMD日LT",
            llll : "YYYY年MMMD日ddddLT"
        },
        meridiem : function (hour, minute, isLower) {
            var hm = hour*100 + minute;
            if (hm < 600) {
                return "凌晨";
            } else if (hm < 900) {
                return "早上";
            } else if (hm < 1130) {
                return "上午";
            } else if (hm < 1230) {
                return "中午";
            } else if (hm < 1800) {
                return "下午";
            } else {
                return "晚上";
            }
        },
        calendar : {
            sameDay : function () {
                return this.minutes() === 0 ? "[今天]Ah[点整]" : "[今天]T";
            },
            nextDay : function () {
                return this.minutes() === 0 ? "[明天]Ah[点整]" : "[明天]T";
            },
            lastDay : function () {
                return this.minutes() === 0 ? "[昨天]Ah[点整]" : "[昨天]T";
            },
            nextWeek : function () {
                var startOfWeek, prefix;
                startOfWeek = moment().startOf('week');
                prefix = this.unix() - startOfWeek.unix() > 7 * 24 * 3600 ? '[下]' : '[本]';
                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
            },
            lastWeek : function () {
                var startOfWeek, prefix;
                startOfWeek = moment().startOf('week');
                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
            },
            sameElse : 'L'
        },
        ordinal : function (number, period) {
            switch (period) {
            case "d":
            case "D":
            case "DDD":
                return number + "日";
            case "M":
                return number + "月";
            case "w":
            case "W":
                return number + "周";
            default:
                return number;
            }
        },
        relativeTime : {
            future : "%s内",
            past : "%s前",
            s : "几秒",
            m : "1分钟",
            mm : "%d分钟",
            h : "1小时",
            hh : "%d小时",
            d : "1天",
            dd : "%d天",
            M : "1个月",
            MM : "%d个月",
            y : "1年",
            yy : "%d年"
        },
        week : {
            dow : 1 // Monday is the first day of the week.
        }
    });
}));
<commit_msg>update to pass test<commit_after>// moment.js language configuration
// language : chinese
// author : suupic : https://github.com/suupic
// author : Zeno Zeng : https://github.com/zenozeng

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['moment'], factory); // AMD
    } else if (typeof exports === 'object') {
        factory(require('../moment')); // Node
    } else {
        factory(window.moment); // Browser global
    }
}(function (moment) {
    moment.lang('zh-cn', {
        months : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
        monthsShort : "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),
        weekdays : "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
        weekdaysShort : "周日_周一_周二_周三_周四_周五_周六".split("_"),
        weekdaysMin : "日_一_二_三_四_五_六".split("_"),
        longDateFormat : {
            LT : "Ah点mm",
            L : "YYYY年MMMD日",
            LL : "YYYY年MMMD日",
            LLL : "YYYY年MMMD日LT",
            LLLL : "YYYY年MMMD日ddddLT",
            l : "YYYY年MMMD日",
            ll : "YYYY年MMMD日",
            lll : "YYYY年MMMD日LT",
            llll : "YYYY年MMMD日ddddLT"
        },
        meridiem : function (hour, minute, isLower) {
            var hm = hour * 100 + minute;
            if (hm < 600) {
                return "凌晨";
            } else if (hm < 900) {
                return "早上";
            } else if (hm < 1130) {
                return "上午";
            } else if (hm < 1230) {
                return "中午";
            } else if (hm < 1800) {
                return "下午";
            } else {
                return "晚上";
            }
        },
        calendar : {
            sameDay : function () {
                return this.minutes() === 0 ? "[今天]Ah[点整]" : "[今天]T";
            },
            nextDay : function () {
                return this.minutes() === 0 ? "[明天]Ah[点整]" : "[明天]T";
            },
            lastDay : function () {
                return this.minutes() === 0 ? "[昨天]Ah[点整]" : "[昨天]T";
            },
            nextWeek : function () {
                var startOfWeek, prefix;
                startOfWeek = moment().startOf('week');
                prefix = this.unix() - startOfWeek.unix() > 7 * 24 * 3600 ? '[下]' : '[本]';
                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
            },
            lastWeek : function () {
                var startOfWeek, prefix;
                startOfWeek = moment().startOf('week');
                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
                return this.minutes() === 0 ? prefix + "dddAh点整" : prefix + "dddAh点mm";
            },
            sameElse : 'L'
        },
        ordinal : function (number, period) {
            switch (period) {
            case "d":
            case "D":
            case "DDD":
                return number + "日";
            case "M":
                return number + "月";
            case "w":
            case "W":
                return number + "周";
            default:
                return number;
            }
        },
        relativeTime : {
            future : "%s内",
            past : "%s前",
            s : "几秒",
            m : "1分钟",
            mm : "%d分钟",
            h : "1小时",
            hh : "%d小时",
            d : "1天",
            dd : "%d天",
            M : "1个月",
            MM : "%d个月",
            y : "1年",
            yy : "%d年"
        },
        week : {
            dow : 1 // Monday is the first day of the week.
        }
    });
}));
<|endoftext|>


<commit_before>import moment from 'moment'
import _ from 'lodash'
import { ObjectID } from 'mongodb'
import makeDebug from 'debug'

const debug = makeDebug('kalisio:kCore:query:hooks')

function marshallComparisonFieldsInQuery (queryObject) {
  _.forOwn(queryObject, (value, key) => {
    // Process current attributes or  recurse
    if (typeof value === 'object') {
      marshallComparisonFieldsInQuery(value)
    } else if ((key === '$lt') || (key === '$lte') || (key === '$gt') || (key === '$gte')) {
      let number = _.toNumber(value)
      // Update from query string to number if required
      if (!Number.isNaN(number)) {
        queryObject[key] = number
      } else {
        // try for dates as well
        let date = moment.utc(value)
        if (date.isValid()) {
          queryObject[key] = new Date(date.format())
        }
      }
    }
  })
}

export function marshallComparisonQuery (hook) {
  let query = hook.params.query
  if (query) {
    // Complex queries might have nested objects so we call a recursive function to handle this
    marshallComparisonFieldsInQuery(query)
  }
}

export function marshallGeometryQuery (hook) {
  let query = hook.params.query
  if (!query) return

  if (typeof query.geometry === 'object') {
    // Geospatial operators begin with $
    let geoOperator = _.keys(query.geometry).find(key => key.startsWith('$'))
    geoOperator = query.geometry[geoOperator]
    _.forOwn(geoOperator, (value, key) => {
      // Geospatial parameters begin with $
      if (key.startsWith('$')) {
        // Some target coordinates
        if (!_.isNil(value.coordinates)) {
          value.coordinates = value.coordinates.map(coordinate => _.toNumber(coordinate))
        } else {
          // Other simple values
          geoOperator[key] = _.toNumber(value)
        }
      }
    })
  }
}

export function populateObject (options) {
  return function (hook) {
    let app = hook.app
    let data = hook.data
    let params = hook.params
    let query = params.query
    const idProperty = options.nameIdAs || options.idField
    const serviceProperty = options.nameServiceAs || options.serviceField

    // Check if not already done
    if (typeof _.get(params, idProperty) === 'object') {
      debug(`Skipping populating ${idProperty} as already done`)
      return Promise.resolve(hook)
    }
    if (typeof _.get(params, serviceProperty) === 'object') {
      debug(`Skipping populating ${serviceProperty} as already done`)
      return Promise.resolve(hook)
    }

    // Get service where we can find the object to populate
    // Make hook usable with query params as well and service name or real object
    let service = _.get(data, options.serviceField) || _.get(query, options.serviceField)
    if (typeof service === 'string') {
      const message = `Cannot find the service for ${options.serviceField} = ${service} to dynamically populate.`
      service = app.getService(service)
      if (!service) {
        if (options.throwOnNotFound) throw new Error(message)
        else return Promise.resolve(hook)
      }
    } else if (!service) {
      if (options.throwOnNotFound) throw new Error(`No ${options.serviceField} given to dynamically populate.`)
      else return Promise.resolve(hook)
    }
    // Then the object ID
    let id = _.get(data, options.idField) || _.get(query, options.idField) || _.get(hook, 'id')
    if (!id) {
      if (options.throwOnNotFound) throw new Error(`Cannot find the ${options.idField} to dynamically populate.`)
      else return Promise.resolve(hook)
    }

    debug(`Populating ${idProperty} with ID ${id}`)
    // Set the retrieved service on the same field or given one in hook params
    _.set(params, serviceProperty, service)
    // Let it work with id string or real object
    if (typeof id === 'string' || ObjectID.isValid(id)) {
      return service.get(id.toString(), { user: hook.params.user }).then(object => {
        if (!object) {
          if (options.throwOnNotFound) throw new Error(`Cannot find object with id ${id} to dynamically populate.`)
          else return hook
        }
        // Set the retrieved object on the same field or given one in hook params
        _.set(params, idProperty, object)
        return hook
      })
    } else {
      // Set the object on the same field or given one in hook params
      _.set(params, idProperty, id)
      return Promise.resolve(hook)
    }
  }
}

export function populateObjects (options) {
  return function (hook) {
    let app = hook.app
    let data = hook.data
    let params = hook.params
    let query = params.query
    const idProperty = options.nameIdAs || options.idField
    const serviceProperty = options.nameServiceAs || options.serviceField

    // Check if not already done
    if (Array.isArray(_.get(params, idProperty))) {
      debug(`Skipping populating ${idProperty} as already done`)
      return Promise.resolve(hook)
    }
    if (typeof _.get(params, serviceProperty) === 'object') {
      debug(`Skipping populating ${serviceProperty} as already done`)
      return Promise.resolve(hook)
    }

    // Get service where we can find the object to populate
    // Make hook usable with query params as well and service name or real object
    let service = _.get(data, options.serviceField) || _.get(query, options.serviceField)
    if (typeof service === 'string') {
      const message = `Cannot find the service for ${options.serviceField} = ${service} to dynamically populate.`
      service = app.getService(service)
      if (!service) {
        if (options.throwOnNotFound) throw new Error(message)
        else return Promise.resolve(hook)
      }
    } else if (!service) {
      if (options.throwOnNotFound) throw new Error(`No ${options.serviceField} given to dynamically populate.`)
      else return Promise.resolve(hook)
    }

    // Set the retrieved service on the same field or given one in hook params
    _.set(params, serviceProperty, service)

    // Then the object ID
    let id = _.get(data, options.idField) || _.get(query, options.idField)
    // If no ID given we perform a find, no pagination to be sure we get all objects
    if (!id) {
      debug(`Populating ${idProperty}`)
      return service.find({ query: {}, paginate: false, user: hook.params.user }).then(objects => {
        // Set the retrieved objects on the same field or given one in hook params
        debug(`Populated ${objects.length} ${idProperty}`)
        _.set(params, idProperty, objects)
        return hook
      })
    } else {
      debug(`Populating ${idProperty} with ID ${id}`)
      // Let it work with id string or real object
      if (typeof id === 'string' || ObjectID.isValid(id)) {
        return service.get(id.toString(), { user: hook.params.user }).then(object => {
          if (!object) {
            if (options.throwOnNotFound) throw new Error(`Cannot find ${options.idField} = ${id} to dynamically populate.`)
            else return hook
          }
          // Set the retrieved object on the same field or given one in hook params
          _.set(params, idProperty, [object])
          return hook
        })
      } else {
        // Set the object on the same field or given one in hook params
        _.set(params, idProperty, [id])
        return Promise.resolve(hook)
      }
    }
  }
}
<commit_msg>Make populateObject(s) work with contextual services<commit_after>import moment from 'moment'
import _ from 'lodash'
import { ObjectID } from 'mongodb'
import makeDebug from 'debug'

const debug = makeDebug('kalisio:kCore:query:hooks')

function marshallComparisonFieldsInQuery (queryObject) {
  _.forOwn(queryObject, (value, key) => {
    // Process current attributes or  recurse
    if (typeof value === 'object') {
      marshallComparisonFieldsInQuery(value)
    } else if ((key === '$lt') || (key === '$lte') || (key === '$gt') || (key === '$gte')) {
      let number = _.toNumber(value)
      // Update from query string to number if required
      if (!Number.isNaN(number)) {
        queryObject[key] = number
      } else {
        // try for dates as well
        let date = moment.utc(value)
        if (date.isValid()) {
          queryObject[key] = new Date(date.format())
        }
      }
    }
  })
}

export function marshallComparisonQuery (hook) {
  let query = hook.params.query
  if (query) {
    // Complex queries might have nested objects so we call a recursive function to handle this
    marshallComparisonFieldsInQuery(query)
  }
}

export function marshallGeometryQuery (hook) {
  let query = hook.params.query
  if (!query) return

  if (typeof query.geometry === 'object') {
    // Geospatial operators begin with $
    let geoOperator = _.keys(query.geometry).find(key => key.startsWith('$'))
    geoOperator = query.geometry[geoOperator]
    _.forOwn(geoOperator, (value, key) => {
      // Geospatial parameters begin with $
      if (key.startsWith('$')) {
        // Some target coordinates
        if (!_.isNil(value.coordinates)) {
          value.coordinates = value.coordinates.map(coordinate => _.toNumber(coordinate))
        } else {
          // Other simple values
          geoOperator[key] = _.toNumber(value)
        }
      }
    })
  }
}

export function populateObject (options) {
  return function (hook) {
    let app = hook.app
    let data = hook.data
    let params = hook.params
    let query = params.query
    const context = hook.service.context
    const idProperty = options.nameIdAs || options.idField
    const serviceProperty = options.nameServiceAs || options.serviceField

    // Check if not already done
    if (typeof _.get(params, idProperty) === 'object') {
      debug(`Skipping populating ${idProperty} as already done`)
      return Promise.resolve(hook)
    }
    if (typeof _.get(params, serviceProperty) === 'object') {
      debug(`Skipping populating ${serviceProperty} as already done`)
      return Promise.resolve(hook)
    }

    // Get service where we can find the object to populate
    // Make hook usable with query params as well and service name or real object
    let service = _.get(data, options.serviceField) || _.get(query, options.serviceField)
    if (typeof service === 'string') {
      const message = `Cannot find the service for ${options.serviceField} = ${service} to dynamically populate.`
      service = app.getService(service, context)
      if (!service) {
        if (options.throwOnNotFound) throw new Error(message)
        else return Promise.resolve(hook)
      }
    } else if (!service) {
      if (options.throwOnNotFound) throw new Error(`No ${options.serviceField} given to dynamically populate.`)
      else return Promise.resolve(hook)
    }
    // Then the object ID
    let id = _.get(data, options.idField) || _.get(query, options.idField) || _.get(hook, 'id')
    if (!id) {
      if (options.throwOnNotFound) throw new Error(`Cannot find the ${options.idField} to dynamically populate.`)
      else return Promise.resolve(hook)
    }

    debug(`Populating ${idProperty} with ID ${id}`)
    // Set the retrieved service on the same field or given one in hook params
    _.set(params, serviceProperty, service)
    // Let it work with id string or real object
    if (typeof id === 'string' || ObjectID.isValid(id)) {
      return service.get(id.toString(), { user: hook.params.user }).then(object => {
        if (!object) {
          if (options.throwOnNotFound) throw new Error(`Cannot find object with id ${id} to dynamically populate.`)
          else return hook
        }
        // Set the retrieved object on the same field or given one in hook params
        _.set(params, idProperty, object)
        return hook
      })
    } else {
      // Set the object on the same field or given one in hook params
      _.set(params, idProperty, id)
      return Promise.resolve(hook)
    }
  }
}

export function populateObjects (options) {
  return function (hook) {
    let app = hook.app
    let data = hook.data
    let params = hook.params
    let query = params.query
    const context = hook.service.context
    const idProperty = options.nameIdAs || options.idField
    const serviceProperty = options.nameServiceAs || options.serviceField

    // Check if not already done
    if (Array.isArray(_.get(params, idProperty))) {
      debug(`Skipping populating ${idProperty} as already done`)
      return Promise.resolve(hook)
    }
    if (typeof _.get(params, serviceProperty) === 'object') {
      debug(`Skipping populating ${serviceProperty} as already done`)
      return Promise.resolve(hook)
    }

    // Get service where we can find the object to populate
    // Make hook usable with query params as well and service name or real object
    let service = _.get(data, options.serviceField) || _.get(query, options.serviceField)
    if (typeof service === 'string') {
      const message = `Cannot find the service for ${options.serviceField} = ${service} to dynamically populate.`
      service = app.getService(service, context)
      if (!service) {
        if (options.throwOnNotFound) throw new Error(message)
        else return Promise.resolve(hook)
      }
    } else if (!service) {
      if (options.throwOnNotFound) throw new Error(`No ${options.serviceField} given to dynamically populate.`)
      else return Promise.resolve(hook)
    }

    // Set the retrieved service on the same field or given one in hook params
    _.set(params, serviceProperty, service)

    // Then the object ID
    let id = _.get(data, options.idField) || _.get(query, options.idField)
    // If no ID given we perform a find, no pagination to be sure we get all objects
    if (!id) {
      debug(`Populating ${idProperty}`)
      return service.find({ query: {}, paginate: false, user: hook.params.user }).then(objects => {
        // Set the retrieved objects on the same field or given one in hook params
        debug(`Populated ${objects.length} ${idProperty}`)
        _.set(params, idProperty, objects)
        return hook
      })
    } else {
      debug(`Populating ${idProperty} with ID ${id}`)
      // Let it work with id string or real object
      if (typeof id === 'string' || ObjectID.isValid(id)) {
        return service.get(id.toString(), { user: hook.params.user }).then(object => {
          if (!object) {
            if (options.throwOnNotFound) throw new Error(`Cannot find ${options.idField} = ${id} to dynamically populate.`)
            else return hook
          }
          // Set the retrieved object on the same field or given one in hook params
          _.set(params, idProperty, [object])
          return hook
        })
      } else {
        // Set the object on the same field or given one in hook params
        _.set(params, idProperty, [id])
        return Promise.resolve(hook)
      }
    }
  }
}
<|endoftext|>


<commit_before>'use strict'

const assert = require('assert')
const Model = require('../')

describe('Trails Model', () => {
  const Foo = class Foo extends Model {
    static config () {
      return {
        tableName: 'foo'
      }
    }
  }
  const Bar = class Bar extends Model { }
  const SubFoo = class SubFoo extends Foo {
    static config () {
      return {
        tableName: 'subfoo'
      }
    }
  }
  const SubBar = class SubBar extends Bar { }

  describe('#constructor', () => {
    it('.app should be accessible but not enumerable', () => {
      let foo = new Foo(1)
      let keys = Object.keys(foo)

      assert.equal(foo.app, 1)
      assert.equal(keys.indexOf('app'), -1)
    })

  })

  describe('#getModelName', () => {
    it('should return correct model name', () => {
      const foo = new Foo()
      assert(foo.getModelName(), 'foo')
    })
  })

  describe('#getTableName', () => {
    it('should return tableName set in config', () => {
      const foo = new Foo()
      assert.equal(foo.getTableName(), 'foo')
    })
    it('should return tableName named after className if no tableName set', () => {
      const bar = new Bar()
      assert.equal(bar.getTableName(), 'bar')
    })
    it('should return tableName named after className of subclass', () => {
      const subbar = new SubBar()
      assert.equal(subbar.getTableName(), 'subbar')
    })
    it('should return tableName set in config of subclass', () => {
      const subfoo = new SubFoo()
      assert.equal(subfoo.getTableName(), 'subfoo')
    })
  })
})

<commit_msg>remove model.test.js as it's not relevant here<commit_after><|endoftext|>


<commit_before>// Exported Functions and prototypes are defined at end of file

var pg       = require('pg');
var async    = require('async');
var config   = require('../config.js');
var markdown = require('markdown').markdown;
var should   = require('should');
var moment   = require('moment');

var articleModule = require('../model/article.js');
var logModule = require('../model/logModule.js');

var pgMap = require('./pgMap.js')
var debug = require('debug')('OSMBC:model:blog');

module.exports.table = "blog";

module.exports.categories = [
  {DE:"[Aktuelle Kategorie]",EN:"[Actual Category]"},
  {DE:"In eigener Sache",EN:"About us"},
  {DE:"Wochenaufruf",EN:"Weekly exerciseEN:"},
  {DE:"Mapping",EN:"Mapping"},
  {DE:"Community",EN:"Community"},
  {DE:"Importe",EN:"Imports"},
  {DE:"OpenStreetMap Foundation",EN:"OpenStreetMap Foundation"},
  {DE:"Veranstaltungen",EN:"Events"},
  {DE:"Humanitarian OSM",EN:"Humanitarian OSM"},
  {DE:"Karten",EN:"Maps"},
  {DE:"switch2OSM",EN:"#switch2OSM"},
  {DE:"Open-Data",EN:"Open Data"},
  {DE:"Lizenzen",EN:"Licences"},
  {DE:"Programme",EN:"Software"},
  {DE:"Programmierung",EN:"Programming"},
  {DE:"Kennst Du schon …",EN:"Did you know …"},
  {DE:"Weitere Themen mit Geo-Bezug",EN:'Other “geo” things'},
  {DE:"Wochenvorschau" ,EN:"Not Translated"}];

module.exports.internalCateogries = [
{DE:"--unpublished--" ,EN:"--unpublished--"},
{DE:"--uncategorized--" ,EN:"--uncategorized--"}
]

function Blog(proto)
{
  debug("Blog");
  this.id = 0;
  this._meta={};
  this._meta.table = "blog";
  this.categories = module.exports.categories;
  if (proto) {
    for (var k in proto) {
      this[k] = proto[k];
    }
  }
}

function create (proto) {
  debug("create");
  return new Blog(proto);
}

function setAndSave(user,data,callback) {
  debug("setAndSave");
  var self = this;
  delete self.lock;
  async.series([
    function checkID(cb) {
      if (self.id == 0) {
        self.save(cb);
      } else cb();
    }
  ],function(err){
    should.exist(self.id);
    should(self.id).not.equal(0);
    async.forEachOf(data,function(value,key,callback){
      if (typeof(value)=='undefined') return callback();
      if (value == self[key]) return callback();
      debug("Set Key %s to value %s",key,value);
      debug("Old Value Was %s",self[key]);
      articleModule.removeOpenBlogCache();
      async.series ( [
          function(callback) {
             logModule.log({oid:self.id,user:user,table:"blog",property:key,from:self[key],to:value},callback);
          },
          function(callback) {
            self[key] = value;
            callback();
          }
        ],function(err){
          callback(err);
        })

    },function(err) {
      if (err) return callback(err);
      self.save(callback);
    })
  })
}
function setReviewComment(user,data,callback) {
  debug("reviewComment");
  var self = this;
  async.series([
    function checkID(cb) {
      if (self.id == 0) {
        self.save(cb);
      } else cb();
    }
  ],function(err){
    should.exist(self.id);
    should(self.id).not.equal(0);
    if (typeof(data)=='undefined') return callback();
    if (typeof(self.reviewComment) == "undefined" || self.reviewComment == null) {
      self.reviewComment = [];
    }
    for (var i=0;i<self.reviewComment.length;i++) {
      if (self.reviewComment[i].user == user && self.reviewComment[i].text == data) return callback();
    }
    async.series ( [
        function(callback) {
           logModule.log({oid:self.id,user:user,table:"blog",property:"comment",from:"Add",to:data},callback);
        },
        function(callback) {
          var date = new Date();
          console.log(self.reviewComment);
          self.reviewComment.push({user:user,text:data,timestamp:date});
          callback();
        }
      ],function(err){
        if (err) return callback(err);
        self.save(callback);
      })
  })
}

function find(obj1,obj2,callback) {
  debug("find");
  pgMap.find(this,obj1,obj2,callback);
}
function findById(id,callback) {
  debug("findById %s",id);
  pgMap.findById(id,this,callback);
}

function findOne(obj1,obj2,callback) {
  debug("findOne");
  pgMap.findOne(this,obj1,obj2,callback);
}

function createNewBlog(proto,callback) {
  debug("createNewBlog");
  if (typeof(proto)=='function') {
    callback = proto;
    delete proto;
  }
  should.not.exist(proto.id);

  this.findOne(null,{column:"name",desc:true},function(err,result) {
    var name = "WN250";
    var endDate = new Date();
    if (result) {
      if (result.name.substring(0,2)=="WN") {
        name = result.name;
        if (result.endDate && typeof(result.endDate)!='undefined') {
          endDate = new Date(result.endDate);
        }
      }
    }
    debug("Maximaler Name %s",name);
    var wnId = name.substring(2,99);
    var newWnId = parseInt(wnId) +1;
    var newName = "WN"+newWnId;
    var startDate = new Date(endDate);

    startDate.setDate(startDate.getDate()+1);
    endDate.setDate(endDate.getDate()+7);
    var blog = create();
    blog.name = newName;
    blog.status = "open";
    blog.startDate = startDate;
    blog.endDate = endDate;
    //copy flat prototype to object.
    for (var k in proto) {
      blog[k]=proto[k];
    }
    blog.save(callback);
  });
}

function preview(edit,lang,callback) {
  debug('preview');
  var self = this;

  if (typeof(lang)=='function') {
    callback = lang;
    lang = "DE";
  }
  var articles = {};
  var preview = "";

  articleModule.find({blog:this.name},{column:"title"},function(err,result){

    // first put the Header
    if (lang=='DE')
      preview = '
Wochennotiz '+self.name+'
\n'
    if (lang=='EN')
      preview = '
 Weekly'+self.name+'
\n'
    if (self.startDate && self.endDate) {
      preview += "
"+moment(self.startDate).locale(lang).format('l') +" - "+moment(self.endDate).locale(lang).format('l') +'
\n';
    }
    preview += "\n"

    // Put every article in an array for the category
    for (var i=0;i<result.length;i++ ) {
      var r = result[i];
      if (typeof(articles[r.category]) == 'undefined') {
        articles[r.category] = [];
      }
      articles[r.category].push(r);
    }

    var clist = self.getCategories();

    // Generate the blog result along the categories
    for (var i=0;i<clist.length;i++) {
      var category = clist[i].DE;

      var categoryLANG = clist[i].DE;
      if (lang=="DE") categoryLANG = clist[i].DE;
      if (lang=="EN") categoryLANG = clist[i].EN;

      if (!edit && category =="--unpublished--") continue;

      // If the category exists, generate HTML for it
      if (typeof(articles[category])!='undefined') {
        debug('Generating HTML for category %s',category);
        var htmlForCategory = ''

        for (var j=0;j<articles[category].length;j++) {
          var r = articles[category][j];
          if (edit == 'overview') {
            htmlForCategory += r.overview()+'\n';
          } else if  (lang == "DE") {
            htmlForCategory += r.preview(edit)+'\n';
          } else if (lang == "EN") {
            htmlForCategory += r.previewEN(edit)+'\n';
          }
        }
        var header = '
'+categoryLANG+'
\n';
        htmlForCategory = header + '
\n'+htmlForCategory+'
\n'
        preview += htmlForCategory;
      }
    }
    var result = {};
    result.preview = preview;
    result.articles = articles;
    callback(null, result);
  })
}

function getCategories() {
  debug('getCategories');

  var c = this.categories;
  if (!c) c = module.exports.categories;

  c.push(exports.internalCateogries);
  return c;
}

function createTable(cb) {
  debug('createTable');
  createString = 'CREATE TABLE blog (  id bigserial NOT NULL,  data json,  \
                  CONSTRAINT blog_pkey PRIMARY KEY (id) ) WITH (  OIDS=FALSE);'
  createView = "CREATE INDEX blog_id_idx ON blog USING btree (id);";
  pgMap.createTable('blog',createString,createView,cb)
}

function dropTable(cb) {
  debug('dropTable');
  pgMap.dropTable('blog',cb);
}

// Prototype Functions

// preview(edit,callback)
// edit: boolean, specifying wether generated HTML should contain edit links for articles or not
// result of preview is html code to display the blog.
Blog.prototype.preview = preview;

// setAndSave(user,data,callback)
// user: actual username for logging purposes
// data: json with values that has to be changed
// Function will change the given values and create for every field,
// where the value differes from representation in memory a log entry.
// at the end, the blog value is written in total
// This is may be relevant for concurrent save
// as there is no locking with version numbers yet.
Blog.prototype.setAndSave = setAndSave;

Blog.prototype.setReviewComment = setReviewComment;

// save
// just store the object in the database
Blog.prototype.save = pgMap.save;

// delete the object from the database
Blog.prototype.remove = pgMap.remove;

// Get Categories of the blog
// This can be the global defined, or the one from the blog itself
// Additional there can be some Categories for Edit Reasons
Blog.prototype.getCategories = getCategories;

// Define it on BlogModule level to (for no Blog Specified)
module.exports.getCategories = getCategories;

// Creation Functions

// Create a blog in memory with a given prototype
// create(proto)
// proto: (optional) JSON Data, to copy for the new object
//         the copy is a flat copy
module.exports.create= create;

// Create a blog in the database,
// createNewBlog(proto,callback)
// for parameter see create
// proto is not allowed to have an id, this is generated by the database
// and stored into the object
module.exports.createNewBlog = createNewBlog;

// Find Functions

// find(object,order,callback)
// object (optional) find Objects, that conform with all values in the object
// order (optional)  field to sort by
module.exports.find = find;

// find(id,callback)
// id find Objects with ID
module.exports.findById = findById;

// findOne(object,order,callback)
// same as find, but callback returns one object, if it exists
module.exports.findOne = findOne;

// Create Tables in Prostgres with all indices and views
module.exports.createTable = createTable;

// Delete table in Postgres
module.exports.dropTable = dropTable;
<commit_msg>Revert "Start implementing, but not finished."<commit_after>// Exported Functions and prototypes are defined at end of file

var pg       = require('pg');
var async    = require('async');
var config   = require('../config.js');
var markdown = require('markdown').markdown;
var should   = require('should');
var moment   = require('moment');

var articleModule = require('../model/article.js');
var logModule = require('../model/logModule.js');

var pgMap = require('./pgMap.js')
var debug = require('debug')('OSMBC:model:blog');

module.exports.table = "blog";

module.exports.categories = [
  {DE:"[Aktuelle Kategorie]",EN:"[Actual Category]"},
  {DE:"In eigener Sache",EN:"About us"},
  {DE:"Wochenaufruf",EN:"Weekly exerciseEN:"},
  {DE:"Mapping",EN:"Mapping"},
  {DE:"Community",EN:"Community"},
  {DE:"Importe",EN:"Imports"},
  {DE:"OpenStreetMap Foundation",EN:"OpenStreetMap Foundation"},
  {DE:"Veranstaltungen",EN:"Events"},
  {DE:"Humanitarian OSM",EN:"Humanitarian OSM"},
  {DE:"Karten",EN:"Maps"},
  {DE:"switch2OSM",EN:"#switch2OSM"},
  {DE:"Open-Data",EN:"Open Data"},
  {DE:"Lizenzen",EN:"Licences"},
  {DE:"Programme",EN:"Software"},
  {DE:"Programmierung",EN:"Programming"},
  {DE:"Kennst Du schon …",EN:"Did you know …"},
  {DE:"Weitere Themen mit Geo-Bezug",EN:'Other “geo” things'},
  {DE:"Wochenvorschau" ,EN:"Not Translated"},
  {DE:"--unpublished--" ,EN:"--unpublished--"}];

function Blog(proto)
{
  debug("Blog");
  this.id = 0;
  this._meta={};
  this._meta.table = "blog";
  this.categories = module.exports.categories;
  if (proto) {
    for (var k in proto) {
      this[k] = proto[k];
    }
  }
}

function create (proto) {
  debug("create");
  return new Blog(proto);
}

function setAndSave(user,data,callback) {
  debug("setAndSave");
  var self = this;
  delete self.lock;
  async.series([
    function checkID(cb) {
      if (self.id == 0) {
        self.save(cb);
      } else cb();
    }
  ],function(err){
    should.exist(self.id);
    should(self.id).not.equal(0);
    async.forEachOf(data,function(value,key,callback){
      if (typeof(value)=='undefined') return callback();
      if (value == self[key]) return callback();
      debug("Set Key %s to value %s",key,value);
      debug("Old Value Was %s",self[key]);
      articleModule.removeOpenBlogCache();
      async.series ( [
          function(callback) {
             logModule.log({oid:self.id,user:user,table:"blog",property:key,from:self[key],to:value},callback);
          },
          function(callback) {
            self[key] = value;
            callback();
          }
        ],function(err){
          callback(err);
        })

    },function(err) {
      if (err) return callback(err);
      self.save(callback);
    })
  })
}
function setReviewComment(user,data,callback) {
  debug("reviewComment");
  var self = this;
  async.series([
    function checkID(cb) {
      if (self.id == 0) {
        self.save(cb);
      } else cb();
    }
  ],function(err){
    should.exist(self.id);
    should(self.id).not.equal(0);
    if (typeof(data)=='undefined') return callback();
    if (typeof(self.reviewComment) == "undefined" || self.reviewComment == null) {
      self.reviewComment = [];
    }
    for (var i=0;i<self.reviewComment.length;i++) {
      if (self.reviewComment[i].user == user && self.reviewComment[i].text == data) return callback();
    }
    async.series ( [
        function(callback) {
           logModule.log({oid:self.id,user:user,table:"blog",property:"comment",from:"Add",to:data},callback);
        },
        function(callback) {
          var date = new Date();
          console.log(self.reviewComment);
          self.reviewComment.push({user:user,text:data,timestamp:date});
          callback();
        }
      ],function(err){
        if (err) return callback(err);
        self.save(callback);
      })
  })
}

function find(obj1,obj2,callback) {
  debug("find");
  pgMap.find(this,obj1,obj2,callback);
}
function findById(id,callback) {
  debug("findById %s",id);
  pgMap.findById(id,this,callback);
}

function findOne(obj1,obj2,callback) {
  debug("findOne");
  pgMap.findOne(this,obj1,obj2,callback);
}

function createNewBlog(proto,callback) {
  debug("createNewBlog");
  if (typeof(proto)=='function') {
    callback = proto;
    delete proto;
  }
  should.not.exist(proto.id);

  this.findOne(null,{column:"name",desc:true},function(err,result) {
    var name = "WN250";
    var endDate = new Date();
    if (result) {
      if (result.name.substring(0,2)=="WN") {
        name = result.name;
        if (result.endDate && typeof(result.endDate)!='undefined') {
          endDate = new Date(result.endDate);
        }
      }
    }
    debug("Maximaler Name %s",name);
    var wnId = name.substring(2,99);
    var newWnId = parseInt(wnId) +1;
    var newName = "WN"+newWnId;
    var startDate = new Date(endDate);

    startDate.setDate(startDate.getDate()+1);
    endDate.setDate(endDate.getDate()+7);
    var blog = create();
    blog.name = newName;
    blog.status = "open";
    blog.startDate = startDate;
    blog.endDate = endDate;
    //copy flat prototype to object.
    for (var k in proto) {
      blog[k]=proto[k];
    }
    blog.save(callback);
  });
}

function preview(edit,lang,callback) {
  debug('preview');
  var self = this;

  if (typeof(lang)=='function') {
    callback = lang;
    lang = "DE";
  }
  var articles = {};
  var preview = "";

  articleModule.find({blog:this.name},{column:"title"},function(err,result){

    // first put the Header
    if (lang=='DE')
      preview = '
Wochennotiz '+self.name+'
\n'
    if (lang=='EN')
      preview = '
 Weekly'+self.name+'
\n'
    if (self.startDate && self.endDate) {
      preview += "
"+moment(self.startDate).locale(lang).format('l') +" - "+moment(self.endDate).locale(lang).format('l') +'
\n';
    }
    preview += "\n"

    // Put every article in an array for the category
    for (var i=0;i<result.length;i++ ) {
      var r = result[i];
      if (typeof(articles[r.category]) == 'undefined') {
        articles[r.category] = [];
      }
      articles[r.category].push(r);
    }

    var clist = self.getCategories();

    // Generate the blog result along the categories
    for (var i=0;i<clist.length;i++) {
      var category = clist[i].DE;

      var categoryLANG = clist[i].DE;
      if (lang=="DE") categoryLANG = clist[i].DE;
      if (lang=="EN") categoryLANG = clist[i].EN;

      if (!edit && category =="--unpublished--") continue;

      // If the category exists, generate HTML for it
      if (typeof(articles[category])!='undefined') {
        debug('Generating HTML for category %s',category);
        var htmlForCategory = ''

        for (var j=0;j<articles[category].length;j++) {
          var r = articles[category][j];
          if (edit == 'overview') {
            htmlForCategory += r.overview()+'\n';
          } else if  (lang == "DE") {
            htmlForCategory += r.preview(edit)+'\n';
          } else if (lang == "EN") {
            htmlForCategory += r.previewEN(edit)+'\n';
          }
        }
        var header = '
'+categoryLANG+'
\n';
        htmlForCategory = header + '
\n'+htmlForCategory+'
\n'
        preview += htmlForCategory;
      }
    }
    var result = {};
    result.preview = preview;
    result.articles = articles;
    callback(null, result);
  })
}

function getCategories() {
  debug('getCategories');

  // Funktion is used for prototype @ Blog and for Blog Module
  if (this.categories) return this.categories;
  return module.exports.categories;
}

function createTable(cb) {
  debug('createTable');
  createString = 'CREATE TABLE blog (  id bigserial NOT NULL,  data json,  \
                  CONSTRAINT blog_pkey PRIMARY KEY (id) ) WITH (  OIDS=FALSE);'
  createView = "CREATE INDEX blog_id_idx ON blog USING btree (id);";
  pgMap.createTable('blog',createString,createView,cb)
}

function dropTable(cb) {
  debug('dropTable');
  pgMap.dropTable('blog',cb);
}

// Prototype Functions

// preview(edit,callback)
// edit: boolean, specifying wether generated HTML should contain edit links for articles or not
// result of preview is html code to display the blog.
Blog.prototype.preview = preview;

// setAndSave(user,data,callback)
// user: actual username for logging purposes
// data: json with values that has to be changed
// Function will change the given values and create for every field,
// where the value differes from representation in memory a log entry.
// at the end, the blog value is written in total
// This is may be relevant for concurrent save
// as there is no locking with version numbers yet.
Blog.prototype.setAndSave = setAndSave;

Blog.prototype.setReviewComment = setReviewComment;

// save
// just store the object in the database
Blog.prototype.save = pgMap.save;

// delete the object from the database
Blog.prototype.remove = pgMap.remove;

// Get Categories of the blog
// This can be the global defined, or the one from the blog itself
// Additional there can be some Categories for Edit Reasons
Blog.prototype.getCategories = getCategories;

// Define it on BlogModule level to (for no Blog Specified)
module.exports.getCategories = getCategories;

// Creation Functions

// Create a blog in memory with a given prototype
// create(proto)
// proto: (optional) JSON Data, to copy for the new object
//         the copy is a flat copy
module.exports.create= create;

// Create a blog in the database,
// createNewBlog(proto,callback)
// for parameter see create
// proto is not allowed to have an id, this is generated by the database
// and stored into the object
module.exports.createNewBlog = createNewBlog;

// Find Functions

// find(object,order,callback)
// object (optional) find Objects, that conform with all values in the object
// order (optional)  field to sort by
module.exports.find = find;

// find(id,callback)
// id find Objects with ID
module.exports.findById = findById;

// findOne(object,order,callback)
// same as find, but callback returns one object, if it exists
module.exports.findOne = findOne;

// Create Tables in Prostgres with all indices and views
module.exports.createTable = createTable;

// Delete table in Postgres
module.exports.dropTable = dropTable;
<|endoftext|>


<commit_before>#!/usr/bin/env node

// @flow
/* eslint-disable no-process-exit */
import importCwd from 'import-cwd'

const rootPackage = importCwd('./package.json')

const options = {
  file: 'tasks',
  ...rootPackage.start,
}

if (Array.isArray(options.require)) {
  options.require.forEach(require)
}

let tasks = options.preset ? importCwd(options.preset) : importCwd(`./${options.file}`)

const getAvailableTasksRunnersMessage = () => {
  return `Available task runners: "${Object.keys(tasks).join('", "')}"`
}

const taskName = process.argv[2]

if (typeof taskName === 'undefined') {
  console.log('Task runner name is required')
  console.log(getAvailableTasksRunnersMessage())
  process.exit(0)
}

const taskRunner = tasks[taskName]

if (typeof taskRunner === 'undefined') {
  console.error(`Unable to find task runner "${taskName}"`)
  console.error(getAvailableTasksRunnersMessage())
  process.exit(1)
}

const taskArgs = process.argv.slice(3)

taskRunner(...taskArgs)({ taskName }).catch(() => {
  process.exit(1)
})
<commit_msg>:wrench: @start/cli: minor tweak<commit_after>#!/usr/bin/env node

// @flow
/* eslint-disable no-process-exit */
import importCwd from 'import-cwd'

const rootPackage = importCwd('./package.json')

const options = {
  file: 'tasks',
  ...rootPackage.start,
}

if (Array.isArray(options.require)) {
  options.require.forEach(require)
}

let tasks = importCwd(options.preset ? options.preset : `./${options.file}`)

const getAvailableTasksRunnersMessage = () => {
  return `Available task runners: "${Object.keys(tasks).join('", "')}"`
}

const taskName = process.argv[2]

if (typeof taskName === 'undefined') {
  console.log('Task runner name is required')
  console.log(getAvailableTasksRunnersMessage())
  process.exit(0)
}

const taskRunner = tasks[taskName]

if (typeof taskRunner === 'undefined') {
  console.error(`Unable to find task runner "${taskName}"`)
  console.error(getAvailableTasksRunnersMessage())
  process.exit(1)
}

const taskArgs = process.argv.slice(3)

taskRunner(...taskArgs)({ taskName }).catch(() => {
  process.exit(1)
})
<|endoftext|>


<commit_before>export function Config(connection, app) {
	if(typeof connection === 'string') {
		connection = app.config.get('database.connections.' + connection)
	}

	if(connection.isNil) {
		return
	}

	const driver = connection.driver || null
	delete connection.driver

	const dialect = connection.dialect || null
	delete connection.dialect

	const pool = connection.pool || null
	delete connection.pool

	const useNullAsDefault = connection.useNullAsDefault || null
	delete connection.useNullAsDefault

	let config = { }

	if(!driver.isNil) {
		config.client = driver
	}

	if(!dialect.isNil) {
		config.dialect = dialect
	}

	if(!pool.isNil) {
		config.pool = pool
	}

	if(!useNullAsDefault.isNil) {
		config.useNullAsDefault = useNullAsDefault
	}

	if(config.client === 'pg' || config.client === 'postgres' || config.client === 'postgresql') {
		config = Object.assign({ }, config, connection)
	} else {
		config.connection = connection
	}

	config.seeds = {
		directory: './database/seeds'
	}

	config.migrations = {
		directory: './database/migrations'
	}

	return config
}
<commit_msg>Fixed bug in Config where it used paths for migrations/seeds relative to working dir and not app root<commit_after>export function Config(connection, app) {
	if(typeof connection === 'string') {
		connection = app.config.get('database.connections.' + connection)
	}

	if(connection.isNil) {
		return
	}

	const driver = connection.driver || null
	delete connection.driver

	const dialect = connection.dialect || null
	delete connection.dialect

	const pool = connection.pool || null
	delete connection.pool

	const useNullAsDefault = connection.useNullAsDefault || null
	delete connection.useNullAsDefault

	let config = { }

	if(!driver.isNil) {
		config.client = driver
	}

	if(!dialect.isNil) {
		config.dialect = dialect
	}

	if(!pool.isNil) {
		config.pool = pool
	}

	if(!useNullAsDefault.isNil) {
		config.useNullAsDefault = useNullAsDefault
	}

	if(config.client === 'pg' || config.client === 'postgres' || config.client === 'postgresql') {
		config = Object.assign({ }, config, connection)
	} else {
		config.connection = connection
	}

	config.seeds = {
		directory: app.paths.base('database', 'seeds')
	}

	config.migrations = {
		directory: app.paths.base('database', 'migrations')
	}

	return config
}
<|endoftext|>


<commit_before>process.on('uncaughtException', e => {
    e = e || {}
    const appRoot = new RegExp(path.join(__dirname, '../../'), 'g')

    if (e.message) {
        process.stderr.write('\u001b[131m[Error]\u001b[031m' + e.message + '\n\u001b[m\n')
    }
    if (e.stack) {
        process.stderr.write('\u001b[131m[Stack]\u001b[031m' + (e.stack.replace(appRoot, '')) + '\u001b[m\n')
    }
})

import fs from 'fs-extra'
import path from 'path'
import yargs from 'yargs'
import {BrowserWindow, Menu, app} from 'electron'

const parseCommandLine = () => {
    const parser = yargs
        .boolean('dev').describe('dev', 'Run development mode')
        .boolean('help').describe('help', 'Show command line help').alias('help', 'h')
        .boolean('version').describe('version', 'Show version').alias('version', 'v')

    const args = parser.parse(process.argv.slice(1))

    if (args.help) {
        parser.showHelp('error')
        process.exit(0);
    }
    if (args.version) {
        console.log(`Delir ${app.getVersion()}`);
        process.exit(0);
    }

    return {
        devMode: args['dev']
    }
}

const install = async () => {
    const userDir = app.getPath('appData')

    try {
        await fs.mkdirp(path.join(userDir, 'delir/plugins'))
    } catch (e) {
        throw e
    }
}

(async () => {
    const args = parseCommandLine()
    await install()

    if (args.devMode || process.env.DELIR_ENV === 'dev') {
        console.log('Run as develop mode')

        // install devtools
        const devtron = require('devtron')
        devtron.install()

        const {default: installExtension, REACT_DEVELOPER_TOOLS} = require('electron-devtools-installer')
        await installExtension(REACT_DEVELOPER_TOOLS)
    }

    app.on('window-all-closed', () => {
        app.quit()
    })

    const run = () => {
        const window = new BrowserWindow({
            // frame: false,
            titleBarStyle: 'hidden',
            // transparent: true,
            webPreferences: {
                webgl: true,
                experimentalFeatures: true,
                experimentalCanvasFeatures: true,
            },
        })

        window.loadURL(`file://${path.join(__dirname, '/../delir/index.html')}`)
        window.show()
        args.devMode && window.webContents.openDevTools()
    }

    app.isReady() ? run() : app.on('ready', run)
})().catch(e => console.log(e))
<commit_msg>Installing devtools only development<commit_after>process.on('uncaughtException', e => {
    e = e || {}
    const appRoot = new RegExp(path.join(__dirname, '../../'), 'g')

    if (e.message) {
        process.stderr.write('\u001b[131m[Error]\u001b[031m' + e.message + '\n\u001b[m\n')
    }
    if (e.stack) {
        process.stderr.write('\u001b[131m[Stack]\u001b[031m' + (e.stack.replace(appRoot, '')) + '\u001b[m\n')
    }
})

import fs from 'fs-extra'
import path from 'path'
import yargs from 'yargs'
import {BrowserWindow, Menu, app} from 'electron'

const parseCommandLine = () => {
    const parser = yargs
        .boolean('dev').describe('dev', 'Run development mode')
        .boolean('help').describe('help', 'Show command line help').alias('help', 'h')
        .boolean('version').describe('version', 'Show version').alias('version', 'v')

    const args = parser.parse(process.argv.slice(1))

    if (args.help) {
        parser.showHelp('error')
        process.exit(0);
    }
    if (args.version) {
        console.log(`Delir ${app.getVersion()}`);
        process.exit(0);
    }

    return {
        devMode: args['dev']
    }
}

const install = async () => {
    const userDir = app.getPath('appData')

    try {
        await fs.mkdirp(path.join(userDir, 'delir/plugins'))
    } catch (e) {
        throw e
    }
}

(async () => {
    const args = parseCommandLine()
    await install()

    if (process.env.DELIR_ENV === 'dev') {
        console.log('Run as develop mode')

        // install devtools
        const devtron = require('devtron')
        devtron.install()

        const {default: installExtension, REACT_DEVELOPER_TOOLS} = require('electron-devtools-installer')
        await installExtension(REACT_DEVELOPER_TOOLS)
    }

    app.on('window-all-closed', () => {
        app.quit()
    })

    const run = () => {
        const window = new BrowserWindow({
            // frame: false,
            titleBarStyle: 'hidden',
            // transparent: true,
            webPreferences: {
                webgl: true,
                experimentalFeatures: true,
                experimentalCanvasFeatures: true,
            },
        })

        window.loadURL(`file://${path.join(__dirname, '/../delir/index.html')}`)
        window.show()
        args.devMode && window.webContents.openDevTools()
    }

    app.isReady() ? run() : app.on('ready', run)
})().catch(e => console.log(e))
<|endoftext|>


<commit_before>// ******************************************
//		Import configurations
// ******************************************

var config				= require('./config.json');

// ******************************************
//		Install NodeJS Dependencies
// ******************************************

// Express
var express				= require('express');
// Serve-Static
var serveStatic			= require('serve-static');
// Body-Parser
var bodyParser			= require('body-parser');
// Multer
var multer				= require('multer')
// RethinkDB
var r					= require('rethinkdb');

// ******************************************
//		Initialize
// ******************************************

var table				= 'list';
var tableIndex			= 'createdAt';

var startExpress		= function() {
    app.listen(config.express.port);
	console.log('_____________________');
	console.log('HTTP and API server online')
    console.log('Listening on port '+config.express.port);
	console.log('_____________________');
}

var initialize 			= function(conn) {
	r.table(table).indexWait('createdAt').run(conn)
		.then(function(result) {
			console.log("DB OK, starting express...");
			console.log('_____________________');
			startExpress();
		})
		.error(function(error){
			console.log("The table doesn't exist.");
			console.log("Initializing table: "+table);
			r.tableCreate(table).run(conn)
				.finally(function(){
					console.log("Initializing index: "+tableIndex);
					r.table(table).indexCreate(tableIndex).run(conn)
						.finally(function(){
							console.log("DB Initialized, starting express...");
							console.log('_____________________');
							startExpress();
						});
				});
		});
};

r.connect(config.rethinkdb)
	.then(function(conn) {
		console.log('_____________________');
		console.log("Conection stablished");
		console.log("Checking DB...");
		r.dbList().run(conn)
			.then(function(dbList){
				if (dbList.indexOf(config.rethinkdb.db) > -1)
				{
					initialize(conn);
				} else {
					console.log("The DB doesn't exist.");
					console.log("Initializing DB "+config.rethinkdb.db);
					r.dbCreate(config.rethinkdb.db).run(conn)
						.then(initialize(conn))
				}
			})
	})
	.error(function(error){
		console.log("Could not open a connection to initialize the database "+config.rethinkdb.db);
		console.log(err.message);
		process.exit(1);
	});

// ******************************************
//		Basic Express Setup
// ******************************************

// Create the application
var app					= express();
// Create a connection to the database
app.use(createConnection);
// Data parsing
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
// Define main routes
app.route('/lista/list').get(list);
app.route('/lista/add').put(add);
app.route('/lista/remove').post(remove);
// Static files server
app.use(serveStatic('./public'));
// Close connection to the database
app.use(closeConnection);

// ******************************************
//		API
// ******************************************

// ------------------------------------------
//		Create a RethinkDB connection
//		save @ request.rdbConn
// ------------------------------------------

var createConnection 	= function(request, res, next) {
    r.connect(config.rethinkdb)
		.then(function(conn) {
            request.rdbConn = conn;
            next();
        })
		.error(handleError(res))
};

// ------------------------------------------
// 		Close the RethinkDB connection
// ------------------------------------------

var closeConnection		= function(request) {
    request.rdbConn.close();
}
// ------------------------------------------
//		Send back a 500 error
// ------------------------------------------

var handleError			= function(res) {
    return function(error){
		res.send(500,{error: error.message});
	}
}

// ------------------------------------------
//		Retrieve all elements
// ------------------------------------------

var list				= function(request, res, next) {
	console.log('_____________________');
	console.log('API - Sending all elements');
	console.log('_____________________');
    r.table(table).orderBy({index: "createdAt"}).run(request.rdbConn)
	.then( function(cursor) {
		return cursos.toArray();
	})
	.error(handleError(res))
	.finally(next);
}

// ------------------------------------------
//		Insert an element
// ------------------------------------------

var add					= function(request, res, next) {
	var element			= request.body;
	console.log('_____________________');
	console.log('API - Saving element');
	console.log(element);
	console.log('_____________________');
}

// ------------------------------------------
//		Delete an element
// ------------------------------------------

var	remove				= function (request, res, next) {
	var element			= request.body;
	console.log('_____________________');
	console.log('API - Deleting element');
	console.log(element);
	console.log('_____________________');
}<commit_msg>RESTful API<commit_after>// ******************************************
//		Import configurations
// ******************************************

var config				= require('./config.json');

// ******************************************
//		Install NodeJS Dependencies
// ******************************************

// Express
var express				= require('express');
// Serve-Static
var serveStatic			= require('serve-static');
// Body-Parser
var bodyParser			= require('body-parser');
// Multer
var multer				= require('multer')
// RethinkDB
var r					= require('rethinkdb');

// ******************************************
//		Initialize
// ******************************************

var table				= 'list';
var tableIndex			= 'createdAt';

var startExpress		= function() {
    app.listen(config.express.port);
	console.log('_____________________');
	console.log('HTTP and API server online')
    console.log('Listening on port '+config.express.port);
	console.log('_____________________');
}

var initialize 			= function(conn) {
	r.table(table).indexWait('createdAt').run(conn)
		.then(function(result) {
			console.log("DB OK, starting express...");
			console.log('_____________________');
			startExpress();
		})
		.error(function(error){
			console.log("The table doesn't exist.");
			console.log("Initializing table: "+table);
			r.tableCreate(table).run(conn)
				.finally(function(){
					console.log("Initializing index: "+tableIndex);
					r.table(table).indexCreate(tableIndex).run(conn)
						.finally(function(){
							console.log("DB Initialized, starting express...");
							console.log('_____________________');
							startExpress();
						});
				});
		});
};

r.connect(config.rethinkdb)
	.then(function(conn) {
		console.log('_____________________');
		console.log("Conection stablished");
		console.log("Checking DB...");
		r.dbList().run(conn)
			.then(function(dbList){
				if (dbList.indexOf(config.rethinkdb.db) > -1)
				{
					initialize(conn);
				} else {
					console.log("The DB doesn't exist.");
					console.log("Initializing DB "+config.rethinkdb.db);
					r.dbCreate(config.rethinkdb.db).run(conn)
						.then(initialize(conn))
				}
			})
	})
	.error(function(error){
		console.log("Could not open a connection to initialize the database "+config.rethinkdb.db);
		console.log(err.message);
		process.exit(1);
	});

// ******************************************
//		API
// ******************************************

// ------------------------------------------
//		Send back a 500 error
// ------------------------------------------

var handleError			= function(res) {
    return function(error){
		res.send(500,{error: error.message});
	}
}

// ------------------------------------------
//		Retrieve all elements
// ------------------------------------------

var list				= function(request, res, next) {
	console.log('_____________________');
	console.log('API - list/list');

	r.connect(config.rethinkdb)
		.then(function(conn) {
			r.table(table).run(conn)
				.then( function(data) {
					var query = data._responses[0].r;
					res.send(query);
					console.log('Done.');
					console.log('_____________________');
				})
				.error(handleError(res))
		});
}

// ------------------------------------------
//		Insert an element
// ------------------------------------------

var add					= function(request, res, next) {
	var element			= request.body;
	console.log('_____________________');
	console.log('API - list/add');
	console.log(element);

	r.connect(config.rethinkdb)
		.then(function(conn) {
			r.table(table).insert(element).run(conn)
				.then( function() {
					console.log('Done.');
					console.log('_____________________');
				})
				.error(handleError(res))
		});
}

// ------------------------------------------
//		Delete an element
// ------------------------------------------

var	empty				= function (request, res, next) {
	var element			= request.body;
	console.log('_____________________');
	console.log('API - list/empty');

	r.connect(config.rethinkdb)
		.then(function(conn) {
			r.table(table).delete({returnChanges: true}).run(conn)
				.then( function(changes) {
					console.log(changes);
					console.log('Done.');
					console.log('_____________________');
				})
				.error(handleError(res))
		});
}

// ******************************************
//		Basic Express Setup
// ******************************************

// Create the application
var app					= express();
// Data parsing
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
// Define main routes
app.route('/list/list').get(list);
app.route('/list/add').put(add);
app.route('/list/empty').post(empty);
// Static files server
app.use(serveStatic('./public'));<|endoftext|>


<commit_before>// Adapted by Giuseppe Futia from the node.js documentation

/*jslint node: true */

"use strict";

var server = require('net').createServer();

var port = 4001;

server.on('listening', function () {
    console.info('Server is listening on port', port);
});

server.on('connection', function (socket) {
    console.info('Server has a new connection');
    socket.end();
    server.close();
});

server.on('close', function () {
    console.info('Server in now closed');
});

server.on('error', function (err) {
    console.info('Error occurred:', err.message);
});

server.listen(port);
<commit_msg>tcp.js: correct typo<commit_after>// Adapted by Giuseppe Futia from the node.js documentation

/*jslint node: true */

"use strict";

var server = require('net').createServer();

var port = 4001;

server.on('listening', function () {
    console.info('Server is listening on port', port);
});

server.on('connection', function (socket) {
    console.info('Server has a new connection');
    socket.end();
    server.close();
});

server.on('close', function () {
    console.info('Server is now closed');
});

server.on('error', function (err) {
    console.info('Error occurred:', err.message);
});

server.listen(port);
<|endoftext|>


<commit_before>var jsdom = require('jsdom');
var Path = require('path');
var URL = require('url');
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var async = require('async');
var format = require('util').format;

var notemplate = module.exports = new EventEmitter();

var views = Object.create(null);

// keep that in memory
var jquery = fs.readFileSync(Path.join(Path.dirname(require.resolve('jquery-browser')), 'lib/jquery.js'));

function load(path, cb) {
	var view = views[path] || { path: path };
	fs.stat(path, function(err, result) {
		if (err) return cb(err);
		if (view.mtime && result.mtime <= view.mtime) {
			view.hit = true;
			return cb(null, view);
		}
		fs.readFile(view.path, function(err, str) {
			if (err) return cb(err, view);
			view.window = getWindow(str);
			view.mtime = result.mtime;
			view.hit = false;
			views[view.path] = view;
			return cb(null, view);
		});
	});
}

function getWindow(str) {
	// create window with jquery
	var window = jsdom.jsdom(str, null, {			// default DOM, but eventually will be level2.html
		features: {
			FetchExternalResources: false,				// loaded depending on script[notemplate] attribute
			ProcessExternalResources: false,			// same
			MutationEvents: false,								// not needed
			QuerySelector: false									// not needed, we use jquery's bundled sizzle instead of jsdom's one.
		},
		xhtml: true
	}).createWindow();
	window.console = console;
	window.run(jquery);
	jqueryPatches(window.jQuery);
	return window;
}

function loadScript(src, cb) {
	var url = URL.parse(src);
	if (url.hostname) return cb(format("express-notemplate error - cannot load remote script\n%s", src), null);
	var path = Path.join(notemplate.settings.public, url.pathname);
	path.exists(path, function(exists) {
		if (exists) fs.readFile(path, cb);
		else cb(format("express-notemplate error - cannot load local script\n%s", path));
	});
}

function outer($nodes) {
	var ret = '';
	$nodes.each(function() {
		ret += this.outerHTML;
	});
	return ret;
}

function jqueryPatches($) {
	// jQuery monkey-patch
	$.buildFragmentOrig = $.buildFragment;
	$.buildFragment = function(args, nodes, scripts) {
		var r = $.buildFragmentOrig(args, nodes, scripts);
		// or else script.contentText will be run, this is a security risk
		if (Array.isArray(scripts)) scripts.length = 0;
		return r;
	};
}

function merge(view, options, callback) {
	var window = view.window;
	var $ = window.$;
	var document = window.document;
	document.replaceChild(view.root.cloneNode(true), document.documentElement);
	// global listeners
	notemplate.emit('data', view, options);
	// listeners from scripts loaded inside view.window
	$(document).triggerHandler('data', data);
	// global listeners
	notemplate.emit('render', view, options);
	var output;
	if (options.fragment) output = outer($(options.fragment)); // output selected nodes
	else output = document.doctype.toString() + "\n" + document.outerHTML; // outputs doctype because of jsdom bug
	// global listeners can modify output (sync)
	var obj = { output : output };
	notemplate.emit('output', obj, options);
	callback(null, obj.output);
}

notemplate.__express = function(filename, options, callback) {
	load(filename, function(err, view) {
		if (err) return callback(err);
		// the first time the DOM is ready is an event
		var window = view.window;
		if (!view.hit) {
			notemplate.emit('ready', view, options);
			async.forEach(window.$('script'), function(script, done) {
				var att = script.attributes.notemplate;
				// default is notemplate="client"
				if (!att) return done();
				att = att.value;
				script.attributes.removeNamedItem('notemplate');
				// any other value is "client"
				if (att != "server" && att != "both") return done();
				var src = script.attributes.src;
				// html5 runs script content only when src is not set
				if (!src && script.textContent) window.run(script.textContent);
				if (att == "server") script.parentNode.remove
				if (!src) return done();
				loadScript(src.value, function(err, textContent) {
					if (err) done(err);
					else {
						window.run(textContent);
						done();
					}
				});
			}, function(err) {
				if (err) console.error(err); // errors are not fatal
				view.hit = true;
				view.root = window.document.documentElement;
				// all scripts have been loaded
				// now we can deal with data merging
				merge(view, options, callback);
			});
		} else merge(view, options, callback);
	});
};
<commit_msg>readFile return buffers, not strings.<commit_after>var jsdom = require('jsdom');
var Path = require('path');
var URL = require('url');
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var async = require('async');
var format = require('util').format;

var notemplate = module.exports = new EventEmitter();

var views = Object.create(null);

// keep that in memory
var jquery = fs.readFileSync(Path.join(Path.dirname(require.resolve('jquery-browser')), 'lib/jquery.js')).toString();

function load(path, cb) {
	var view = views[path] || { path: path };
	fs.stat(path, function(err, result) {
		if (err) return cb(err);
		if (view.mtime && result.mtime <= view.mtime) {
			view.hit = true;
			return cb(null, view);
		}
		fs.readFile(view.path, function(err, str) {
			if (err) return cb(err, view);
			view.window = getWindow(str);
			view.mtime = result.mtime;
			view.hit = false;
			views[view.path] = view;
			return cb(null, view);
		});
	});
}

function getWindow(str) {
	// create window with jquery
	var window = jsdom.jsdom(str, null, {			// default DOM, but eventually will be level2.html
		features: {
			FetchExternalResources: false,				// loaded depending on script[notemplate] attribute
			ProcessExternalResources: false,			// same
			MutationEvents: false,								// not needed
			QuerySelector: false									// not needed, we use jquery's bundled sizzle instead of jsdom's one.
		},
		xhtml: true
	}).createWindow();
	window.console = console;
	window.run(jquery);
	jqueryPatches(window.jQuery);
	return window;
}

function loadScript(src, cb) {
	var url = URL.parse(src);
	if (url.hostname) return cb(format("express-notemplate error - cannot load remote script\n%s", src), null);
	var path = Path.join(notemplate.settings.public, url.pathname);
	path.exists(path, function(exists) {
		if (exists) fs.readFile(path, cb);
		else cb(format("express-notemplate error - cannot load local script\n%s", path));
	});
}

function outer($nodes) {
	var ret = '';
	$nodes.each(function() {
		ret += this.outerHTML;
	});
	return ret;
}

function jqueryPatches($) {
	// jQuery monkey-patch
	$.buildFragmentOrig = $.buildFragment;
	$.buildFragment = function(args, nodes, scripts) {
		var r = $.buildFragmentOrig(args, nodes, scripts);
		// or else script.contentText will be run, this is a security risk
		if (Array.isArray(scripts)) scripts.length = 0;
		return r;
	};
}

function merge(view, options, callback) {
	var window = view.window;
	var $ = window.$;
	var document = window.document;
	document.replaceChild(view.root.cloneNode(true), document.documentElement);
	// global listeners
	notemplate.emit('data', view, options);
	// listeners from scripts loaded inside view.window
	$(document).triggerHandler('data', data);
	// global listeners
	notemplate.emit('render', view, options);
	var output;
	if (options.fragment) output = outer($(options.fragment)); // output selected nodes
	else output = document.doctype.toString() + "\n" + document.outerHTML; // outputs doctype because of jsdom bug
	// global listeners can modify output (sync)
	var obj = { output : output };
	notemplate.emit('output', obj, options);
	callback(null, obj.output);
}

notemplate.__express = function(filename, options, callback) {
	load(filename, function(err, view) {
		if (err) return callback(err);
		// the first time the DOM is ready is an event
		var window = view.window;
		if (!view.hit) {
			notemplate.emit('ready', view, options);
			async.forEach(window.$('script'), function(script, done) {
				var att = script.attributes.notemplate;
				// default is notemplate="client"
				if (!att) return done();
				att = att.value;
				script.attributes.removeNamedItem('notemplate');
				// any other value is "client"
				if (att != "server" && att != "both") return done();
				var src = script.attributes.src;
				// html5 runs script content only when src is not set
				if (!src && script.textContent) window.run(script.textContent);
				if (att == "server") script.parentNode.remove
				if (!src) return done();
				loadScript(src.value, function(err, textContent) {
					if (err) done(err);
					else {
						window.run(textContent.toString());
						done();
					}
				});
			}, function(err) {
				if (err) console.error(err); // errors are not fatal
				view.hit = true;
				view.root = window.document.documentElement;
				// all scripts have been loaded
				// now we can deal with data merging
				merge(view, options, callback);
			});
		} else merge(view, options, callback);
	});
};
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget('indico.palettepicker', {

        options: {
            availableColors: [],
            onSelect: null,
            numColumns: 5,
            selectedColor: null,
            qtipConstructor: null
        },

        _create: function() {
            var self = this;
            var element = this.element;
            var paletteTable = $('<table>', {'class': 'palette-picker'});
            var availableColors = this.options.availableColors;
            var tr = this._createTableRow();

            self._paletteTable = paletteTable;

            $.each(availableColors, function(index, color) {
                var td = $('<td>', {
                    'class': 'palette-color',
                    'data': {color: color}
                });

                var colorBox = $('<div>', {
                    'css': {'background': '#' + color.background},
                    'class': 'background-box'
                });

                colorBox.append($('<div>', {
                    'css': {'background': '#' + color.text},
                    'class': 'text-box'
                }));

                td.append(colorBox);
                tr.append(td);

                if ((index + 1) % self.options.numColumns == 0) {
                    paletteTable.append(tr);
                    tr = self._createTableRow();
                }
            });

            if (tr.children().length) {
                paletteTable.append(tr);
            }

            paletteTable.on('click', '.palette-color', function() {
                var $this = $(this),
                    color = $this.data('color'),
                    backgroundColor = '#' + color.background,
                    textColor = '#' + color.text,
                    styleObject = element[0].style;

                self.options.selectedColor = color;
                self._updateSelection();

                styleObject.setProperty('color', textColor, 'important');
                styleObject.setProperty('background', backgroundColor, 'important');

                if (self.options.onSelect) {
                    self.options.onSelect.call(element, backgroundColor, textColor);
                }

                element.qtip('hide');
            });

            var qtipOptions = {
                prerender: false,
                overwrite: false,
                style: {
                    classes: 'palette-picker-qtip'
                },
                position: {
                    my: 'top center',
                    at: 'bottom center',
                    target: element,
                    adjust: {
                        mouse: false,
                        scroll: false
                    }
                },
                content: {
                    text: paletteTable
                },
                show: {
                    event: 'click',
                    solo: true
                },
                hide: {
                    event: 'unfocus'
                },
                events: {
                    show: self._updateSelection.bind(self)
                }
            }
            if (self.options.qtipConstructor) {
                self.options.qtipConstructor(element, qtipOptions);
            } else {
                element.qtip(qtipOptions);
            }
        },

        _createTableRow: function() {
            return $('<tr>', {'height': 13});
        },

        _updateSelection: function() {
            var selectedColor = this.options.selectedColor;
            this._paletteTable.find('.palette-color').each(function() {
                var $this = $(this);
                var color = $this.data('color');
                if (selectedColor != null
                        && color.background == selectedColor.background
                        && color.text == selectedColor.text) {
                    $this.addClass('selected');
                } else {
                    $this.removeClass('selected');
                }
            });
        }
    });
})(jQuery);
<commit_msg>Fix palette-picker preventing display of tooltips<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget('indico.palettepicker', {

        options: {
            availableColors: [],
            onSelect: null,
            numColumns: 5,
            selectedColor: null,
            qtipConstructor: null
        },

        _create: function() {
            var self = this;
            var element = this.element;
            var paletteTable = $('<table>', {'class': 'palette-picker'});
            var availableColors = this.options.availableColors;
            var tr = this._createTableRow();

            self._paletteTable = paletteTable;

            $.each(availableColors, function(index, color) {
                var td = $('<td>', {
                    'class': 'palette-color',
                    'data': {color: color}
                });

                var colorBox = $('<div>', {
                    'css': {'background': '#' + color.background},
                    'class': 'background-box'
                });

                colorBox.append($('<div>', {
                    'css': {'background': '#' + color.text},
                    'class': 'text-box'
                }));

                td.append(colorBox);
                tr.append(td);

                if ((index + 1) % self.options.numColumns == 0) {
                    paletteTable.append(tr);
                    tr = self._createTableRow();
                }
            });

            if (tr.children().length) {
                paletteTable.append(tr);
            }

            paletteTable.on('click', '.palette-color', function() {
                var $this = $(this),
                    color = $this.data('color'),
                    backgroundColor = '#' + color.background,
                    textColor = '#' + color.text,
                    styleObject = element[0].style;

                self.options.selectedColor = color;
                self._updateSelection();

                styleObject.setProperty('color', textColor, 'important');
                styleObject.setProperty('background', backgroundColor, 'important');

                if (self.options.onSelect) {
                    self.options.onSelect.call(element, backgroundColor, textColor);
                }

                element.qtip('hide');
            });

            var qtipOptions = {
                prerender: false,
                overwrite: false,
                suppress: false,
                style: {
                    classes: 'palette-picker-qtip'
                },
                position: {
                    my: 'top center',
                    at: 'bottom center',
                    target: element,
                    adjust: {
                        mouse: false,
                        scroll: false
                    }
                },
                content: {
                    text: paletteTable
                },
                show: {
                    event: 'click',
                    solo: true
                },
                hide: {
                    event: 'unfocus'
                },
                events: {
                    show: self._updateSelection.bind(self)
                }
            }
            if (self.options.qtipConstructor) {
                self.options.qtipConstructor(element, qtipOptions);
            } else {
                element.qtip(qtipOptions);
            }
        },

        _createTableRow: function() {
            return $('<tr>', {'height': 13});
        },

        _updateSelection: function() {
            var selectedColor = this.options.selectedColor;
            this._paletteTable.find('.palette-color').each(function() {
                var $this = $(this);
                var color = $this.data('color');
                if (selectedColor != null
                        && color.background == selectedColor.background
                        && color.text == selectedColor.text) {
                    $this.addClass('selected');
                } else {
                    $this.removeClass('selected');
                }
            });
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>'use strict';

/**
* Returns a RawGit URL.
*
* @private
* @param {Object} opts - function options
* @param {string} opts.protocol - HTTP protocol
* @param {string} opts.hostname - RawGit hostname
* @param {string} opts.slug - repository slug
* @param {string} opts.file - filepath
* @param {boolean} opts.cdn - boolean indicating whether a resource should be delivered via a CDN
* @returns {string} RawGit URL
*
* @example
* var out = url({
*     'protocol': 'https',
*     'hostname': 'rawgit.com',
*     'slug': 'stdlib-js/stdlib/develop',
*     'file': 'README.md',
*     'cdn': true
* });
* // returns 'https://cdn.rawgit.com/stdlib-js/stdlib/develop/README.md'
*/
function url( opts ) {
	var str = '';
	str += opts.protocol+'://';
	if ( opts.cdn ) {
		str += 'cdn.';
	}
	str += opts.hostname+'/';
	str += opts.slug+'/';
	str += opts.file;
	return str;
} // end FUNCTION url()

// EXPORTS //

module.exports = url;
<commit_msg>Update type annotation<commit_after>'use strict';

/**
* Returns a RawGit URL.
*
* @private
* @param {Options} opts - function options
* @param {string} opts.protocol - HTTP protocol
* @param {string} opts.hostname - RawGit hostname
* @param {string} opts.slug - repository slug
* @param {string} opts.file - filepath
* @param {boolean} opts.cdn - boolean indicating whether a resource should be delivered via a CDN
* @returns {string} RawGit URL
*
* @example
* var out = url({
*     'protocol': 'https',
*     'hostname': 'rawgit.com',
*     'slug': 'stdlib-js/stdlib/develop',
*     'file': 'README.md',
*     'cdn': true
* });
* // returns 'https://cdn.rawgit.com/stdlib-js/stdlib/develop/README.md'
*/
function url( opts ) {
	var str = '';
	str += opts.protocol+'://';
	if ( opts.cdn ) {
		str += 'cdn.';
	}
	str += opts.hostname+'/';
	str += opts.slug+'/';
	str += opts.file;
	return str;
} // end FUNCTION url()

// EXPORTS //

module.exports = url;
<|endoftext|>