<commit_before>/**
 *
 * @license
 * Copyright (C) 2016 Joseph Roque
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Joseph Roque
 * @file NavBar.js
 * @module NavBar
 * @description Navigation and search bar for the top of the app, to allow the user to
 *              search from anywhere.
 * @flow
 *
 */
'use strict';

// React Native imports
import React from 'react';
import {
  Dimensions,
  LayoutAnimation,
  Platform,
  StyleSheet,
  TouchableOpacity,
  TextInput,
  View,
} from 'react-native';

// Imports
const Constants = require('../Constants');
const Ionicons = require('react-native-vector-icons/Ionicons');
const Preferences = require('../util/Preferences');
const StatusBarUtils = require('../util/StatusBarUtils');

// Get dimensions of the screen
const { width } = Dimensions.get('window');

// Type definition for component props.
type Props = {
  onSearch: () => any,
  onBack: ?() => any,
  onDrawerToggle: ?() => any,
};

// Type definition for component state.
type State = {
  showBackButton: ?boolean,
  refresh: ?boolean,
};

class NavBar extends React.Component {
  state: State;

  /**
   * Properties which the parent component should make available to this
   * component.
   */
  static propTypes = {
    onBack: React.PropTypes.func,
    onDrawerToggle: React.PropTypes.func,
    onSearch: React.PropTypes.func.isRequired,
  };

  /**
   * Pass props and declares initial state.
   *
   * @param {Props} props properties passed from container to this component.
   */
  constructor(props: Props) {
    super(props);
    this.state = {
      showBackButton: false,
      refresh: false,
    };

    // Explicitly binding 'this' to certain methods
    (this:any).getRefresh = this.getRefresh.bind(this);
  };

  /**
   * Configures the app to animate the next layout change, then updates the
   * state.
   *
   * @param {State} state the new state for the component.
   */
  setState(state: State) {
    if (state.showBackButton) {
      setTimeout(() => {
        LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
        super.setState(state);
      }, 50);
    } else {
      super.setState(state);
    }
  };

  /**
   * Returns the current state of the refresh variable, to allow it to be
   * flipped to re-render the view.
   *
   * @return {boolean} the value of {this.state.refresh}.
   */
  getRefresh(): boolean {
    if (this.state.refresh == null) {
      return false;
    }

    return this.state.refresh;
  };

  /**
   * Clears the search field and requests a back navigation.
   */
  _onBack(): void {
    this.refs.SearchInput.setNativeProps({text: ''});
    if (this.props.onBack) {
      this.props.onBack();
    }
  };

  /**
   * Prompts the app to search, so long as there is any text to search with.
   *
   * @param {string} text params to search for.
   */
  _onSearch(text: string): void {
    if (text && text.length > 0) {
      this.props.onSearch(text);
    }
  };

  /**
   * Renders a text input field for searching.
   *
   * @return {ReactElement} the hierarchy of views to render.
   */
  render(): ReactElement {
    // Get current language for translations
    let Translations = null;
    if (Preferences.getSelectedLanguage() === 'fr') {
      Translations = require('../../assets/static/js/Translations.fr.js');
    } else {
      Translations = require('../../assets/static/js/Translations.en.js');
    }

    // Setting position of search bar and back button dependent on if back button is showing.
    let searchBarLeft = (this.state.showBackButton)
        ? 50
        : 10;
    let searchBarWidth = (this.state.showBackButton)
        ? width - 60
        : width - 20;
    let backButtonLeft = (this.state.showBackButton)
        ? 0
        : -60;

    return (
      <View style={_styles.container}>
        <TouchableOpacity onPress={this._onBack.bind(this)} style={{height: 40, alignItems: 'center', left: backButtonLeft}}>
          <Ionicons
              color={'white'}
              name={'ios-arrow-back'}
              size={24}
              style={{marginLeft: 20, marginRight: 20, marginTop: 8}} />
        </TouchableOpacity>
        <View style={[_styles.innerContainer, _styles.searchContainer, {width: searchBarWidth, left: searchBarLeft}]}>
          <Ionicons
              onPress={() => this.refs.SearchInput.focus()}
              name={'ios-search'}
              size={24}
              color={'white'}
              style={{marginLeft: 10, marginRight: 10}} />
          <TextInput
              ref='SearchInput'
              style={{flex: 1, height: 40, color: Constants.Colors.polarGrey}}
              onChangeText={this._onSearch.bind(this)}
              autoCorrect={false}
              placeholder={Translations['search_placeholder']}
              placeholderTextColor={Constants.Colors.lightGrey} />
        </View>
      </View>
    )
  };
};

// Private styles for component
const _styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
    height: 60,
    marginTop: StatusBarUtils.getStatusBarPadding(Platform),
  },
  innerContainer: {
    alignItems: 'center',
    flexDirection: 'row',
    borderRadius: 10,
    backgroundColor: 'rgba(0, 0, 0, 0.2)',
    margin: 10,
    marginLeft: 0,
  },
  searchContainer: {
    position: 'absolute',
    top: 0,
  },
});

// Expose component to app
module.exports = NavBar;
<commit_msg>Fix broken animation on back press<commit_after>/**
 *
 * @license
 * Copyright (C) 2016 Joseph Roque
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Joseph Roque
 * @file NavBar.js
 * @module NavBar
 * @description Navigation and search bar for the top of the app, to allow the user to
 *              search from anywhere.
 * @flow
 *
 */
'use strict';

// React Native imports
import React from 'react';
import {
  Dimensions,
  LayoutAnimation,
  Platform,
  StyleSheet,
  TouchableOpacity,
  TextInput,
  View,
} from 'react-native';

// Imports
const Constants = require('../Constants');
const Ionicons = require('react-native-vector-icons/Ionicons');
const Preferences = require('../util/Preferences');
const StatusBarUtils = require('../util/StatusBarUtils');

// Get dimensions of the screen
const { width } = Dimensions.get('window');

// Type definition for component props.
type Props = {
  onSearch: () => any,
  onBack: ?() => any,
  onDrawerToggle: ?() => any,
};

// Type definition for component state.
type State = {
  showBackButton: ?boolean,
  refresh: ?boolean,
};

class NavBar extends React.Component {
  state: State;

  /**
   * Properties which the parent component should make available to this
   * component.
   */
  static propTypes = {
    onBack: React.PropTypes.func,
    onDrawerToggle: React.PropTypes.func,
    onSearch: React.PropTypes.func.isRequired,
  };

  /**
   * Pass props and declares initial state.
   *
   * @param {Props} props properties passed from container to this component.
   */
  constructor(props: Props) {
    super(props);
    this.state = {
      showBackButton: false,
      refresh: false,
    };

    // Explicitly binding 'this' to certain methods
    (this:any).getRefresh = this.getRefresh.bind(this);
  };

  /**
   * Configures the app to animate the next layout change, then updates the
   * state.
   *
   * @param {State} state the new state for the component.
   */
  setState(state: State) {
    if (state.showBackButton != null) {
      setTimeout(() => {
        LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
        super.setState(state);
      }, 50);
    } else {
      super.setState(state);
    }
  };

  /**
   * Returns the current state of the refresh variable, to allow it to be
   * flipped to re-render the view.
   *
   * @return {boolean} the value of {this.state.refresh}.
   */
  getRefresh(): boolean {
    if (this.state.refresh == null) {
      return false;
    }

    return this.state.refresh;
  };

  /**
   * Clears the search field and requests a back navigation.
   */
  _onBack(): void {
    this.refs.SearchInput.setNativeProps({text: ''});
    if (this.props.onBack) {
      this.props.onBack();
    }
  };

  /**
   * Prompts the app to search, so long as there is any text to search with.
   *
   * @param {string} text params to search for.
   */
  _onSearch(text: string): void {
    if (text && text.length > 0) {
      this.props.onSearch(text);
    }
  };

  /**
   * Renders a text input field for searching.
   *
   * @return {ReactElement} the hierarchy of views to render.
   */
  render(): ReactElement {
    // Get current language for translations
    let Translations = null;
    if (Preferences.getSelectedLanguage() === 'fr') {
      Translations = require('../../assets/static/js/Translations.fr.js');
    } else {
      Translations = require('../../assets/static/js/Translations.en.js');
    }

    // Setting position of search bar and back button dependent on if back button is showing.
    let searchBarLeft = (this.state.showBackButton)
        ? 50
        : 10;
    let searchBarWidth = (this.state.showBackButton)
        ? width - 60
        : width - 20;
    let backButtonLeft = (this.state.showBackButton)
        ? 0
        : -60;

    return (
      <View style={_styles.container}>
        <TouchableOpacity onPress={this._onBack.bind(this)} style={{height: 40, alignItems: 'center', left: backButtonLeft}}>
          <Ionicons
              color={'white'}
              name={'ios-arrow-back'}
              size={24}
              style={{marginLeft: 20, marginRight: 20, marginTop: 8}} />
        </TouchableOpacity>
        <View style={[_styles.innerContainer, _styles.searchContainer, {width: searchBarWidth, left: searchBarLeft}]}>
          <Ionicons
              onPress={() => this.refs.SearchInput.focus()}
              name={'ios-search'}
              size={24}
              color={'white'}
              style={{marginLeft: 10, marginRight: 10}} />
          <TextInput
              ref='SearchInput'
              style={{flex: 1, height: 40, color: Constants.Colors.polarGrey}}
              onChangeText={this._onSearch.bind(this)}
              autoCorrect={false}
              placeholder={Translations['search_placeholder']}
              placeholderTextColor={Constants.Colors.lightGrey} />
        </View>
      </View>
    )
  };
};

// Private styles for component
const _styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
    height: 60,
    marginTop: StatusBarUtils.getStatusBarPadding(Platform),
  },
  innerContainer: {
    alignItems: 'center',
    flexDirection: 'row',
    borderRadius: 10,
    backgroundColor: 'rgba(0, 0, 0, 0.2)',
    margin: 10,
    marginLeft: 0,
  },
  searchContainer: {
    position: 'absolute',
    top: 0,
  },
});

// Expose component to app
module.exports = NavBar;
<|endoftext|>


<commit_before>var express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  Book = mongoose.model('Book');

module.exports = function(app) {
  app.use('/api', router);
};

router.use(function(req, res, next) {
  console.log('Something is happening');
  next();
});

router.get('/', function(req, res) {
  res.json({
    message: 'Api Page!'
  });
});

router.route('/books')
  .post(function(req, res) {
    var book = new Book();
    book.title = req.body.title;
    book.isbn = req.body.isbn;
    book.author = req.body.author;

    book.save(function(err) {
      if (err)
        res.send(err);
      res.json({
        message: 'Book created!'
      });
    });
  });
<commit_msg>book ids working<commit_after>var express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  Book = mongoose.model('Book');

module.exports = function(app) {
  app.use('/api', router);
};

router.use(function(req, res, next) {
  console.log('Something is happening');
  next();
});

router.get('/', function(req, res) {
  res.json({
    message: 'Api Page!'
  });
});

router.route('/books')
  .post(function(req, res) {
    var book = new Book();
    book.title = req.body.title;
    book.isbn = req.body.isbn;
    book.author = req.body.author;

    book.save(function(err) {
      if (err)
        res.send(err);
      res.json({
        message: 'Book created!'
      });
    });
  })
  .get(function(req, res) {
    Book.find(function(err, books) {
      if (err)
        res.send(err);
      res.json(books);
    });
  });

router.route('/books/:book_id')
  .get(function(req, res) {
    Book.findById(req.params.book_id, function(err, book) {
      if (err)
        res.send(err);
      res.json(book);
    });
  });
<|endoftext|>


<commit_before>$(function() {
    function PSUControlViewModel(parameters) {
        var self = this;

        self.settingsViewModel = parameters[0]
        self.loginState = parameters[1];
        self.settings = undefined;
        self.hasGPIO = ko.observable(undefined);
        self.isPSUOn = ko.observable(undefined);
        self.psu_indicator = $("#psucontrol_indicator");

        self.onBeforeBinding = function() {
            self.settings = self.settingsViewModel.settings;
        };

        self.onDataUpdaterPluginMessage = function(plugin, data) {
            if (plugin != "psucontrol") {
                return;
            }

            self.hasGPIO(data.hasGPIO);
            self.isPSUOn(data.isPSUOn);

            if (self.isPSUOn()) {
                self.psu_indicator.removeClass("off").addClass("on");
            } else {
                self.psu_indicator.removeClass("on").addClass("off");
            }

        };

        self.togglePSU = function() {
            if (self.isPSUOn()) {
                if (self.settings.plugins.psucontrol.enablePowerOffWarningDialog()) {
                    showConfirmationDialog({
                        message: "You are about to turn off the PSU.",
                        onproceed: function() {
                            self.turnPSUOff();
                        }
                    });
                } else {
                    self.turnPSUOff();
                }
            } else {
                self.turnPSUOn();
            }
        };

        self.turnPSUOn = function() {
            $.ajax({
                url: API_BASEURL + "plugin/psucontrol",
                type: "POST",
                dataType: "json",
                data: JSON.stringify({
                    command: "turnPSUOn"
                }),
                contentType: "application/json; charset=UTF-8"
            })
        };

    	self.turnPSUOff = function() {
            $.ajax({
                url: API_BASEURL + "plugin/psucontrol",
                type: "POST",
                dataType: "json",
                data: JSON.stringify({
                    command: "turnPSUOff"
                }),
                contentType: "application/json; charset=UTF-8"
            })
        };
    }

    ADDITIONAL_VIEWMODELS.push([
        PSUControlViewModel,
        ["settingsViewModel", "loginStateViewModel"],
        ["#navbar_plugin_psucontrol", "#settings_plugin_psucontrol"]
    ]);
});
<commit_msg>Moved indicator color update from onDataUpdaterPLuginMessage to a subscriber. Query PSU state on load<commit_after>$(function() {
    function PSUControlViewModel(parameters) {
        var self = this;

        self.settingsViewModel = parameters[0]
        self.loginState = parameters[1];
        self.settings = undefined;
        self.hasGPIO = ko.observable(undefined);
        self.isPSUOn = ko.observable(undefined);
        self.psu_indicator = $("#psucontrol_indicator");

        self.onBeforeBinding = function() {
            self.settings = self.settingsViewModel.settings;
        };

        self.onStartup = function () {
            self.isPSUOn.subscribe(function() {
                if (self.isPSUOn()) {
                    self.psu_indicator.removeClass("off").addClass("on");
                } else {
                    self.psu_indicator.removeClass("on").addClass("off");
                }
            });

            $.ajax({
                url: API_BASEURL + "plugin/psucontrol",
                type: "POST",
                dataType: "json",
                data: JSON.stringify({
                    command: "getPSUState"
                }),
                contentType: "application/json; charset=UTF-8"
            }).done(function(data) {
                self.isPSUOn(data.isPSUOn);
            });
        }

        self.onDataUpdaterPluginMessage = function(plugin, data) {
            if (plugin != "psucontrol") {
                return;
            }

            self.hasGPIO(data.hasGPIO);
            self.isPSUOn(data.isPSUOn);
        };

        self.togglePSU = function() {
            if (self.isPSUOn()) {
                if (self.settings.plugins.psucontrol.enablePowerOffWarningDialog()) {
                    showConfirmationDialog({
                        message: "You are about to turn off the PSU.",
                        onproceed: function() {
                            self.turnPSUOff();
                        }
                    });
                } else {
                    self.turnPSUOff();
                }
            } else {
                self.turnPSUOn();
            }
        };

        self.turnPSUOn = function() {
            $.ajax({
                url: API_BASEURL + "plugin/psucontrol",
                type: "POST",
                dataType: "json",
                data: JSON.stringify({
                    command: "turnPSUOn"
                }),
                contentType: "application/json; charset=UTF-8"
            })
        };

    	self.turnPSUOff = function() {
            $.ajax({
                url: API_BASEURL + "plugin/psucontrol",
                type: "POST",
                dataType: "json",
                data: JSON.stringify({
                    command: "turnPSUOff"
                }),
                contentType: "application/json; charset=UTF-8"
            })
        };
    }

    ADDITIONAL_VIEWMODELS.push([
        PSUControlViewModel,
        ["settingsViewModel", "loginStateViewModel"],
        ["#navbar_plugin_psucontrol", "#settings_plugin_psucontrol"]
    ]);
});
<|endoftext|>


<commit_before>var http = require('http'),
    https = require("https"),
    request = require("request"),
    mongoose = require("mongoose"),
    querystring = require('querystring'),
    _ = require('underscore'),
    Photo = require('../models/instagram'),
    Log = require('../models/log'),
    config = require('../config'),
    io = require('socket.io'),
    pluralize = require('pluralize'),
    instagram_api = require('../services/instagram_api');

mongoose.connect(config.db.mongo_url);

exports.get_maps = function(req, res) {
    if(req.query['hub.challenge'])
        return res.send(req.query['hub.challenge']);
    res.render('instagram/maps');
}

exports.post_maps = function(req, res) {

    // request.body is a JSON already parsed
    req.body.forEach(function(notificationOjb) {

        https.get({
            host: 'api.instagram.com',
            path: '/v1/' + pluralize(notificationOjb.object) + '/' + notificationOjb.object_id + '/media/recent' +
                '?' + querystring.stringify({
                    client_id: config.instagram.client_id,
                    count: 1
                }),
        }, function(res) {

            var raw = "";

            res.on('data', function(chunk) {
                raw += chunk;
            });

            res.on('end', function() {

                var response = JSON.parse(raw);
                if (response['data'].length > 0) {

                    for (i in response.data) {
                        var instagram_notif = new Photo({
                            src: response.data[i].images.standard_resolution.url,
                            url: response.data[i].images.standard_resolution.url,
                            width: 640,
                            height: 480,
                            type: "instagram",
                            media: {
                              notification: notificationOjb,
                              data: response.data[i]
                            }
                        });
                        global.io.sockets.emit('photo_map', instagram_notif);

                    } //endfor
                }
            });

        });
    });
    res.send(200);
}

exports.get_subscriptions = function(req, res) {

    instagram_api.get_subscriptions(function(err, httpResp, body) {
        res.render('instagram/subscriptions', {
            status: {
                code: httpResp.statusCode,
                message: httpResp.statusMessage,
            },
            meta: body.meta,
            subscriptions: httpResp.statusCode == 200 ? body.data : []
        });
    });
}

exports.post_subscriptions = function(req, res) {

    instagram_api.post_subscription(req.body, function(error) {

        if (error)
            return res.send(500, error);

        instagram_api.get_subscriptions(function(err, httpResp, body) {
            res.render('instagram/subscriptions', {
                status: {
                    code: httpResp.statusCode,
                    message: httpResp.statusMessage,
                },
                meta: body.meta,
                subscriptions: httpResp.statusCode == 200 ? body.data : []
            });
        });
    });
}

exports.get_subscribe = function(req, res) {
    global.io.sockets.emit('test', "test");
    res.send(req.query['hub.challenge']);
};

exports.post_subscribe = function(request, response) {

    var log = new Log({
        data: request.body
    })
    log.save(function(err) {
        if (err) console.log(err);
    })

    // request.body is a JSON already parsed
    request.body.forEach(function(notificationOjb) {
        // Every notification object contains the id of the geography
        // that has been updated, and the photo can be obtained from
        // that geography

        https.get({
            host: 'api.instagram.com',
            path: '/v1/' + pluralize(notificationOjb.object) + '/' + notificationOjb.object_id + '/media/recent' +
                '?' + querystring.stringify({
                    client_id: config.instagram.client_id,
                    count: 1
                }),
        }, function(res) {

            var raw = "";

            res.on('data', function(chunk) {
                raw += chunk;
            });

            // When the whole body has arrived, it has to be a valid JSON, with data,
            // and the first photo of the date must to have a location attribute.
            // If so, the photo is emitted through the websocket
            res.on('end', function() {

                var response = JSON.parse(raw);
                if (response['data'].length > 0) {

                    for (i in response.data) {

                        var instagram_notif = new Photo({
                            src: response.data[i].images.standard_resolution.url,
                            url: response.data[i].images.standard_resolution.url,
                            width: 640,
                            height: 480,
                            type: "instagram",
                            media: {
                              notification: notificationOjb,
                              data: response.data[i]
                            }
                        });

                        //Previne duplicatas
                        Photo.find({
                            url: response.data[i].images.standard_resolution.url
                        }, function(err, documents) {
                            if (err) res.send(500);
                            if (documents.length == 0) {
                                instagram_notif.save(function(err) {
                                    if (err) {
                                        console.log(err);
                                    } else {
                                        global.io.sockets.emit('photo', instagram_notif);
                                        console.log(instagram_notif);
                                    }
                                });

                            }
                        });

                    } //endfor
                }
            });

        });
    });
    response.send(200);
};

exports.get_index = function(req, res) {
    Photo.find({}, function(err, documents) {
        if (err) res.send(500);
        res.render('instagram/index', {
            photos: documents
            , layout: false
        });
    });
};

exports.get_photos = function(req, res) {
    Photo.find({}, function(err, documents) {
        if (err) res.send(500);

        res.send(documents);
    });
};
<commit_msg>mudanda objeto de fotos<commit_after>var http = require('http'),
    https = require("https"),
    request = require("request"),
    mongoose = require("mongoose"),
    querystring = require('querystring'),
    _ = require('underscore'),
    Photo = require('../models/photo'),
    Log = require('../models/log'),
    config = require('../config'),
    io = require('socket.io'),
    pluralize = require('pluralize'),
    instagram_api = require('../services/instagram_api');

mongoose.connect(config.db.mongo_url);

exports.get_maps = function(req, res) {
    if(req.query['hub.challenge'])
        return res.send(req.query['hub.challenge']);
    res.render('instagram/maps');
}

exports.post_maps = function(req, res) {

    // request.body is a JSON already parsed
    req.body.forEach(function(notificationOjb) {

        https.get({
            host: 'api.instagram.com',
            path: '/v1/' + pluralize(notificationOjb.object) + '/' + notificationOjb.object_id + '/media/recent' +
                '?' + querystring.stringify({
                    client_id: config.instagram.client_id,
                    count: 1
                }),
        }, function(res) {

            var raw = "";

            res.on('data', function(chunk) {
                raw += chunk;
            });

            res.on('end', function() {

                var response = JSON.parse(raw);
                if (response['data'].length > 0) {

                    for (i in response.data) {
                        var instagram_notif = new Photo({
                            src: response.data[i].images.standard_resolution.url,
                            url: response.data[i].images.standard_resolution.url,
                            width: 640,
                            height: 480,
                            type: "instagram",
                            media: {
                              notification: notificationOjb,
                              data: response.data[i]
                            }
                        });
                        global.io.sockets.emit('photo_map', instagram_notif);

                    } //endfor
                }
            });

        });
    });
    res.send(200);
}

exports.get_subscriptions = function(req, res) {

    instagram_api.get_subscriptions(function(err, httpResp, body) {
        res.render('instagram/subscriptions', {
            status: {
                code: httpResp.statusCode,
                message: httpResp.statusMessage,
            },
            meta: body.meta,
            subscriptions: httpResp.statusCode == 200 ? body.data : []
        });
    });
}

exports.post_subscriptions = function(req, res) {

    instagram_api.post_subscription(req.body, function(error) {

        if (error)
            return res.send(500, error);

        instagram_api.get_subscriptions(function(err, httpResp, body) {
            res.render('instagram/subscriptions', {
                status: {
                    code: httpResp.statusCode,
                    message: httpResp.statusMessage,
                },
                meta: body.meta,
                subscriptions: httpResp.statusCode == 200 ? body.data : []
            });
        });
    });
}

exports.get_subscribe = function(req, res) {
    global.io.sockets.emit('test', "test");
    res.send(req.query['hub.challenge']);
};

exports.post_subscribe = function(request, response) {

    var log = new Log({
        data: request.body
    })
    log.save(function(err) {
        if (err) console.log(err);
    })

    // request.body is a JSON already parsed
    request.body.forEach(function(notificationOjb) {
        // Every notification object contains the id of the geography
        // that has been updated, and the photo can be obtained from
        // that geography

        https.get({
            host: 'api.instagram.com',
            path: '/v1/' + pluralize(notificationOjb.object) + '/' + notificationOjb.object_id + '/media/recent' +
                '?' + querystring.stringify({
                    client_id: config.instagram.client_id,
                    count: 1
                }),
        }, function(res) {

            var raw = "";

            res.on('data', function(chunk) {
                raw += chunk;
            });

            // When the whole body has arrived, it has to be a valid JSON, with data,
            // and the first photo of the date must to have a location attribute.
            // If so, the photo is emitted through the websocket
            res.on('end', function() {

                var response = JSON.parse(raw);
                if (response['data'].length > 0) {

                    for (i in response.data) {

                        var instagram_notif = new Photo({
                            src: response.data[i].images.standard_resolution.url,
                            url: response.data[i].images.standard_resolution.url,
                            width: 640,
                            height: 480,
                            type: "instagram",
                            media: {
                              notification: notificationOjb,
                              data: response.data[i]
                            }
                        });

                        //Previne duplicatas
                        Photo.find({
                            url: response.data[i].images.standard_resolution.url
                        }, function(err, documents) {
                            if (err) res.send(500);
                            if (documents.length == 0) {
                                instagram_notif.save(function(err) {
                                    if (err) {
                                        console.log(err);
                                    } else {
                                        global.io.sockets.emit('photo', instagram_notif);
                                        console.log(instagram_notif);
                                    }
                                });

                            }
                        });

                    } //endfor
                }
            });

        });
    });
    response.send(200);
};

exports.get_index = function(req, res) {
    Photo.find({}, function(err, documents) {
        if (err) res.send(500);
        res.render('instagram/index', {
            photos: documents
            , layout: false
        });
    });
};

exports.get_photos = function(req, res) {
    Photo.find({}, function(err, documents) {
        if (err) res.send(500);

        res.send(documents);
    });
};
<|endoftext|>


<commit_before>/**
 * Author: Zeta Ret, Ivo Yankulovski
 * Zeta Ret XeltoSS ASTConstructor
 * Generates ASTConstructorInstance of type function
 * Version: 1.00
 * Date: 2019
**/
function ASTConstructor(key,data,datahandler){
	var ASTConstructorInstance=function ASTConstructorInstance(){};
	ASTConstructorInstance.constructor=arguments.callee;
	ASTConstructorInstance.key=key;
	ASTConstructorInstance.data=data;
	ASTConstructorInstance.datahandler=datahandler;
	ASTConstructorInstance.toString=function toString(){return this.datahandler?this.datahandler(this.key,this.data):this.data.toString()};
	return ASTConstructorInstance;
}<commit_msg>Update ASTConstructor.js<commit_after>/**
 * Author: Zeta Ret, Ivo Yankulovski
 * Zeta Ret XeltoSS ASTConstructor
 * Generates ASTConstructorInstance of type function
 * Version: 1.00
 * Date: 2018
**/
function ASTConstructor(key,data,datahandler){
	var ASTConstructorInstance=function ASTConstructorInstance(){};
	ASTConstructorInstance.constructor=arguments.callee;
	ASTConstructorInstance.key=key;
	ASTConstructorInstance.data=data;
	ASTConstructorInstance.datahandler=datahandler;
	ASTConstructorInstance.toString=function toString(){return this.datahandler?this.datahandler(this.key,this.data):this.data.toString()};
	return ASTConstructorInstance;
}
<|endoftext|>


<commit_before>angular.module('ot.view.branchLinks', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branchLinks', {
            url: '/branch/{branchId}/links',
            templateUrl: 'app/view/view.branchLinks.tpl.html',
            controller: 'BranchLinksCtrl'
        });
    })
    .controller('BranchLinksCtrl', function ($location, $scope, $stateParams, $window, ot, otGraphqlService) {
        const branchId = $stateParams.branchId;
        const view = ot.view();

        const parameter = $location.hash();
        let initialDirection = 'USING';
        if (parameter === 'USED_BY') {
            initialDirection = 'USED_BY';
        }

        const context = {
            // using or usedBy, depending on the direction we want to follow
            direction: initialDirection,
            // the chart, not initialized at first
            chart: undefined
        };
        $scope.context = context;

        // Loading indicator
        $scope.loadingData = false;

        // Changing the direction of the dependencies
        $scope.changeDirection = () => {
            if (context.direction === 'USING') {
                context.direction = 'USED_BY';
            } else {
                context.direction = 'USING';
            }
            $location.hash(context.direction);
            refreshGraph();
        };

        // Refreshes the chart
        const refreshGraph = () => {
            if (context.chart) {
                context.chart.showLoading();
            }
            $scope.loadingData = true;
            loadData().then(raw => {
                try {
                    // View setup
                    if (!$scope.branch) {
                        const branch = raw.branches[0];
                        view.title = '';
                        view.breadcrumbs = ot.branchBreadcrumbs(branch);
                        view.commands = [
                            ot.viewCloseCommand('/branch/' + branch.id)
                        ];
                        $scope.branch = branch;
                    }
                    // Graph data preparation
                    const data = transformData(raw, context.direction);
                    // Graph setup
                    const chart = getOrCreateChart();
                    const options = createOptionWithData(data);
                    chart.clear();
                    chart.setOption(options, true);
                } finally {
                    $scope.loadingData = false;
                    if (context.chart) {
                        context.chart.hideLoading();
                    }
                }
            });
        };

        // Creates the chart option with some data
        const createOptionWithData = (data) => {
            return {
                series: [
                    {
                        type: 'tree',
                        data: [data],
                        top: '1%',
                        left: '20%',
                        bottom: '1%',
                        right: '20%',
                        symbolSize: (value) => {
                            if (value === 'edge') {
                                return 3;
                            } else {
                                return 25;
                            }
                        },
                        label: {
                            position: 'top',
                            verticalAlign: 'middle',
                            align: 'center',
                            fontSize: 12,
                            rich: {
                                buildName: {
                                    padding: [0, 0, 0, 8]
                                }
                            }
                        },
                        leaves: {
                            label: {
                                position: 'top',
                                verticalAlign: 'middle',
                                align: 'center'
                            }
                        },
                        emphasis: {
                            focus: 'ancestor'
                        },
                        expandAndCollapse: false,
                        animationDuration: 550,
                        animationDurationUpdate: 750
                    }
                ]
            };
        };

        // Gets the chart or creates it
        const getOrCreateChart = () => {
            if (context.chart) {
                return context.chart;
            }
            context.chart = createChart();
            return context.chart;
        };

        // Creates & inits the chart
        const createChart = () => {
            const graph = document.getElementById('graph');
            const chart = echarts.init(graph);
            // Event handling
            initChartEventHandling(chart);
            // OK
            return chart;
        };

        // Event handling on the chart
        const initChartEventHandling = (chart) => {
            chart.on('dblclick', (params) => {
                if (params.value && params.value.links && params.value.links._page) {
                    $window.open(params.value.links._page, "_blank");
                }
            });
        };

        // Transforming the raw data into a graph
        const transformData = (raw, direction) => {
            const branch = raw.branches[0];
            // TODO Case when there is no build
            const build = branch.builds[0];
            return transformGraphIntoNode(build.graph, direction, 0);
        };

        // Transforming a `BranchLinksNode` into a chart node
        const transformGraphIntoNode = (graph, direction, depth) => {
            // Initial node
            const node = {
                name: graph.branch.name
                // No value initially
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // Project name as a line
            formatterLines.push(graph.branch.project.name);
            // Display name in case of a build
            if (graph.build) {
                // Display name is the build name unless there is a release property attached to the build
                let displayName = graph.build.name;
                node.value = graph.build.id;
                if (graph.build.releaseProperty && graph.build.releaseProperty.value && graph.build.releaseProperty.value.name) {
                    displayName = graph.build.releaseProperty.value.name;
                }
                // Promotions
                let promotionsFormat = '';
                if (graph.build && graph.build.promotionRuns && graph.build.promotionRuns.length > 0) {
                    const run = graph.build.promotionRuns[graph.build.promotionRuns.length - 1];
                    const promotion = run.promotionLevel.name;
                    const image = run.promotionLevel.links._image;
                    if (image) {
                        node.label.rich[promotion] = {
                            backgroundColor: {
                                image: image
                            },
                            height: 16,
                            weight: 16
                        };
                        promotionsFormat += `{${promotion}|}`;
                    }
                }
                // Build line
                formatterLines.push(`${promotionsFormat}{buildName|${displayName}}`);
            }
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Edges
            node.children = graph.edges.map(edge => transformEdge(edge, direction, depth));
            // OK
            return node;
        };

        // Edge transformation
        const transformEdge = (edge, direction, depth) => {
            // Direction of the link as the name
            let name;
            if (direction === 'USING') {
                name = '>>> using >>>';
            } else {
                name = '<<< used by <<<';
            }
            // Initial node
            const node = {
                name: name,
                value: 'edge'
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // TODO Decorations on the edge
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Linked node as a child
            node.children = [
                transformGraphIntoNode(edge.linkedTo, direction, depth + 1)
            ];
            // OK
            return node;
        };

        // Loading the raw data
        const loadData = () => {
            return otGraphqlService.pageGraphQLCall(query, {
                branchId: branchId,
                direction: context.direction
            });
        };

        // Query recursive building

        const buildNodeQuery = (levels) => {
            if (levels > 0) {
                return `
                    ...nodeContent
                    edges {
                      direction
                      decorations {
                        ...decorationContent
                      }
                      linkedTo {
                        ${ buildNodeQuery(levels - 1) }
                      }
                    }
                `;
            } else {
                return `
                    ...nodeContent
                `;
            }
        };

        const buildQuery = (levels) => {
            return `
                query BranchBuildGraph(
                  $branchId: Int!,
                  $direction: BranchLinksDirection!
                ) {
                    branches(id: $branchId) {
                      id
                      name
                      project {
                        id
                        name
                      }
                      builds(count: 1) {
                        name
                        graph(direction: $direction) {
                          ${ buildNodeQuery(levels) }
                        }
                      }
                    }
                }

                fragment decorationContent on BranchLinksDecoration {
                  feature {
                    id
                  }
                  id
                  text
                  description
                  icon
                  url
                }

                fragment nodeContent on BranchLinksNode {
                  branch {
                    id
                    name
                    links {
                      _page
                    }
                    project {
                      id
                      name
                      links {
                        _page
                      }
                    }
                  }
                  build {
                    id
                    name
                    links {
                      _page
                    }
                    promotionRuns(lastPerLevel: true) {
                      promotionLevel {
                        name
                        links {
                          _image
                        }
                      }
                    }
                  }
                }
            `;
        };

        const query = buildQuery(10);

        // Loading the data on load
        refreshGraph();
    })
;<commit_msg>#857 Navigation to the branch or build<commit_after>angular.module('ot.view.branchLinks', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branchLinks', {
            url: '/branch/{branchId}/links',
            templateUrl: 'app/view/view.branchLinks.tpl.html',
            controller: 'BranchLinksCtrl'
        });
    })
    .controller('BranchLinksCtrl', function ($location, $scope, $stateParams, $window, ot, otGraphqlService) {
        const branchId = $stateParams.branchId;
        const view = ot.view();

        const parameter = $location.hash();
        let initialDirection = 'USING';
        if (parameter === 'USED_BY') {
            initialDirection = 'USED_BY';
        }

        const context = {
            // using or usedBy, depending on the direction we want to follow
            direction: initialDirection,
            // the chart, not initialized at first
            chart: undefined
        };
        $scope.context = context;

        // Loading indicator
        $scope.loadingData = false;

        // Changing the direction of the dependencies
        $scope.changeDirection = () => {
            if (context.direction === 'USING') {
                context.direction = 'USED_BY';
            } else {
                context.direction = 'USING';
            }
            $location.hash(context.direction);
            refreshGraph();
        };

        // Refreshes the chart
        const refreshGraph = () => {
            if (context.chart) {
                context.chart.showLoading();
            }
            $scope.loadingData = true;
            loadData().then(raw => {
                try {
                    // View setup
                    if (!$scope.branch) {
                        const branch = raw.branches[0];
                        view.title = '';
                        view.breadcrumbs = ot.branchBreadcrumbs(branch);
                        view.commands = [
                            ot.viewCloseCommand('/branch/' + branch.id)
                        ];
                        $scope.branch = branch;
                    }
                    // Graph data preparation
                    const data = transformData(raw, context.direction);
                    // Graph setup
                    const chart = getOrCreateChart();
                    const options = createOptionWithData(data);
                    chart.clear();
                    chart.setOption(options, true);
                } finally {
                    $scope.loadingData = false;
                    if (context.chart) {
                        context.chart.hideLoading();
                    }
                }
            });
        };

        // Creates the chart option with some data
        const createOptionWithData = (data) => {
            return {
                series: [
                    {
                        type: 'tree',
                        data: [data],
                        top: '1%',
                        left: '20%',
                        bottom: '1%',
                        right: '20%',
                        symbolSize: (value) => {
                            if (value && value.type === 'edge') {
                                return 3;
                            } else {
                                return 25;
                            }
                        },
                        label: {
                            position: 'top',
                            verticalAlign: 'middle',
                            align: 'center',
                            fontSize: 12,
                            rich: {
                                buildName: {
                                    padding: [0, 0, 0, 8]
                                }
                            }
                        },
                        leaves: {
                            label: {
                                position: 'top',
                                verticalAlign: 'middle',
                                align: 'center'
                            }
                        },
                        emphasis: {
                            focus: 'ancestor'
                        },
                        expandAndCollapse: false,
                        animationDuration: 550,
                        animationDurationUpdate: 750
                    }
                ]
            };
        };

        // Gets the chart or creates it
        const getOrCreateChart = () => {
            if (context.chart) {
                return context.chart;
            }
            context.chart = createChart();
            return context.chart;
        };

        // Creates & inits the chart
        const createChart = () => {
            const graph = document.getElementById('graph');
            const chart = echarts.init(graph);
            // Event handling
            initChartEventHandling(chart);
            // OK
            return chart;
        };

        // Event handling on the chart
        const initChartEventHandling = (chart) => {
            chart.on('dblclick', (params) => {
                console.log("params.value = ", params.value);
                if (params.value && params.value.page) {
                    $window.open(params.value.page, "_blank");
                }
            });
        };

        // Transforming the raw data into a graph
        const transformData = (raw, direction) => {
            const branch = raw.branches[0];
            // TODO Case when there is no build
            const build = branch.builds[0];
            return transformGraphIntoNode(build.graph, direction, 0);
        };

        // Transforming a `BranchLinksNode` into a chart node
        const transformGraphIntoNode = (graph, direction, depth) => {
            // Value is the build ID or the branch ID
            let value;
            if (graph.build) {
                value = {
                    type: 'build',
                    page: graph.build.links._page
                };
            } else {
                value = {
                    type: 'branch',
                    page: graph.branch.links._page
                };
            }
            // Initial node
            const node = {
                name: graph.branch.name,
                value: value
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // Project name as a line
            formatterLines.push(graph.branch.project.name);
            // Display name in case of a build
            if (graph.build) {
                // Display name is the build name unless there is a release property attached to the build
                let displayName = graph.build.name;
                if (graph.build.releaseProperty && graph.build.releaseProperty.value && graph.build.releaseProperty.value.name) {
                    displayName = graph.build.releaseProperty.value.name;
                }
                // Promotions
                let promotionsFormat = '';
                if (graph.build && graph.build.promotionRuns && graph.build.promotionRuns.length > 0) {
                    const run = graph.build.promotionRuns[graph.build.promotionRuns.length - 1];
                    const promotion = run.promotionLevel.name;
                    const image = run.promotionLevel.links._image;
                    if (image) {
                        node.label.rich[promotion] = {
                            backgroundColor: {
                                image: image
                            },
                            height: 16,
                            weight: 16
                        };
                        promotionsFormat += `{${promotion}|}`;
                    }
                }
                // Build line
                formatterLines.push(`${promotionsFormat}{buildName|${displayName}}`);
            }
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Edges
            node.children = graph.edges.map(edge => transformEdge(edge, direction, depth));
            // OK
            return node;
        };

        // Edge transformation
        const transformEdge = (edge, direction, depth) => {
            // Direction of the link as the name
            let name;
            if (direction === 'USING') {
                name = '>>> using >>>';
            } else {
                name = '<<< used by <<<';
            }
            // Initial node
            const node = {
                name: name,
                value: {
                    type: 'edge'
                }
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // TODO Decorations on the edge
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Linked node as a child
            node.children = [
                transformGraphIntoNode(edge.linkedTo, direction, depth + 1)
            ];
            // OK
            return node;
        };

        // Loading the raw data
        const loadData = () => {
            return otGraphqlService.pageGraphQLCall(query, {
                branchId: branchId,
                direction: context.direction
            });
        };

        // Query recursive building

        const buildNodeQuery = (levels) => {
            if (levels > 0) {
                return `
                    ...nodeContent
                    edges {
                      direction
                      decorations {
                        ...decorationContent
                      }
                      linkedTo {
                        ${ buildNodeQuery(levels - 1) }
                      }
                    }
                `;
            } else {
                return `
                    ...nodeContent
                `;
            }
        };

        const buildQuery = (levels) => {
            return `
                query BranchBuildGraph(
                  $branchId: Int!,
                  $direction: BranchLinksDirection!
                ) {
                    branches(id: $branchId) {
                      id
                      name
                      project {
                        id
                        name
                      }
                      builds(count: 1) {
                        name
                        graph(direction: $direction) {
                          ${ buildNodeQuery(levels) }
                        }
                      }
                    }
                }

                fragment decorationContent on BranchLinksDecoration {
                  feature {
                    id
                  }
                  id
                  text
                  description
                  icon
                  url
                }

                fragment nodeContent on BranchLinksNode {
                  branch {
                    id
                    name
                    links {
                      _page
                    }
                    project {
                      id
                      name
                      links {
                        _page
                      }
                    }
                  }
                  build {
                    id
                    name
                    links {
                      _page
                    }
                    promotionRuns(lastPerLevel: true) {
                      promotionLevel {
                        name
                        links {
                          _image
                        }
                      }
                    }
                  }
                }
            `;
        };

        const query = buildQuery(10);

        // Loading the data on load
        refreshGraph();
    })
;<|endoftext|>


<commit_before>angular.module('ot.view.branchLinks', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branchLinks', {
            url: '/branch/{branchId}/links',
            templateUrl: 'app/view/view.branchLinks.tpl.html',
            controller: 'BranchLinksCtrl'
        });
    })
    .controller('BranchLinksCtrl', function ($location, $scope, $stateParams, $window, ot, otGraphqlService) {
        const branchId = $stateParams.branchId;
        const view = ot.view();

        const parameter = $location.hash();
        let initialDirection = 'USING';
        if (parameter === 'USED_BY') {
            initialDirection = 'USED_BY';
        }

        const context = {
            // using or usedBy, depending on the direction we want to follow
            direction: initialDirection,
            // the chart, not initialized at first
            chart: undefined
        };
        $scope.context = context;

        // Loading indicator
        $scope.loadingData = false;

        // Changing the direction of the dependencies
        $scope.changeDirection = () => {
            if (context.direction === 'USING') {
                context.direction = 'USED_BY';
            } else {
                context.direction = 'USING';
            }
            $location.hash(context.direction);
            refreshGraph();
        };

        // Refreshes the chart
        const refreshGraph = () => {
            if (context.chart) {
                context.chart.showLoading();
            }
            $scope.loadingData = true;
            loadData().then(raw => {
                try {
                    // View setup
                    if (!$scope.branch) {
                        const branch = raw.branches[0];
                        view.title = '';
                        view.breadcrumbs = ot.branchBreadcrumbs(branch);
                        view.commands = [
                            ot.viewCloseCommand('/branch/' + branch.id)
                        ];
                        $scope.branch = branch;
                    }
                    // Graph data preparation
                    const data = transformData(raw, context.direction);
                    // Graph setup
                    const chart = getOrCreateChart();
                    const options = createOptionWithData(data);
                    chart.clear();
                    chart.setOption(options, true);
                } finally {
                    $scope.loadingData = false;
                    if (context.chart) {
                        context.chart.hideLoading();
                    }
                }
            });
        };

        // Creates the chart option with some data
        const createOptionWithData = (data) => {
            return {
                series: [
                    {
                        type: 'tree',
                        data: [data],
                        top: '1%',
                        left: '20%',
                        bottom: '1%',
                        right: '20%',
                        symbolSize: (value) => {
                            if (value && value.type === 'edge') {
                                return 6;
                            } else {
                                return 25;
                            }
                        },
                        label: {
                            position: 'top',
                            verticalAlign: 'middle',
                            align: 'center',
                            fontSize: 12,
                            rich: {
                                decorationText: {
                                    padding: [0, 0, 0, 8]
                                }
                            }
                        },
                        leaves: {
                            label: {
                                position: 'top',
                                verticalAlign: 'middle',
                                align: 'center'
                            }
                        },
                        emphasis: {
                            focus: 'ancestor'
                        },
                        expandAndCollapse: false,
                        animationDuration: 550,
                        animationDurationUpdate: 750
                    }
                ]
            };
        };

        // Gets the chart or creates it
        const getOrCreateChart = () => {
            if (context.chart) {
                return context.chart;
            }
            context.chart = createChart();
            return context.chart;
        };

        // Creates & inits the chart
        const createChart = () => {
            const graph = document.getElementById('graph');
            const chart = echarts.init(graph);
            // Event handling
            initChartEventHandling(chart);
            // OK
            return chart;
        };

        // Event handling on the chart
        const initChartEventHandling = (chart) => {
            chart.on('dblclick', (params) => {
                console.log("params.value = ", params.value);
                if (params.value && params.value.page) {
                    $window.open(params.value.page, "_blank");
                }
            });
        };

        // Transforming the raw data into a graph
        const transformData = (raw, direction) => {
            const branch = raw.branches[0];
            // TODO Case when there is no build
            const build = branch.builds[0];
            return transformGraphIntoNode(build.graph, direction, 0);
        };

        // Transforming a `BranchLinksNode` into a chart node
        const transformGraphIntoNode = (graph, direction, depth) => {
            // Value is the build ID or the branch ID
            let value;
            if (graph.build) {
                value = {
                    type: 'build',
                    page: graph.build.links._page
                };
            } else {
                value = {
                    type: 'branch',
                    page: graph.branch.links._page
                };
            }
            // Initial node
            const node = {
                name: graph.branch.name,
                value: value
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // Project name as a line
            formatterLines.push(graph.branch.project.name);
            // Display name in case of a build
            if (graph.build) {
                // Display name is the build name unless there is a release property attached to the build
                let displayName = graph.build.name;
                if (graph.build.releaseProperty && graph.build.releaseProperty.value && graph.build.releaseProperty.value.name) {
                    displayName = graph.build.releaseProperty.value.name;
                }
                // Promotions
                let promotionsFormat = '';
                if (graph.build && graph.build.promotionRuns && graph.build.promotionRuns.length > 0) {
                    const run = graph.build.promotionRuns[graph.build.promotionRuns.length - 1];
                    const promotion = run.promotionLevel.name;
                    const image = run.promotionLevel.links._image;
                    if (image) {
                        node.label.rich[promotion] = {
                            backgroundColor: {
                                image: image
                            },
                            height: 16,
                            weight: 16
                        };
                        promotionsFormat += `{${promotion}|}`;
                    }
                }
                // Build line
                formatterLines.push(`${promotionsFormat}{buildName|${displayName}}`);
            }
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Edges
            node.children = graph.edges.map(edge => transformEdge(edge, direction, depth));
            // OK
            return node;
        };

        // Edge transformation
        const transformEdge = (edge, direction, depth) => {
            // Direction of the link as the name
            let name;
            if (direction === 'USING') {
                name = '>>> using >>>';
            } else {
                name = '<<< used by <<<';
            }
            // Initial node
            const node = {
                name: name,
                value: {
                    type: 'edge'
                }
            };

            // Decoration label
            node.label = {
                rich: {}
            };
            const formatterLines = edge.decorations.map(decoration => getDecorationFormatterForLabel(decoration, node.label.rich)).filter(line => line);
            node.label.formatter = formatterLines.join('\n');

            // TODO Decoration tooltip

            // Linked node as a child
            node.children = [
                transformGraphIntoNode(edge.linkedTo, direction, depth + 1)
            ];
            // OK
            return node;
        };

        const getDecorationFormatterForLabel = (decoration, classes) => {
            if (decoration.label === 'NONE') {
                return '';
            } else {
                let line = '';
                if ((decoration.label === 'ICON' || decoration.label === 'ALL') && decoration.icon) {
                    const className = `${decoration.feature.id}_${decoration.id}_${decoration.icon}`;
                    const iconUrl = `/extension/${decoration.feature.id}/graph/${decoration.id}/${decoration.icon}.png`;
                    classes[className] = {
                        backgroundColor: {
                            image: iconUrl
                        },
                        height: 16,
                        weight: 16
                    };
                    line += `{${className}|}`;
                }
                if ((decoration.label === 'TEXT' || decoration.label === 'ALL') && decoration.text) {
                    line += `{decorationText|${decoration.text}}`;
                }
                return line;
            }
        };

        // Loading the raw data
        const loadData = () => {
            return otGraphqlService.pageGraphQLCall(query, {
                branchId: branchId,
                direction: context.direction
            });
        };

        // Query recursive building

        const buildNodeQuery = (levels) => {
            if (levels > 0) {
                return `
                    ...nodeContent
                    edges {
                      direction
                      decorations {
                        ...decorationContent
                      }
                      linkedTo {
                        ${ buildNodeQuery(levels - 1) }
                      }
                    }
                `;
            } else {
                return `
                    ...nodeContent
                `;
            }
        };

        const buildQuery = (levels) => {
            return `
                query BranchBuildGraph(
                  $branchId: Int!,
                  $direction: BranchLinksDirection!
                ) {
                    branches(id: $branchId) {
                      id
                      name
                      links {
                        _page
                      }
                      project {
                        id
                        name
                        links {
                          _page
                        }
                      }
                      builds(count: 1) {
                        name
                        graph(direction: $direction) {
                          ${ buildNodeQuery(levels) }
                        }
                      }
                    }
                }

                fragment decorationContent on BranchLinksDecoration {
                  feature {
                    id
                  }
                  id
                  text
                  description
                  icon
                  url
                  label
                }

                fragment nodeContent on BranchLinksNode {
                  branch {
                    id
                    name
                    links {
                      _page
                    }
                    project {
                      id
                      name
                      links {
                        _page
                      }
                    }
                  }
                  build {
                    id
                    name
                    links {
                      _page
                    }
                    promotionRuns(lastPerLevel: true) {
                      promotionLevel {
                        name
                        links {
                          _image
                        }
                      }
                    }
                  }
                }
            `;
        };

        const query = buildQuery(10);

        // Loading the data on load
        refreshGraph();
    })
;<commit_msg>#857 Decoration tooltips<commit_after>angular.module('ot.view.branchLinks', [
    'ui.router',
    'ot.service.core',
    'ot.service.structure',
    'ot.service.graphql'
])
    .config(function ($stateProvider) {
        $stateProvider.state('branchLinks', {
            url: '/branch/{branchId}/links',
            templateUrl: 'app/view/view.branchLinks.tpl.html',
            controller: 'BranchLinksCtrl'
        });
    })
    .controller('BranchLinksCtrl', function ($location, $scope, $stateParams, $window, ot, otGraphqlService) {
        const branchId = $stateParams.branchId;
        const view = ot.view();

        const parameter = $location.hash();
        let initialDirection = 'USING';
        if (parameter === 'USED_BY') {
            initialDirection = 'USED_BY';
        }

        const context = {
            // using or usedBy, depending on the direction we want to follow
            direction: initialDirection,
            // the chart, not initialized at first
            chart: undefined
        };
        $scope.context = context;

        // Loading indicator
        $scope.loadingData = false;

        // Changing the direction of the dependencies
        $scope.changeDirection = () => {
            if (context.direction === 'USING') {
                context.direction = 'USED_BY';
            } else {
                context.direction = 'USING';
            }
            $location.hash(context.direction);
            refreshGraph();
        };

        // Refreshes the chart
        const refreshGraph = () => {
            if (context.chart) {
                context.chart.showLoading();
            }
            $scope.loadingData = true;
            loadData().then(raw => {
                try {
                    // View setup
                    if (!$scope.branch) {
                        const branch = raw.branches[0];
                        view.title = '';
                        view.breadcrumbs = ot.branchBreadcrumbs(branch);
                        view.commands = [
                            ot.viewCloseCommand('/branch/' + branch.id)
                        ];
                        $scope.branch = branch;
                    }
                    // Graph data preparation
                    const data = transformData(raw, context.direction);
                    // Graph setup
                    const chart = getOrCreateChart();
                    const options = createOptionWithData(data);
                    chart.clear();
                    chart.setOption(options, true);
                } finally {
                    $scope.loadingData = false;
                    if (context.chart) {
                        context.chart.hideLoading();
                    }
                }
            });
        };

        // Creates the chart option with some data
        const createOptionWithData = (data) => {
            return {
                tooltip: {
                    trigger: 'item',
                    triggerOn: 'click',
                    show: false // Managed at data node level
                },
                series: [
                    {
                        type: 'tree',
                        data: [data],
                        top: '1%',
                        left: '20%',
                        bottom: '1%',
                        right: '20%',
                        symbolSize: (value) => {
                            if (value && value.type === 'edge') {
                                return 6;
                            } else {
                                return 25;
                            }
                        },
                        label: {
                            position: 'top',
                            verticalAlign: 'middle',
                            align: 'center',
                            fontSize: 12,
                            rich: {
                                decorationText: {
                                    padding: [0, 0, 0, 8]
                                }
                            }
                        },
                        leaves: {
                            label: {
                                position: 'top',
                                verticalAlign: 'middle',
                                align: 'center'
                            }
                        },
                        emphasis: {
                            focus: 'ancestor'
                        },
                        expandAndCollapse: false,
                        animationDuration: 550,
                        animationDurationUpdate: 750
                    }
                ]
            };
        };

        // Gets the chart or creates it
        const getOrCreateChart = () => {
            if (context.chart) {
                return context.chart;
            }
            context.chart = createChart();
            return context.chart;
        };

        // Creates & inits the chart
        const createChart = () => {
            const graph = document.getElementById('graph');
            const chart = echarts.init(graph);
            // Event handling
            initChartEventHandling(chart);
            // OK
            return chart;
        };

        // Event handling on the chart
        const initChartEventHandling = (chart) => {
            chart.on('dblclick', (params) => {
                console.log("params.value = ", params.value);
                if (params.value && params.value.page) {
                    $window.open(params.value.page, "_blank");
                }
            });
        };

        // Transforming the raw data into a graph
        const transformData = (raw, direction) => {
            const branch = raw.branches[0];
            // TODO Case when there is no build
            const build = branch.builds[0];
            return transformGraphIntoNode(build.graph, direction, 0);
        };

        // Transforming a `BranchLinksNode` into a chart node
        const transformGraphIntoNode = (graph, direction, depth) => {
            // Value is the build ID or the branch ID
            let value;
            if (graph.build) {
                value = {
                    type: 'build',
                    page: graph.build.links._page
                };
            } else {
                value = {
                    type: 'branch',
                    page: graph.branch.links._page
                };
            }
            // Initial node
            const node = {
                name: graph.branch.name,
                value: value
            };
            // Label
            node.label = {
                rich: {}
            };
            // Format lines
            const formatterLines = [];
            // Project name as a line
            formatterLines.push(graph.branch.project.name);
            // Display name in case of a build
            if (graph.build) {
                // Display name is the build name unless there is a release property attached to the build
                let displayName = graph.build.name;
                if (graph.build.releaseProperty && graph.build.releaseProperty.value && graph.build.releaseProperty.value.name) {
                    displayName = graph.build.releaseProperty.value.name;
                }
                // Promotions
                let promotionsFormat = '';
                if (graph.build && graph.build.promotionRuns && graph.build.promotionRuns.length > 0) {
                    const run = graph.build.promotionRuns[graph.build.promotionRuns.length - 1];
                    const promotion = run.promotionLevel.name;
                    const image = run.promotionLevel.links._image;
                    if (image) {
                        node.label.rich[promotion] = {
                            backgroundColor: {
                                image: image
                            },
                            height: 16,
                            weight: 16
                        };
                        promotionsFormat += `{${promotion}|}`;
                    }
                }
                // Build line
                formatterLines.push(`${promotionsFormat}{buildName|${displayName}}`);
            }
            // Label formatter
            node.label.formatter = formatterLines.join('\n');
            // Edges
            node.children = graph.edges.map(edge => transformEdge(edge, direction, depth));
            // OK
            return node;
        };

        // Edge transformation
        const transformEdge = (edge, direction, depth) => {
            // Direction of the link as the name
            let name;
            if (direction === 'USING') {
                name = '>>> using >>>';
            } else {
                name = '<<< used by <<<';
            }
            // Initial node
            const node = {
                name: name,
                value: {
                    type: 'edge'
                }
            };

            // Decoration label
            node.label = {
                rich: {}
            };
            const formatterLines = edge.decorations.map(decoration => getDecorationFormatterForLabel(decoration, node.label.rich)).filter(line => line);
            node.label.formatter = formatterLines.join('\n');

            // Decoration tooltip
            const tooltipLines = edge.decorations.map(decoration => getDecorationFormatterForTooltip(decoration)).filter(line => line);
            if (tooltipLines.length > 0) {
                node.tooltip = {
                    show: true,
                    formatter: tooltipLines.join('\n')
                };
            }

            // Linked node as a child
            node.children = [
                transformGraphIntoNode(edge.linkedTo, direction, depth + 1)
            ];
            // OK
            return node;
        };

        const getDecorationFormatterForTooltip = (decoration) => {
            // No decoration when no text
            if (!decoration.text) {
                return '';
            }

            let line = '<p>';

            // Icon
            if (decoration.icon) {
                const iconUrl = getDecorationIconUrl(decoration);
                line += `<img src="${iconUrl}" width="16" height="16" alt="${decoration.icon}"/> `;
            }

            // Link
            if (decoration.url) {
                line += `<a href="${decoration.url}">`;
            }

            // Text
            line += `<span title="${decoration.description}">${decoration.text}</span>`;

            // Closing the link
            if (decoration.url) {
                line += '</a>';
            }

            line += '</p>';
            return line;
        };

        const getDecorationFormatterForLabel = (decoration, classes) => {
            if (decoration.label === 'NONE') {
                return '';
            } else {
                let line = '';
                if ((decoration.label === 'ICON' || decoration.label === 'ALL') && decoration.icon) {
                    const className = `${decoration.feature.id}_${decoration.id}_${decoration.icon}`;
                    const iconUrl = getDecorationIconUrl(decoration);
                    classes[className] = {
                        backgroundColor: {
                            image: iconUrl
                        },
                        height: 16,
                        weight: 16
                    };
                    line += `{${className}|}`;
                }
                if ((decoration.label === 'TEXT' || decoration.label === 'ALL') && decoration.text) {
                    line += `{decorationText|${decoration.text}}`;
                }
                return line;
            }
        };

        const getDecorationIconUrl = (decoration) => {
            if (decoration.icon) {
                return `/extension/${decoration.feature.id}/graph/${decoration.id}/${decoration.icon}.png`;
            } else {
                return '';
            }
        };

        // Loading the raw data
        const loadData = () => {
            return otGraphqlService.pageGraphQLCall(query, {
                branchId: branchId,
                direction: context.direction
            });
        };

        // Query recursive building

        const buildNodeQuery = (levels) => {
            if (levels > 0) {
                return `
                    ...nodeContent
                    edges {
                      direction
                      decorations {
                        ...decorationContent
                      }
                      linkedTo {
                        ${ buildNodeQuery(levels - 1) }
                      }
                    }
                `;
            } else {
                return `
                    ...nodeContent
                `;
            }
        };

        const buildQuery = (levels) => {
            return `
                query BranchBuildGraph(
                  $branchId: Int!,
                  $direction: BranchLinksDirection!
                ) {
                    branches(id: $branchId) {
                      id
                      name
                      links {
                        _page
                      }
                      project {
                        id
                        name
                        links {
                          _page
                        }
                      }
                      builds(count: 1) {
                        name
                        graph(direction: $direction) {
                          ${ buildNodeQuery(levels) }
                        }
                      }
                    }
                }

                fragment decorationContent on BranchLinksDecoration {
                  feature {
                    id
                  }
                  id
                  text
                  description
                  icon
                  url
                  label
                }

                fragment nodeContent on BranchLinksNode {
                  branch {
                    id
                    name
                    links {
                      _page
                    }
                    project {
                      id
                      name
                      links {
                        _page
                      }
                    }
                  }
                  build {
                    id
                    name
                    links {
                      _page
                    }
                    promotionRuns(lastPerLevel: true) {
                      promotionLevel {
                        name
                        links {
                          _image
                        }
                      }
                    }
                  }
                }
            `;
        };

        const query = buildQuery(10);

        // Loading the data on load
        refreshGraph();
    })
;<|endoftext|>


<commit_before>/*
---

name: ViewTransition.Cover

description: Provide a view transition that covers the previous view.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- ViewTransition

provides:
	- ViewTransition.Cover

...
*/

Moobile.ViewTransition.Cover = new Class({

	Extends: Moobile.ViewTransition,

	enter: function(viewToShow, viewToHide, parentView, first) {

		this.parent(viewToShow, viewToHide, parentView, first);

		if (first) {
			this.animate(viewToShow, 'transition-cover-enter-first');
			return this;
		}

		this.addSubject(viewToShow, 'transition-view-to-show');
		this.addSubject(viewToHide, 'transition-view-to-hide');

		this.animate(parentView.content, 'transition-cover-enter');

		return this;
	},

	onEnter: function(viewToShow, viewToHide, parentView, first) {

		this.parent(viewToShow, viewToHide, parentView, first);

		viewToHide.show();
		viewToShow.addClass('transition-cover-enter-background-view');
		viewToShow.addClass('transition-cover-enter-foreground-view');

		return this;
	},

	leave: function(viewToShow, viewToHide, parentView) {

		this.parent(viewToShow, viewToHide, parentView);

		viewToShow.removeClass('transition-cover-enter-background-view');
		viewToShow.removeClass('transition-cover-enter-foreground-view');

		this.addSubject(viewToShow, 'transition-view-to-show');
		this.addSubject(viewToHide, 'transition-view-to-hide');

		this.animate(parentView.content, 'transition-cover-leave');

		return this;
	}

});<commit_msg>Added a presentation option to ViewTransition.Cover, mostly used to present a modal view controller<commit_after>/*
---

name: ViewTransition.Cover

description: Provide a view transition that covers the previous view.

license: MIT-style license.

authors:
	- Jean-Philippe Dery (jeanphilippe.dery@gmail.com)

requires:
	- ViewTransition

provides:
	- ViewTransition.Cover

...
*/

Moobile.ViewTransition.Cover = new Class({

	Extends: Moobile.ViewTransition,

	options: {
		presentation: 'fullscreen' // center, box
	},

	mask: null,

	enter: function(viewToShow, viewToHide, parentView, first) {

		this.parent(viewToShow, viewToHide, parentView, first);

		switch (this.options.presentation) {

			case 'box':
				this.mask = new Moobile.Mask();
				viewToShow = new Element('div.transition-cover-view-wrapper').wraps(viewToShow);
				parentView.addClass('transition-cover-box');
				break;

			case 'center':
				this.mask = new Moobile.Mask();
				parentView.addClass('transition-cover-center');
				break;

			case 'fullscreen':
				this.mask = null;
				break;
		}

		if (this.mask) {

			this.mask.addClass('transition-cover-mask');
			this.mask.addEvent('show', this.bound('onMaskShow'));
			this.mask.addEvent('hide', this.bound('onMaskHide'));

			parentView.addChildView(this.mask)

			this.mask.show();
		}

		if (first) {
			this.animate(viewToShow, 'transition-cover-enter-first');
			return this;
		}

		viewToHide.addClass('transition-cover-background-view');
		viewToShow.addClass('transition-cover-foreground-view');

		this.addSubject(viewToShow, 'transition-view-to-show');
		this.addSubject(viewToHide, 'transition-view-to-hide');

		this.animate(parentView.getContent(), 'transition-cover-enter');

		return this;
	},

	onEnter: function(viewToShow, viewToHide, parentView, first) {

		this.parent(viewToShow, viewToHide, parentView, first);

		viewToHide.show();

		return this;
	},

	leave: function(viewToShow, viewToHide, parentView) {

		this.parent(viewToShow, viewToHide, parentView);

		if (this.mask) {
			this.mask.hide();
		}

		if (this.options.presentation == 'box') {
			var viewToHideElement = document.id(viewToHide);
			var viewToHideWrapper = viewToHideElement.getParent('.transition-cover-view-wrapper');
			if (viewToHideWrapper) {
				viewToHide = viewToHideWrapper;
			}
		}

		this.addSubject(viewToShow, 'transition-view-to-show');
		this.addSubject(viewToHide, 'transition-view-to-hide');

		this.animate(parentView.getContent(), 'transition-cover-leave');

		return this;
	},

	onLeave: function(viewToShow, viewToHide, parentView) {

		this.parent(viewToShow, viewToHide, parentView);

		switch (this.options.presentation) {

			case 'box':

				var viewToHideElement = document.id(viewToHide);
				var viewToHideWrapper = viewToHideElement.getParent('.transition-cover-view-wrapper');
				if (viewToHideWrapper) {
					viewToHideElement.inject(viewToHideWrapper, 'after');
					viewToHideWrapper.destroy();
					viewToHideWrapper = null;
				}

				parentView.removeClass('transition-cover-box');

				break;

			case 'center':
				parentView.removeClass('transition-cover-center');
				break;

			case 'fullscreen':
				break;
		}

		viewToHide.removeClass('transition-cover-foreground-view');
		viewToShow.removeClass('transition-cover-background-view');

		return this;
	},

	onMaskShow: function() {

	},

	onMaskHide: function() {
		this.mask.destroy();
		this.mask = null;
	}

});<|endoftext|>


<commit_before>// Kth Smallest Element in an Array

// Find the kth smallest element in an unsorted array. Note that it is the kth smallest element in the sorted order,
// not the kth distinct element.

// For example,
// Given [3,2,1,5,6,4] and k = 2, return 2.

// Note:
// You may assume k is always valid, 1 ≤ k ≤ array's length.

<commit_msg>add params<commit_after>// Kth Smallest Element in an Array

// Find the kth smallest element in an unsorted array. Note that it is the kth smallest element in the sorted order,
// not the kth distinct element.

// For example,
// Given [3,2,1,5,6,4] and k = 2, return 2.

// Note:
// You may assume k is always valid, 1 ≤ k ≤ array's length.

/**
 * @param {arr[]} nums
 * @param {number} k
 * @return {number}
 */
<|endoftext|>