<commit_before>module.exports = {
  general: {
    title: 'General',
    description: '',
    children: {
      siteName: {
        type: String,
        title: 'Site Name',
        description: '',
        defaults: 'NOKIA DATA GATHERING'
      },
      protocolType: {
        type: String,
        title: 'Protocol',
        description: 'This parameter can be set to http or https',
        defaults: 'http'
      },
      httpspfx: {
        type: String,
        title: 'https pfx',
        description: 'Path to .pfx file',
        defaults: './ndg.pfx'
      },
      httpspassphrase: {
        type: String,
        title: 'https password phrase',
        description: 'Password required by certificate',
        defaults: 'q1w2e3r4'
      },
      port: {
        type: String,
        title: 'Port',
        description: '',
        defaults: 3000
      },
      mongodbUrl: {
        type: String,
        title: 'Mongo DB Url',
        description: '',
        defaults: process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/MDG'
      },
      questionsTypes: {
        type: Object,
        title: 'Available questions types',
        description: 'Types of questions that can be used',
        defaults: ['string', 'int', 'decimal', 'date', 'geopoint', 'binary', 'binary#image', 'select', 'select1', 'time', 'note']
      },
      countries: {
        type: Object,
        title: 'Available countries',
        description: 'Available countries that can be used in registration form',
        defaults: ["Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Antarctic Territory", "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Canton and Enderbury Islands", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos [Keeling] Islands", "Colombia", "Comoros", "Congo - Brazzaville", "Congo - Kinshasa", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Côte d’Ivoire", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Dronning Maud Land", "East Germany", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories", "French Southern and Antarctic Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong SAR China", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Johnston Island", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau SAR China", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Metropolitan France", "Mexico", "Micronesia", "Midway Islands", "Moldova", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar [Burma]", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "Neutral Zone", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "North Vietnam", "Northern Mariana Islands", "Norway", "Oman", "Pacific Islands Trust Territory", "Pakistan", "Palau", "Palestinian Territories", "Panama", "Panama Canal Zone", "Papua New Guinea", "Paraguay", "People's Democratic Republic of Yemen", "Peru", "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russia", "Rwanda", "Réunion", "Saint Barthélemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal", "Serbia", "Serbia and Montenegro", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syria", "São Tomé and Príncipe", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "U.S. Minor Outlying Islands", "U.S. Miscellaneous Pacific Islands", "U.S. Virgin Islands", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Unknown or Invalid Region", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wake Island", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe", "Åland Islands"]
      }
    }
  },
  languages: {
    title: 'Languages',
    description: 'Parameters for Digest Authorization. Do NOT change these unless you know what you are doing',
    children: {
      preferred: {
        type: String,
        title: 'preferred language',
        description: '',
        defaults: 'en'
      },
      supported_languages: {
        type: Object,
        title: 'Supported languages',
        description: '',
        defaults: [
          {value: 'en', text: 'English'},
          {value: 'ru', text: 'Русский'},
          {value: 'zh', text: '中文'},
          {value: 'vi', text: 'Việt' }
        ]
      },
      supported_languages_mobile: {
        type: Object,
        title: 'Supported languages mobile',
        description: '',
        defaults: [
          'es',
          'fi',
          'fr',
          'ht',
          'pl',
          'pt',
          'Русский ru',
          'sw',
          'Việt vi',
          'zh'
        ]
      }
    }
  },
  digestAuth: {
    title: 'Digest Auth',
    description: 'Parameters for Digest Authorization. Do NOT change these unless you know what you are doing',
    children: {
      qop: {
        type: String,
        title: 'qop',
        defaults: 'auth'
      },
      realm: {
        type: String,
        title: 'realm',
        defaults: 'NDG'
      },
      algorithm: {
        type: String,
        title: 'algorithm',
        defaults: 'MD5'
      },
      opaque: {
        type: String,
        title: 'opaque',
        defaults: 'bmRnb3BhcXVl'
      }
    }
  },
  basicAuth: {
    title: 'Basic Auth',
    description: 'Parameters for Basic Authorization.',
    children: {
      username: {
        type: String,
        title: 'username',
        defaults: 'admin'
      },
      password: {
        type: String,
        title: 'password',
        defaults: 'admin'
      }
    }
  },
  tests: {
    title: 'Tests',
    description: '',
    children: {
      host: {
        type: String,
        title: 'Host',
        description: 'Host (ip) to bind for tests',
        defaults: 'localhost'
      },
      port: {
        type: String,
        title: 'Port',
        description: 'Port on which testing server will run',
        defaults: 4000
      },
      mongodbUrl: {
        type: String,
        title: 'MongoDB Url',
        description: '',
        defaults: process.env.MONGO_TEST_URL || 'mongodb://127.0.0.1:27017/MDG-test'
      }
    }
  },
  twilio: {
    title: 'Twilio',
    description: 'Set of parameters used for Twilio configuration',
    children: {
      accountSid: {
        type: String,
        title: 'Twilio Account Sid',
        description: 'Unique ID of the Account - first credential to determine which account an API request is coming from (acts as username)',
        defaults: ''
      },
      authToken: {
        type: String,
        title: 'Twilio Auth Token',
        description: 'Auth Token - second credential which acts as a password',
        defaults: ''
      },
      phoneNumber: {
        type: String,
        title: 'Twilio Phone Number',
        description: 'Phone number provided by Twilio',
        defaults: ''
      }
    }
  },
  messages: {
    title: 'Messages',
    description: '',
    children: {
      registrationSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'Hello, your credentials for MDG are: username %s, password %s.'
      },
      userUpdateSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'Hello, your credentials for MDG have been changed to: username %s, password %s.'
      },
      headerSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'MDG: '
      }
    }
  },
  mail: {
    title: 'Mail',
    description: 'Set of parameters related to mail configuration',
    children: {
      from: {
        title: 'Mail from',
        description: 'Defines e-mail for system messages',
        children: {
          registration: {
            type: String,
            title: 'Registration Email from',
            description: '',
            defaults: 'registration@nokiadatagathering.net'
          },
          subscription: {
            type: String,
            title: 'Subscription Email from',
            description: '',
            defaults: 'noreply@nokiadatagathering.net'
          },
          report: {
            type: String,
            title: 'Subscription Email from',
            description: '',
            defaults: 'report@nokiadatagathering.net'
          },
          forgotUsername: {
            type: String,
            title: 'Forgot Username Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          },
          resetPassword: {
            type: String,
            title: 'Reset Password Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          },
          passwordChanged: {
            type: String,
            title: 'Password Changed Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          }
        }
      },
      mandrillApiKey: {
        type: String,
        title: 'Mandrill Api Key',
        description: 'Defines Mandrill Api Key',
        defaults: ''
      },
      emailsForUsersReport: {
        type: Object,
        title: 'Emails for users registrations report',
        defaults: []
      },
      registration: {
        type: String,
        title: 'Registration Email',
        defaults: '/app/views/emails/${languages.preferred}/registrationEmail.jade'
      },
      subscription: {
        type: String,
        title: 'Subscription Email',
        defaults: '/app/views/emails/${languages.preferred}/subscriptionEmail.jade'
      },
      report: {
        type: String,
        title: 'Registration Email',
        defaults: '/app/views/emails/reportEmail.jade'
      },
      forgotUsername: {
        type: String,
        title: 'Forgot Username Email',
        defaults: '/app/views/emails/${languages.preferred}/forgotUsernameEmail.jade'
      },
      resetPassword: {
        type: String,
        title: 'Reset Password Email',
        defaults: '/app/views/emails/${languages.preferred}/resetPasswordEmail.jade'
      },
      passwordChanged: {
        type: String,
        title: 'Password Changed Email',
        defaults: '/app/views/emails/${languages.preferred}/passwordChangedEmail.jade'
      }
    }
  }
};
<commit_msg>Fixed languages string<commit_after>module.exports = {
  general: {
    title: 'General',
    description: '',
    children: {
      siteName: {
        type: String,
        title: 'Site Name',
        description: '',
        defaults: 'NOKIA DATA GATHERING'
      },
      protocolType: {
        type: String,
        title: 'Protocol',
        description: 'This parameter can be set to http or https',
        defaults: 'http'
      },
      httpspfx: {
        type: String,
        title: 'https pfx',
        description: 'Path to .pfx file',
        defaults: './ndg.pfx'
      },
      httpspassphrase: {
        type: String,
        title: 'https password phrase',
        description: 'Password required by certificate',
        defaults: 'q1w2e3r4'
      },
      port: {
        type: String,
        title: 'Port',
        description: '',
        defaults: 3000
      },
      mongodbUrl: {
        type: String,
        title: 'Mongo DB Url',
        description: '',
        defaults: process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/MDG'
      },
      questionsTypes: {
        type: Object,
        title: 'Available questions types',
        description: 'Types of questions that can be used',
        defaults: ['string', 'int', 'decimal', 'date', 'geopoint', 'binary', 'binary#image', 'select', 'select1', 'time', 'note']
      },
      countries: {
        type: Object,
        title: 'Available countries',
        description: 'Available countries that can be used in registration form',
        defaults: ["Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Antarctic Territory", "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Canton and Enderbury Islands", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos [Keeling] Islands", "Colombia", "Comoros", "Congo - Brazzaville", "Congo - Kinshasa", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Côte d’Ivoire", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Dronning Maud Land", "East Germany", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories", "French Southern and Antarctic Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong SAR China", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Johnston Island", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau SAR China", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Metropolitan France", "Mexico", "Micronesia", "Midway Islands", "Moldova", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar [Burma]", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "Neutral Zone", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "North Vietnam", "Northern Mariana Islands", "Norway", "Oman", "Pacific Islands Trust Territory", "Pakistan", "Palau", "Palestinian Territories", "Panama", "Panama Canal Zone", "Papua New Guinea", "Paraguay", "People's Democratic Republic of Yemen", "Peru", "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russia", "Rwanda", "Réunion", "Saint Barthélemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal", "Serbia", "Serbia and Montenegro", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syria", "São Tomé and Príncipe", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "U.S. Minor Outlying Islands", "U.S. Miscellaneous Pacific Islands", "U.S. Virgin Islands", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Unknown or Invalid Region", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wake Island", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe", "Åland Islands"]
      }
    }
  },
  languages: {
    title: 'Languages',
    description: 'Parameters for Digest Authorization. Do NOT change these unless you know what you are doing',
    children: {
      preferred: {
        type: String,
        title: 'preferred language',
        description: '',
        defaults: 'en'
      },
      supported_languages: {
        type: Object,
        title: 'Supported languages',
        description: '',
        defaults: [
          {value: 'en', text: 'English'},
          {value: 'ru', text: 'Русский'},
          {value: 'zh', text: '中文'},
          {value: 'vi', text: 'Việt' }
        ]
      },
      supported_languages_mobile: {
        type: String,
        title: 'Supported languages mobile',
        description: '',
        defaults: 'Chinese ch\r\nVietnamese vi\r\nSpanish es\r\nFinnish fi\r\nPortuguese pt\r\nRussian ru\r\n'
      }
    }
  },
  digestAuth: {
    title: 'Digest Auth',
    description: 'Parameters for Digest Authorization. Do NOT change these unless you know what you are doing',
    children: {
      qop: {
        type: String,
        title: 'qop',
        defaults: 'auth'
      },
      realm: {
        type: String,
        title: 'realm',
        defaults: 'NDG'
      },
      algorithm: {
        type: String,
        title: 'algorithm',
        defaults: 'MD5'
      },
      opaque: {
        type: String,
        title: 'opaque',
        defaults: 'bmRnb3BhcXVl'
      }
    }
  },
  basicAuth: {
    title: 'Basic Auth',
    description: 'Parameters for Basic Authorization.',
    children: {
      username: {
        type: String,
        title: 'username',
        defaults: 'admin'
      },
      password: {
        type: String,
        title: 'password',
        defaults: 'admin'
      }
    }
  },
  tests: {
    title: 'Tests',
    description: '',
    children: {
      host: {
        type: String,
        title: 'Host',
        description: 'Host (ip) to bind for tests',
        defaults: 'localhost'
      },
      port: {
        type: String,
        title: 'Port',
        description: 'Port on which testing server will run',
        defaults: 4000
      },
      mongodbUrl: {
        type: String,
        title: 'MongoDB Url',
        description: '',
        defaults: process.env.MONGO_TEST_URL || 'mongodb://127.0.0.1:27017/MDG-test'
      }
    }
  },
  twilio: {
    title: 'Twilio',
    description: 'Set of parameters used for Twilio configuration',
    children: {
      accountSid: {
        type: String,
        title: 'Twilio Account Sid',
        description: 'Unique ID of the Account - first credential to determine which account an API request is coming from (acts as username)',
        defaults: ''
      },
      authToken: {
        type: String,
        title: 'Twilio Auth Token',
        description: 'Auth Token - second credential which acts as a password',
        defaults: ''
      },
      phoneNumber: {
        type: String,
        title: 'Twilio Phone Number',
        description: 'Phone number provided by Twilio',
        defaults: ''
      }
    }
  },
  messages: {
    title: 'Messages',
    description: '',
    children: {
      registrationSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'Hello, your credentials for MDG are: username %s, password %s.'
      },
      userUpdateSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'Hello, your credentials for MDG have been changed to: username %s, password %s.'
      },
      headerSms: {
        type: String,
        title: 'User Register Sms',
        description: '',
        defaults: 'MDG: '
      }
    }
  },
  mail: {
    title: 'Mail',
    description: 'Set of parameters related to mail configuration',
    children: {
      from: {
        title: 'Mail from',
        description: 'Defines e-mail for system messages',
        children: {
          registration: {
            type: String,
            title: 'Registration Email from',
            description: '',
            defaults: 'registration@nokiadatagathering.net'
          },
          subscription: {
            type: String,
            title: 'Subscription Email from',
            description: '',
            defaults: 'noreply@nokiadatagathering.net'
          },
          report: {
            type: String,
            title: 'Subscription Email from',
            description: '',
            defaults: 'report@nokiadatagathering.net'
          },
          forgotUsername: {
            type: String,
            title: 'Forgot Username Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          },
          resetPassword: {
            type: String,
            title: 'Reset Password Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          },
          passwordChanged: {
            type: String,
            title: 'Password Changed Email from',
            description: '',
            defaults: 'reset_password@nokiadatagathering.net'
          }
        }
      },
      mandrillApiKey: {
        type: String,
        title: 'Mandrill Api Key',
        description: 'Defines Mandrill Api Key',
        defaults: ''
      },
      emailsForUsersReport: {
        type: Object,
        title: 'Emails for users registrations report',
        defaults: []
      },
      registration: {
        type: String,
        title: 'Registration Email',
        defaults: '/app/views/emails/${languages.preferred}/registrationEmail.jade'
      },
      subscription: {
        type: String,
        title: 'Subscription Email',
        defaults: '/app/views/emails/${languages.preferred}/subscriptionEmail.jade'
      },
      report: {
        type: String,
        title: 'Registration Email',
        defaults: '/app/views/emails/reportEmail.jade'
      },
      forgotUsername: {
        type: String,
        title: 'Forgot Username Email',
        defaults: '/app/views/emails/${languages.preferred}/forgotUsernameEmail.jade'
      },
      resetPassword: {
        type: String,
        title: 'Reset Password Email',
        defaults: '/app/views/emails/${languages.preferred}/resetPasswordEmail.jade'
      },
      passwordChanged: {
        type: String,
        title: 'Password Changed Email',
        defaults: '/app/views/emails/${languages.preferred}/passwordChangedEmail.jade'
      }
    }
  }
};
<|endoftext|>


<commit_before>var fs = require("fs");

function view(templateName, values, response) {
    // Read from the template files
    var fileContents = fs.readFileSync('./views/' + templateName + '.html');
    // Insert values in to the content

    // Write out the contents to the response
    response.write(fileContents);
}

module.exports.view = view;<commit_msg>The template is now binded with real user information<commit_after>var fs = require("fs");

function mergeValues(values, content) {
    // Cycle over the keys
    for(var key in values) {
      // Replace all {{key}} with value form the values object
      content = content.replace("{{" + key + "}}", values[key]);
    }
    // return merged content
    return content;
}

function view(templateName, values, response) {
    // Read from the template files
    var fileContents = fs.readFileSync('./views/' + templateName + '.html', {encoding: "utf-8"});
    // Insert values in to the content
    fileContents = mergeValues(values, fileContents);
    // Write out the contents to the response
    response.write(fileContents);
}

module.exports.view = view;<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
/**
 * @module ogs.vgl
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, continue:true, indent: 2*/

/*global vglModule, gl, ogs, vec2, vec3, vec4, mat4, inherit, $*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class renderState
 *
 * @returns {vglModule.renderState}
 */
//////////////////////////////////////////////////////////////////////////////
vglModule.renderState = function() {
  'use strict';

  this.m_modelViewMatrix = mat4.create();
  this.m_projectionMatrix = null;
  this.m_material = null;
  this.m_mapper = null;
};

////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class renderer *
 *
 * @returns {vglModule.renderer}
 */
////////////////////////////////////////////////////////////////////////////
vglModule.renderer = function() {
  'use strict';

  if (!(this instanceof vglModule.renderer)) {
    return new vglModule.renderer();
  }
  vglModule.object.call(this);

  /** @private */
  var m_backgroundColor = [0.0, 0.0, 0.0, 1.0],
      m_sceneRoot = new vglModule.groupNode(),
      m_camera = new vglModule.camera(),
      m_width = 0,
      m_height = 0;

  m_camera.addChild(m_sceneRoot);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get width of the renderer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.width = function() {
    return m_width;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get height of the renderer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.height = function() {
    return m_height;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get background color
   */
  ////////////////////////////////////////////////////////////////////////////
  this.backgroundColor = function() {
    return m_backgroundColor;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set background color of the renderer
   *
   * @param r
   * @param g
   * @param b
   * @param a
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setBackgroundColor = function(r, g, b, a) {
    m_backgroundColor[0] = r;
    m_backgroundColor[1] = g;
    m_backgroundColor[2] = b;
    m_backgroundColor[3] = a;

    this.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get scene root
   *
   * @returns {vglModule.groupNode}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.sceneRoot = function() {
    return m_sceneRoot;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get main camera of the renderer
   *
   * @returns {vglModule.camera}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.camera = function() {
    return m_camera;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Render the scene
   */
  ////////////////////////////////////////////////////////////////////////////
  this.render = function() {
    var i = 0,
        renSt = null,
        children = null,
        actor = null,
        sortedActors = [];

    gl.clearColor(m_backgroundColor[0], m_backgroundColor[1],
      m_backgroundColor[2], m_backgroundColor[3]);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    renSt = new vglModule.renderState();
    children = m_sceneRoot.children();

    for ( i = 0; i < children.length; ++i) {
      actor = children[i];
      actor.computeBounds();
      if (!actor.visible()) {
        continue;
      }

      sortedActors.push([actor.material().binNumber(), actor]);
    }

    // Now perform sorting
    sortedActors.sort(function(a, b) {return a[0] - b[0];});

    for ( i = 0; i < sortedActors.length; ++i) {
      actor = sortedActors[i][1];

      if (actor.referenceFrame() ===
          vglModule.boundingObject.ReferenceFrame.Relative) {
        mat4.multiply(renSt.m_modelViewMatrix, m_camera.viewMatrix(),
          actor.matrix());
        renSt.m_projectionMatrix = m_camera.projectionMatrix();
      } else {
        renSt.m_modelViewMatrix = actor.matrix();
        renSt.m_projectionMatrix = mat4.create();
        mat4.ortho(renSt.m_projectionMatrix, 0, m_width, 0, m_height, -1, 1);
      }

      renSt.m_material = actor.material();
      renSt.m_mapper = actor.mapper();

      // TODO Fix this shortcut
      renSt.m_material.render(renSt);
      renSt.m_mapper.render(renSt);
      renSt.m_material.remove(renSt);
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Automatically set up the camera based on visible actors
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resetCamera = function() {
    m_camera.computeBounds();

    var vn = m_camera.directionOfProjection(),
        visibleBounds = m_camera.bounds(),
        center = [
          (visibleBounds[0] + visibleBounds[1]) / 2.0,
          (visibleBounds[2] + visibleBounds[3]) / 2.0,
          (visibleBounds[4] + visibleBounds[5]) / 2.0
        ],
        diagonals = [
          visibleBounds[1] - visibleBounds[0],
          visibleBounds[3] - visibleBounds[2],
          visibleBounds[5] - visibleBounds[4]
        ],
        radius = 0.0,
        aspect = m_camera.viewAspect(),
        angle = m_camera.viewAngle(),
        distance = null,
        vup = null;

    if (diagonals[0] > diagonals[1]) {
      if (diagonals[0] > diagonals[2]) {
        radius = diagonals[0] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    } else {
      if (diagonals[1] > diagonals[2]) {
        radius = diagonals[1] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    }

    // @todo Need to figure out what's happening here
    if (aspect >= 1.0) {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) / aspect);
    } else {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) * aspect);
    }

    distance = radius / Math.sin(angle * 0.5);
    vup = m_camera.viewUpDirection();

    if (Math.abs(vec3.dot(vup, vn)) > 0.999) {
      m_camera.setViewUpDirection(-vup[2], vup[0], vup[1]);
    }

    m_camera.setFocalPoint(center[0], center[1], center[2]);
    m_camera.setPosition(center[0] + distance * -vn[0],
      center[1] + distance * -vn[1], center[2] + distance * -vn[2]);

    this.resetCameraClippingRange(visibleBounds);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Recalculate camera's clipping range
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resetCameraClippingRange = function(bounds) {
    var vn = m_camera.viewPlaneNormal(),
        position = m_camera.position(),
        a = -vn[0],
        b = -vn[1],
        c = -vn[2],
        d = -(a*position[0] + b*position[1] + c*position[2]),
        range = vec2.create(),
        dist = null,
        i = null,
        j = null,
        k = null;

    // Set the max near clipping plane and the min far clipping plane
    range[0] = a * bounds[0] + b * bounds[2] + c * bounds[4] + d;
    range[1] = 1e-18;

    // Find the closest / farthest bounding box vertex
    for (k = 0; k < 2; k++ ) {
      for (j = 0; j < 2; j++) {
        for (i = 0; i < 2; i++) {
          dist = a * bounds[i] + b * bounds[2 + j] + c * bounds[4 + k] + d;
          range[0] = (dist < range[0]) ? (dist) : (range[0]);
          range[1] = (dist > range[1]) ? (dist) : (range[1]);
        }
      }
    }

    // Do not let the range behind the camera throw off the calculation.
    if (range[0] < 0.0) {
      range[0] = 0.0;
    }

    // Give ourselves a little breathing room
    range[0] = 0.99 * range[0] - (range[1] - range[0]) * 0.5;
    range[1] = 1.01 * range[1] + (range[1] - range[0]) * 0.5;

    // Make sure near is not bigger than far
    range[0] = (range[0] >= range[1]) ? (0.01 * range[1]) : (range[0]);

    // @todo
    // Make sure near is at least some fraction of far - this prevents near
    // from being behind the camera or too close in front. How close is too
    // close depends on the resolution of the depth buffer
    // if (!this->NearClippingPlaneTolerance)
    //   {
    //   this->NearClippingPlaneTolerance = 0.01;
    //   if (this->RenderWindow)
    //     {
    //     int ZBufferDepth = this->RenderWindow->GetDepthBufferSize();
    //     if ( ZBufferDepth > 16 )
    //       {
    //       this->NearClippingPlaneTolerance = 0.001;
    //       }
    //     }
    //   }

    // make sure the front clipping range is not too far from the far clippnig
    // range, this is to make sure that the zbuffer resolution is effectively
    // used
    // if (range[0] < this->NearClippingPlaneTolerance*range[1]) {
    //   range[0] = this->NearClippingPlaneTolerance*range[1];
    // }

    m_camera.setClippingRange(range[0], range[1]);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Resize viewport given a width and height
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resize = function(width, height) {
    // @note: where do m_x and m_y come from?
    this.positionAndResize(m_x, m_y, width, height);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Resize viewport given a position, width and height
   */
  ////////////////////////////////////////////////////////////////////////////
  this.positionAndResize = function(x, y, width, height) {
    // TODO move this code to camera
    if (x < 0 || y < 0 || width < 0 || height < 0) {
      console.log('[error] Invalid position and resize values',
        x, y, width, height);
    }

    m_width = width;
    m_height = height;

    gl.viewport(x, y, m_width, m_height);
    m_camera.setViewAspect(m_width / m_height);
    this.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Add new actor to the collection
   *
   * @param actor
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.addActor = function(actor) {
    if (actor instanceof vglModule.actor) {
      m_sceneRoot.addChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Add an array of actors to the collection
   */
  ////////////////////////////////////////////////////////////////////////////
  this.addActors = function(actors) {
    var i = null
    if (actors instanceof Array) {
      for (i = 0; i < actors.length; ++i) {
        m_sceneRoot.addChild(actors[i]);
      }
      this.modified();
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove the actor from the collection
   *
   * @param actor
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeActor = function(actor) {
    if (m_sceneRoot.children().indexOf(actor) !== -1) {
      m_sceneRoot.removeChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove actors from the collection
   *
   * @param actors
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeActors = function(actors) {
    if (!(actors instanceof Array)) {
      return false;
    }

    var i;
    for (i = 0; i < actors.length; ++i) {
      m_sceneRoot.removeChild(actors[i]);
    }
    this.modified();
    return true;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove all actors for a renderer
   *
   * @returns {*}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeAllActors = function() {
    return m_sceneRoot.removeChildren();
  }

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point in the world space to display space
   */
  ////////////////////////////////////////////////////////////////////////////
  this.worldToDisplay = function(worldPt, viewMatrix, projectionMatrix, width,
                                 height) {
    var viewProjectionMatrix = mat4.create();
    mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);

    // Transform world to clipping coordinates
    var clipPt = vec4.create();
    vec4.transformMat4(clipPt, worldPt, viewProjectionMatrix);

    if (clipPt[3] !== 0.0) {
      clipPt[0] = clipPt[0] / clipPt[3];
      clipPt[1] = clipPt[1] / clipPt[3];
      clipPt[2] = clipPt[2] / clipPt[3];
      clipPt[3] = 1.0;
    }

    var winX = Math.round((((clipPt[0]) + 1) / 2.0) * width);
    // / We calculate -point3D.getY() because the screen Y axis is
    // / oriented top->down
    var winY = Math.round(((1 - clipPt[1]) / 2.0) * height);
    var winZ = clipPt[2];
    var winW = clipPt[3];

    return vec4.fromValues(winX, winY, winZ, winW);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point in display space to world space
   * @param displayPt
   * @param viewMatrix
   * @param projectionMatrix
   * @param width
   * @param height
   * @returns {vec4}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.displayToWorld = function(displayPt, viewMatrix, projectionMatrix,
                                 width, height) {
    var x = (2.0 * displayPt[0] / width) - 1,
        y = -(2.0 * displayPt[1] / height) + 1,
        z = displayPt[2];

    var viewProjectionInverse = mat4.create();
    mat4.multiply(viewProjectionInverse, projectionMatrix, viewMatrix);
    mat4.invert(viewProjectionInverse, viewProjectionInverse);

    var worldPt = vec4.fromValues(x, y, z, 1);
    vec4.transformMat4(worldPt, worldPt, viewProjectionInverse);
    if (worldPt[3] !== 0.0) {
      worldPt[0] = worldPt[0] / worldPt[3];
      worldPt[1] = worldPt[1] / worldPt[3];
      worldPt[2] = worldPt[2] / worldPt[3];
      worldPt[3] = 1.0;
    }

    return worldPt;
  };

  return this;
};

inherit(vglModule.renderer, vglModule.object);
<commit_msg>Fixed renderer<commit_after>//////////////////////////////////////////////////////////////////////////////
/**
 * @module ogs.vgl
 */

/*jslint devel: true, forin: true, newcap: true, plusplus: true*/
/*jslint white: true, continue:true, bitwise:true, indent: 2*/

/*global vglModule, gl, ogs, vec2, vec3, vec4, mat4, inherit, $*/
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class renderState
 *
 * @returns {vglModule.renderState}
 */
//////////////////////////////////////////////////////////////////////////////
vglModule.renderState = function() {
  'use strict';

  this.m_modelViewMatrix = mat4.create();
  this.m_projectionMatrix = null;
  this.m_material = null;
  this.m_mapper = null;
};

////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class renderer *
 *
 * @returns {vglModule.renderer}
 */
////////////////////////////////////////////////////////////////////////////
vglModule.renderer = function() {
  'use strict';

  if (!(this instanceof vglModule.renderer)) {
    return new vglModule.renderer();
  }
  vglModule.object.call(this);

  /** @private */
  var m_backgroundColor = [0.0, 0.0, 0.0, 1.0],
      m_sceneRoot = new vglModule.groupNode(),
      m_camera = new vglModule.camera(),
      m_x = 0,
      m_y = 0,
      m_width = 0,
      m_height = 0;

  m_camera.addChild(m_sceneRoot);

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get width of the renderer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.width = function() {
    return m_width;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get height of the renderer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.height = function() {
    return m_height;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get background color
   */
  ////////////////////////////////////////////////////////////////////////////
  this.backgroundColor = function() {
    return m_backgroundColor;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Set background color of the renderer
   *
   * @param r
   * @param g
   * @param b
   * @param a
   */
  ////////////////////////////////////////////////////////////////////////////
  this.setBackgroundColor = function(r, g, b, a) {
    m_backgroundColor[0] = r;
    m_backgroundColor[1] = g;
    m_backgroundColor[2] = b;
    m_backgroundColor[3] = a;

    this.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get scene root
   *
   * @returns {vglModule.groupNode}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.sceneRoot = function() {
    return m_sceneRoot;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get main camera of the renderer
   *
   * @returns {vglModule.camera}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.camera = function() {
    return m_camera;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Render the scene
   */
  ////////////////////////////////////////////////////////////////////////////
  this.render = function() {
    var i = 0,
        renSt = null,
        children = null,
        actor = null,
        sortedActors = [];

    gl.clearColor(m_backgroundColor[0], m_backgroundColor[1],
      m_backgroundColor[2], m_backgroundColor[3]);
    gl.enable(gl.DEPTH_TEST);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    renSt = new vglModule.renderState();
    children = m_sceneRoot.children();

    for ( i = 0; i < children.length; ++i) {
      actor = children[i];
      actor.computeBounds();
      if (!actor.visible()) {
        continue;
      }

      sortedActors.push([actor.material().binNumber(), actor]);
    }

    // Now perform sorting
    sortedActors.sort(function(a, b) {return a[0] - b[0];});

    for ( i = 0; i < sortedActors.length; ++i) {
      actor = sortedActors[i][1];

      if (actor.referenceFrame() ===
          vglModule.boundingObject.ReferenceFrame.Relative) {
        mat4.multiply(renSt.m_modelViewMatrix, m_camera.viewMatrix(),
          actor.matrix());
        renSt.m_projectionMatrix = m_camera.projectionMatrix();
      } else {
        renSt.m_modelViewMatrix = actor.matrix();
        renSt.m_projectionMatrix = mat4.create();
        mat4.ortho(renSt.m_projectionMatrix, 0, m_width, 0, m_height, -1, 1);
      }

      renSt.m_material = actor.material();
      renSt.m_mapper = actor.mapper();

      // TODO Fix this shortcut
      renSt.m_material.render(renSt);
      renSt.m_mapper.render(renSt);
      renSt.m_material.remove(renSt);
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Automatically set up the camera based on visible actors
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resetCamera = function() {
    m_camera.computeBounds();

    var vn = m_camera.directionOfProjection(),
        visibleBounds = m_camera.bounds(),
        center = [
          (visibleBounds[0] + visibleBounds[1]) / 2.0,
          (visibleBounds[2] + visibleBounds[3]) / 2.0,
          (visibleBounds[4] + visibleBounds[5]) / 2.0
        ],
        diagonals = [
          visibleBounds[1] - visibleBounds[0],
          visibleBounds[3] - visibleBounds[2],
          visibleBounds[5] - visibleBounds[4]
        ],
        radius = 0.0,
        aspect = m_camera.viewAspect(),
        angle = m_camera.viewAngle(),
        distance = null,
        vup = null;

    if (diagonals[0] > diagonals[1]) {
      if (diagonals[0] > diagonals[2]) {
        radius = diagonals[0] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    } else {
      if (diagonals[1] > diagonals[2]) {
        radius = diagonals[1] / 2.0;
      } else {
        radius = diagonals[2] / 2.0;
      }
    }

    // @todo Need to figure out what's happening here
    if (aspect >= 1.0) {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) / aspect);
    } else {
      angle = 2.0 * Math.atan(Math.tan(angle * 0.5) * aspect);
    }

    distance = radius / Math.sin(angle * 0.5);
    vup = m_camera.viewUpDirection();

    if (Math.abs(vec3.dot(vup, vn)) > 0.999) {
      m_camera.setViewUpDirection(-vup[2], vup[0], vup[1]);
    }

    m_camera.setFocalPoint(center[0], center[1], center[2]);
    m_camera.setPosition(center[0] + distance * -vn[0],
      center[1] + distance * -vn[1], center[2] + distance * -vn[2]);

    this.resetCameraClippingRange(visibleBounds);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Recalculate camera's clipping range
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resetCameraClippingRange = function(bounds) {
    var vn = m_camera.viewPlaneNormal(),
        position = m_camera.position(),
        a = -vn[0],
        b = -vn[1],
        c = -vn[2],
        d = -(a*position[0] + b*position[1] + c*position[2]),
        range = vec2.create(),
        dist = null,
        i = null,
        j = null,
        k = null;

    // Set the max near clipping plane and the min far clipping plane
    range[0] = a * bounds[0] + b * bounds[2] + c * bounds[4] + d;
    range[1] = 1e-18;

    // Find the closest / farthest bounding box vertex
    for (k = 0; k < 2; k++ ) {
      for (j = 0; j < 2; j++) {
        for (i = 0; i < 2; i++) {
          dist = a * bounds[i] + b * bounds[2 + j] + c * bounds[4 + k] + d;
          range[0] = (dist < range[0]) ? (dist) : (range[0]);
          range[1] = (dist > range[1]) ? (dist) : (range[1]);
        }
      }
    }

    // Do not let the range behind the camera throw off the calculation.
    if (range[0] < 0.0) {
      range[0] = 0.0;
    }

    // Give ourselves a little breathing room
    range[0] = 0.99 * range[0] - (range[1] - range[0]) * 0.5;
    range[1] = 1.01 * range[1] + (range[1] - range[0]) * 0.5;

    // Make sure near is not bigger than far
    range[0] = (range[0] >= range[1]) ? (0.01 * range[1]) : (range[0]);

    // @todo
    // Make sure near is at least some fraction of far - this prevents near
    // from being behind the camera or too close in front. How close is too
    // close depends on the resolution of the depth buffer
    // if (!this->NearClippingPlaneTolerance)
    //   {
    //   this->NearClippingPlaneTolerance = 0.01;
    //   if (this->RenderWindow)
    //     {
    //     int ZBufferDepth = this->RenderWindow->GetDepthBufferSize();
    //     if ( ZBufferDepth > 16 )
    //       {
    //       this->NearClippingPlaneTolerance = 0.001;
    //       }
    //     }
    //   }

    // make sure the front clipping range is not too far from the far clippnig
    // range, this is to make sure that the zbuffer resolution is effectively
    // used
    // if (range[0] < this->NearClippingPlaneTolerance*range[1]) {
    //   range[0] = this->NearClippingPlaneTolerance*range[1];
    // }

    m_camera.setClippingRange(range[0], range[1]);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Resize viewport given a width and height
   */
  ////////////////////////////////////////////////////////////////////////////
  this.resize = function(width, height) {
    // @note: where do m_x and m_y come from?
    this.positionAndResize(m_x, m_y, width, height);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Resize viewport given a position, width and height
   */
  ////////////////////////////////////////////////////////////////////////////
  this.positionAndResize = function(x, y, width, height) {
    // TODO move this code to camera
    if (x < 0 || y < 0 || width < 0 || height < 0) {
      console.log('[error] Invalid position and resize values',
        x, y, width, height);
    }

    m_width = width;
    m_height = height;

    gl.viewport(x, y, m_width, m_height);
    m_camera.setViewAspect(m_width / m_height);
    this.modified();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Add new actor to the collection
   *
   * @param actor
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.addActor = function(actor) {
    if (actor instanceof vglModule.actor) {
      m_sceneRoot.addChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Add an array of actors to the collection
   */
  ////////////////////////////////////////////////////////////////////////////
  this.addActors = function(actors) {
    var i = null;
    if (actors instanceof Array) {
      for (i = 0; i < actors.length; ++i) {
        m_sceneRoot.addChild(actors[i]);
      }
      this.modified();
    }
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove the actor from the collection
   *
   * @param actor
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeActor = function(actor) {
    if (m_sceneRoot.children().indexOf(actor) !== -1) {
      m_sceneRoot.removeChild(actor);
      this.modified();
      return true;
    }

    return false;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove actors from the collection
   *
   * @param actors
   * @returns {boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeActors = function(actors) {
    if (!(actors instanceof Array)) {
      return false;
    }

    var i;
    for (i = 0; i < actors.length; ++i) {
      m_sceneRoot.removeChild(actors[i]);
    }
    this.modified();
    return true;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Remove all actors for a renderer
   *
   * @returns {*}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.removeAllActors = function() {
    return m_sceneRoot.removeChildren();
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point in the world space to display space
   */
  ////////////////////////////////////////////////////////////////////////////
  this.worldToDisplay = function(worldPt, viewMatrix, projectionMatrix, width,
                                 height) {
    var viewProjectionMatrix = mat4.create(),
        winX = null,
        winY = null,
        winZ = null,
        winW = null,
        clipPt = null;

    mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);

    // Transform world to clipping coordinates
    clipPt = vec4.create();
    vec4.transformMat4(clipPt, worldPt, viewProjectionMatrix);

    if (clipPt[3] !== 0.0) {
      clipPt[0] = clipPt[0] / clipPt[3];
      clipPt[1] = clipPt[1] / clipPt[3];
      clipPt[2] = clipPt[2] / clipPt[3];
      clipPt[3] = 1.0;
    }

    winX = Math.round((((clipPt[0]) + 1) / 2.0) * width);
    // We calculate -point3D.getY() because the screen Y axis is
    // oriented top->down
    winY = Math.round(((1 - clipPt[1]) / 2.0) * height);
    winZ = clipPt[2];
    winW = clipPt[3];

    return vec4.fromValues(winX, winY, winZ, winW);
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point in display space to world space
   * @param displayPt
   * @param viewMatrix
   * @param projectionMatrix
   * @param width
   * @param height
   * @returns {vec4}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.displayToWorld = function(displayPt, viewMatrix, projectionMatrix,
                                 width, height) {
    var x = (2.0 * displayPt[0] / width) - 1,
        y = -(2.0 * displayPt[1] / height) + 1,
        z = displayPt[2],
        viewProjectionInverse = mat4.create(),
        worldPt = null;

    mat4.multiply(viewProjectionInverse, projectionMatrix, viewMatrix);
    mat4.invert(viewProjectionInverse, viewProjectionInverse);

    worldPt = vec4.fromValues(x, y, z, 1);
    vec4.transformMat4(worldPt, worldPt, viewProjectionInverse);
    if (worldPt[3] !== 0.0) {
      worldPt[0] = worldPt[0] / worldPt[3];
      worldPt[1] = worldPt[1] / worldPt[3];
      worldPt[2] = worldPt[2] / worldPt[3];
      worldPt[3] = 1.0;
    }

    return worldPt;
  };

  return this;
};

inherit(vglModule.renderer, vglModule.object);
<|endoftext|>


<commit_before>/**
 * @file TriggerPop component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
import Transition from 'react-transition-group/Transition';
import eventsOn from 'dom-helpers/events/on';
import eventsOff from 'dom-helpers/events/off';
import classNames from 'classnames';

import Portal from '../Portal';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Event from '../_vendors/Event';
import Util from '../_vendors/Util';
import TriggerPopCalculation from '../_vendors/TriggerPopCalculation';
// import Dom from '../_vendors/Dom';

class TriggerPop extends Component {

    static Position = Position;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        // this.scrollEl = null;

        this.state = {
            enter: false,
            exited: true
        };

    }

    /**
     * public
     */
    getEl = () => {
        return this.transitionEl;
    };

    enterHandler = el => {

        this.transitionEl = el;
        this.resetPosition();

        this.setState({
            enter: true
        }, () => {
            const {onRender} = this.props;
            onRender && onRender(el, this.props.triggerEl);
        });

    };

    enteredHandler = el => {
        const {onRendered} = this.props;
        onRendered && onRendered(el, this.props.triggerEl);
    };

    exitHandler = el => {
        this.setState({
            enter: false
        }, () => {
            const {onDestroy} = this.props;
            onDestroy && onDestroy(el, this.props.triggerEl);
        });
    };

    exitedHandler = el => {
        this.setState({
            exited: true
        }, () => {
            const {onDestroyed} = this.props;
            onDestroyed && onDestroyed(el, this.props.triggerEl);
        });
    };

    debounceResetPosition = debounce(() => {
        this.resetPosition();
    }, this.props.resetPositionWait);

    resetPosition = (props = this.props) => {
        const {parentEl, triggerEl, position, isTriggerPositionFixed} = props;
        TriggerPopCalculation.setStyle(parentEl, triggerEl, this.transitionEl, position, isTriggerPositionFixed);
    };

    // addWatchScroll = () => {
    //
    //     const {triggerEl} = this.props;
    //
    //     if (!triggerEl) {
    //         return;
    //     }
    //
    //     const scrollEl = Dom.getClosestScrollable(triggerEl);
    //
    //     if (!scrollEl || scrollEl == document.body) {
    //         return;
    //     }
    //
    //     this.scrollEl = scrollEl;
    //
    //     eventsOn(scrollEl, 'scroll', this.debounceResetPosition);
    //
    // };

    componentDidMount() {
        eventsOn(window, 'resize', this.debounceResetPosition);
    }

    // componentDidUpdate(prevProps) {
    //     if (!prevProps.visible && this.props.visible) {
    //         this.addWatchScroll();
    //     } else if (prevProps.visible && !this.props.visible) {
    //         this.scrollEl && eventsOff(this.scrollEl, 'scroll', this.debounceResetPosition);
    //         this.scrollEl = null;
    //     }
    // }

    componentWillReceiveProps(nextProps) {

        if (nextProps.visible) {
            this.setState({
                exited: !nextProps.visible
            });
        }

        if (nextProps.position !== this.props.position) {
            this.resetPosition(nextProps);
        }

    }

    componentWillUnmount() {
        eventsOff(window, 'resize', this.debounceResetPosition);
    }

    render() {

        const {

                children,

                className, contentClassName, modalClassName, style, theme, parentEl,
                hasTriangle, triangle, position, isAnimated, visible, showModal,

                // not passing down these props
                isEscClose, isBlurClose, shouldPreventContainerScroll, triggerEl, isTriggerPositionFixed,
                resetPositionWait,
                onRender, onRendered, onDestroy, onDestroyed,

                ...restProps

            } = this.props,
            {enter, exited} = this.state,

            popModalClassName = classNames('trigger-pop-modal', {
                hidden: !enter,
                'trigger-pop-modal-animated': isAnimated,
                [modalClassName]: modalClassName
            }),

            popupClassName = classNames('trigger-pop', {
                hidden: !enter,
                'trigger-pop-has-triangle': hasTriangle,
                [`theme-${theme}`]: theme,
                [`trigger-pop-${position}`]: position,
                'trigger-pop-animated': isAnimated,
                [className]: className
            }),

            popContentClassName = classNames('trigger-pop-content', {
                [contentClassName]: contentClassName
            });

        return (
            <Portal visible={!exited}
                    parentEl={parentEl}>

                {
                    showModal ?
                        <Transition appear
                                    in={visible}
                                    timeout={250}>

                        </Transition>
                        :
                        null
                }

                <Transition appear
                            in={visible}
                            timeout={250}
                            onEnter={this.enterHandler}
                            onEntered={this.enteredHandler}
                            onExit={this.exitHandler}
                            onExited={this.exitedHandler}>
                    <Paper {...restProps}
                           className={popupClassName}
                           style={style}
                           onWheel={e => Event.wheelHandler(e, this.props)}>

                        {
                            hasTriangle ?

                                    {triangle}

                                :
                                null
                        }

 Event.wheelHandler(e, this.props)}>
                            {children}

                    </Paper>
                </Transition>

            </Portal>
        );

    }

}

TriggerPop.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the content element.
     */
    contentClassName: PropTypes.string,

    modalClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The trigger pop theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    parentEl: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the trigger pop.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the trigger pop is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the trigger pop will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    showModal: PropTypes.bool,

    /**
     * The trigger pop alignment.The value can be Popup.Position.LEFT or Popup.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,popup will have animation effects.
     */
    isAnimated: PropTypes.bool,

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isBlurClose: PropTypes.bool,
    isEscClose: PropTypes.bool,
    shouldPreventContainerScroll: PropTypes.bool,
    isTriggerPositionFixed: PropTypes.bool,
    resetPositionWait: PropTypes.number,

    /**
     * The function of popup render.
     */
    onRender: PropTypes.func,

    /**
     * The function of popup rendered.
     */
    onRendered: PropTypes.func,

    /**
     * The function of popup destroy.
     */
    onDestroy: PropTypes.func,

    /**
     * The function of popup destroyed.
     */
    onDestroyed: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

TriggerPop.defaultProps = {

    theme: Theme.DEFAULT,
    parentEl: document.body,
    depth: 3,

    visible: false,
    hasTriangle: true,
    triangle:

,
    showModal: false,
    position: Position.BOTTOM,
    isAnimated: true,

    isBlurClose: true,
    isEscClose: true,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false,
    resetPositionWait: 250

};

export default TriggerPop;
<commit_msg>update TriggerPop<commit_after>/**
 * @file TriggerPop component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
import Transition from 'react-transition-group/Transition';
import eventsOn from 'dom-helpers/events/on';
import eventsOff from 'dom-helpers/events/off';
import classNames from 'classnames';

import Portal from '../Portal';
import Paper from '../Paper';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Event from '../_vendors/Event';
import Util from '../_vendors/Util';
import TriggerPopCalculation from '../_vendors/TriggerPopCalculation';
// import Dom from '../_vendors/Dom';

class TriggerPop extends Component {

    static Position = Position;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        // this.scrollEl = null;

        this.state = {
            enter: false,
            exited: true
        };

    }

    /**
     * public
     */
    getEl = () => {
        return this.transitionEl;
    };

    enterHandler = el => {

        this.transitionEl = el;
        this.resetPosition();

        this.setState({
            enter: true
        }, () => {
            const {onRender} = this.props;
            onRender && onRender(el, this.props.triggerEl);
        });

    };

    enteredHandler = el => {
        const {onRendered} = this.props;
        onRendered && onRendered(el, this.props.triggerEl);
    };

    exitHandler = el => {
        this.setState({
            enter: false
        }, () => {
            const {onDestroy} = this.props;
            onDestroy && onDestroy(el, this.props.triggerEl);
        });
    };

    exitedHandler = el => {
        this.setState({
            exited: true
        }, () => {
            const {onDestroyed} = this.props;
            onDestroyed && onDestroyed(el, this.props.triggerEl);
        });
    };

    debounceResetPosition = debounce(() => {
        this.resetPosition();
    }, this.props.resetPositionWait);

    resetPosition = (props = this.props) => {
        const {parentEl, triggerEl, position, isTriggerPositionFixed} = props;
        TriggerPopCalculation.setStyle(parentEl, triggerEl, this.transitionEl, position, isTriggerPositionFixed);
    };

    // addWatchScroll = () => {
    //
    //     const {triggerEl} = this.props;
    //
    //     if (!triggerEl) {
    //         return;
    //     }
    //
    //     const scrollEl = Dom.getClosestScrollable(triggerEl);
    //
    //     if (!scrollEl || scrollEl == document.body) {
    //         return;
    //     }
    //
    //     this.scrollEl = scrollEl;
    //
    //     eventsOn(scrollEl, 'scroll', this.debounceResetPosition);
    //
    // };

    componentDidMount() {
        eventsOn(window, 'resize', this.debounceResetPosition);
    }

    componentDidUpdate(prevProps) {

        if (prevProps.position !== this.props.position) {
            this.resetPosition(this.props);
        }

        // if (!prevProps.visible && this.props.visible) {
        //     this.addWatchScroll();
        // } else if (prevProps.visible && !this.props.visible) {
        //     this.scrollEl && eventsOff(this.scrollEl, 'scroll', this.debounceResetPosition);
        //     this.scrollEl = null;
        // }

    }

    componentWillUnmount() {
        eventsOff(window, 'resize', this.debounceResetPosition);
    }

    static getDerivedStateFromProps(props) {

        const result = {
            prevProps: props
        };

        if (props.visible) {
            result.exited = !props.visible;
        }

        return result;

    }

    render() {

        const {

                children,

                className, contentClassName, modalClassName, style, theme, parentEl,
                hasTriangle, triangle, position, isAnimated, visible, showModal,

                // not passing down these props
                isEscClose, isBlurClose, shouldPreventContainerScroll, triggerEl, isTriggerPositionFixed,
                resetPositionWait,
                onRender, onRendered, onDestroy, onDestroyed,

                ...restProps

            } = this.props,
            {enter, exited} = this.state,

            popModalClassName = classNames('trigger-pop-modal', {
                hidden: !enter,
                'trigger-pop-modal-animated': isAnimated,
                [modalClassName]: modalClassName
            }),

            popupClassName = classNames('trigger-pop', {
                hidden: !enter,
                'trigger-pop-has-triangle': hasTriangle,
                [`theme-${theme}`]: theme,
                [`trigger-pop-${position}`]: position,
                'trigger-pop-animated': isAnimated,
                [className]: className
            }),

            popContentClassName = classNames('trigger-pop-content', {
                [contentClassName]: contentClassName
            });

        return (
            <Portal visible={!exited}
                    parentEl={parentEl}>

                {
                    showModal ?
                        <Transition appear
                                    in={visible}
                                    timeout={250}>

                        </Transition>
                        :
                        null
                }

                <Transition appear
                            in={visible}
                            timeout={250}
                            onEnter={this.enterHandler}
                            onEntered={this.enteredHandler}
                            onExit={this.exitHandler}
                            onExited={this.exitedHandler}>
                    <Paper {...restProps}
                           className={popupClassName}
                           style={style}
                           onWheel={e => Event.wheelHandler(e, this.props)}>

                        {
                            hasTriangle ?

                                    {triangle}

                                :
                                null
                        }

 Event.wheelHandler(e, this.props)}>
                            {children}

                    </Paper>
                </Transition>

            </Portal>
        );

    }

}

TriggerPop.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the content element.
     */
    contentClassName: PropTypes.string,

    modalClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The trigger pop theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    parentEl: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the trigger pop.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the trigger pop is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the trigger pop will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    showModal: PropTypes.bool,

    /**
     * The trigger pop alignment.The value can be Popup.Position.LEFT or Popup.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true,popup will have animation effects.
     */
    isAnimated: PropTypes.bool,

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isBlurClose: PropTypes.bool,
    isEscClose: PropTypes.bool,
    shouldPreventContainerScroll: PropTypes.bool,
    isTriggerPositionFixed: PropTypes.bool,
    resetPositionWait: PropTypes.number,

    /**
     * The function of popup render.
     */
    onRender: PropTypes.func,

    /**
     * The function of popup rendered.
     */
    onRendered: PropTypes.func,

    /**
     * The function of popup destroy.
     */
    onDestroy: PropTypes.func,

    /**
     * The function of popup destroyed.
     */
    onDestroyed: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

TriggerPop.defaultProps = {

    theme: Theme.DEFAULT,
    parentEl: document.body,
    depth: 3,

    visible: false,
    hasTriangle: true,
    triangle:

,
    showModal: false,
    position: Position.BOTTOM,
    isAnimated: true,

    isBlurClose: true,
    isEscClose: true,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false,
    resetPositionWait: 250

};

export default TriggerPop;
<|endoftext|>


<commit_before>/**
 * @ngdoc filter
 * @name formatBytes
 * @kind function
 *
 * @description
 * Convert number into abbreviations.
 * i.e: K for one thousand, M for Million, B for billion
 * e.g: number of users:235,221, decimal:1 => 235.2 K
 */
angular.module('a8m.math.shortFmt', ['a8m.math'])
  .filter('shortFmt', ['$math', function ($math) {
    return function (number, decimal) {
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(number) && isFinite(number)){
        if(number < 1e3) {
          return number;
        } else if(number < 1e6) {
          return convertToDecimal((number / 1e3), decimal, $math) + ' K';
        } else if(number < 1e9){
          return convertToDecimal((number / 1e6), decimal, $math) + ' M';
        } else {
          return convertToDecimal((number / 1e9), decimal, $math) + ' B';
        }

      }
      return "NaN";
    }
  }]);<commit_msg>shortFmt always returns String when given Number<commit_after>/**
 * @ngdoc filter
 * @name formatBytes
 * @kind function
 *
 * @description
 * Convert number into abbreviations.
 * i.e: K for one thousand, M for Million, B for billion
 * e.g: number of users:235,221, decimal:1 => 235.2 K
 */
angular.module('a8m.math.shortFmt', ['a8m.math'])
  .filter('shortFmt', ['$math', function ($math) {
    return function (number, decimal) {
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(number) && isFinite(number)){
        if(number < 1e3) {
          return '' + number;  // Coerce to string
        } else if(number < 1e6) {
          return convertToDecimal((number / 1e3), decimal, $math) + ' K';
        } else if(number < 1e9){
          return convertToDecimal((number / 1e6), decimal, $math) + ' M';
        } else {
          return convertToDecimal((number / 1e9), decimal, $math) + ' B';
        }

      }
      return "NaN";
    }
  }]);<|endoftext|>


<commit_before>export default [
  {
    name: 'Razvan Stoenescu',
    role: 'Creator, Lead Dev & Architect',
    avatar: 'razvan_stoenescu.jpeg',
    email: 'razvan@quasar.dev',
    twitter: 'quasarframework',
    github: 'rstoenescu',
    desc: 'Architecture and development of Quasar on all fronts'
  },

  {
    name: 'Dan Popescu',
    role: 'Senior Core Developer',
    avatar: 'dan_popescu.jpg',
    email: 'dan@quasar.dev',
    github: 'pdanpdan',
    desc: 'Focuses on Quasar UI components, directives and plugins'
  },

  {
    name: 'Jeff Galbraith',
    role: 'Senior Developer',
    avatar: 'jeff_galbraith.jpg',
    email: 'jeff@quasar.dev',
    twitter: 'jgalbraith64',
    github: 'hawkeye64',
    desc: 'UI components, App Extensions and community outreach'
  },

  {
    name: 'Allan Gaunt',
    role: 'Senior Developer',
    avatar: 'allan_gaunt.png',
    github: 'webnoob',
    desc: 'BEX (browser extension App CLI mode), web products and security research'
  },

  {
    name: 'Scott Molinari',
    role: 'Media Manager',
    avatar: 'scott_molinari.jpg',
    github: 'smolinari',
    desc: 'Manages our Facebook page, blog and forum. Helps with docs, bug reports, external systems, writes and manages articles and offers community support.'
  },

  {
    name: 'Paolo Caleffi',
    role: 'Senior developer',
    avatar: 'paolo_caleffi.jpg',
    github: 'IlCallo',
    desc: 'Typescript support'
  },

  {
    name: 'Tobias Mesquita',
    role: 'Senior Developer',
    avatar: 'tobias_mesquita.jpg',
    github: 'TobyMosque',
    desc: 'Help desk'
  },

  {
    name: 'Aldrin Marquez',
    role: 'Community Staff',
    avatar: 'aldrin_marquez.jpg',
    github: 'metalsadman',
    desc: 'Help desk'
  },

  {
    name: 'Kerry Huguet',
    role: 'Senior Developer',
    avatar: 'kerry_huguet.jpeg',
    github: 'outofmemoryagain',
    desc: 'Typescript support'
  },

  {
    name: 'Noah Klayman',
    role: 'Developer / Community Staff',
    avatar: 'noah_klayman.jpeg',
    github: 'nklayman',
    desc: 'Capacitor App CLI mode'
  },

  {
    name: 'Matyáš Racek',
    role: 'Community Staff',
    avatar: 'matyas_panstromek.jpeg',
    github: 'panstromek',
    desc: 'Help desk'
  },

  {
    name: 'Ben Coughenour',
    role: 'Community Staff',
    avatar: 'ben_coughenour.jpg',
    github: 'sskwrl',
    desc: 'Help desk'
  },

  {
    name: 'Heitor Ribeiro',
    role: 'Community Staff',
    avatar: 'heitor_ribeiro.jpg',
    github: 'bloodf',
    desc: 'Writes articles and offers community support.'
  },

  {
    name: 'Jesús Villanueva',
    role: 'Senior Developer',
    avatar: 'jesus_villanueva.jpg',
    github: 'jesusvilla',
    desc: 'UI components, App Extensions and Help desk'
  },

  {
    name: 'Adam Purdy',
    role: 'Community Staff',
    avatar: 'adam_purdy.jpg',
    github: 'adamkpurdy',
    desc: 'Firebase Support Owner & Maintainer, Quasar support member.'
  },

  {
    name: 'Ross Ball',
    role: 'Designer',
    avatar: 'ross_ball.jpeg',
    github: 'rossity',
    desc: 'Quasar Themes'
  }
]
<commit_msg>Add Dmitrij Polianin to team list (#7163)<commit_after>export default [
  {
    name: 'Razvan Stoenescu',
    role: 'Creator, Lead Dev & Architect',
    avatar: 'razvan_stoenescu.jpeg',
    email: 'razvan@quasar.dev',
    twitter: 'quasarframework',
    github: 'rstoenescu',
    desc: 'Architecture and development of Quasar on all fronts'
  },

  {
    name: 'Dan Popescu',
    role: 'Senior Core Developer',
    avatar: 'dan_popescu.jpg',
    email: 'dan@quasar.dev',
    github: 'pdanpdan',
    desc: 'Focuses on Quasar UI components, directives and plugins'
  },

  {
    name: 'Jeff Galbraith',
    role: 'Senior Developer',
    avatar: 'jeff_galbraith.jpg',
    email: 'jeff@quasar.dev',
    twitter: 'jgalbraith64',
    github: 'hawkeye64',
    desc: 'UI components, App Extensions and community outreach'
  },

  {
    name: 'Allan Gaunt',
    role: 'Senior Developer',
    avatar: 'allan_gaunt.png',
    github: 'webnoob',
    desc: 'BEX (browser extension App CLI mode), web products and security research'
  },

  {
    name: 'Scott Molinari',
    role: 'Media Manager',
    avatar: 'scott_molinari.jpg',
    github: 'smolinari',
    desc: 'Manages our Facebook page, blog and forum. Helps with docs, bug reports, external systems, writes and manages articles and offers community support.'
  },

  {
    name: 'Paolo Caleffi',
    role: 'Senior developer',
    avatar: 'paolo_caleffi.jpg',
    github: 'IlCallo',
    desc: 'Typescript support'
  },

  {
    name: 'Tobias Mesquita',
    role: 'Senior Developer',
    avatar: 'tobias_mesquita.jpg',
    github: 'TobyMosque',
    desc: 'Help desk'
  },

  {
    name: 'Aldrin Marquez',
    role: 'Community Staff',
    avatar: 'aldrin_marquez.jpg',
    github: 'metalsadman',
    desc: 'Help desk'
  },

  {
    name: 'Kerry Huguet',
    role: 'Senior Developer',
    avatar: 'kerry_huguet.jpeg',
    github: 'outofmemoryagain',
    desc: 'Typescript support'
  },

  {
    name: 'Noah Klayman',
    role: 'Developer / Community Staff',
    avatar: 'noah_klayman.jpeg',
    github: 'nklayman',
    desc: 'Capacitor App CLI mode'
  },

  {
    name: 'Matyáš Racek',
    role: 'Community Staff',
    avatar: 'matyas_panstromek.jpeg',
    github: 'panstromek',
    desc: 'Help desk'
  },

  {
    name: 'Ben Coughenour',
    role: 'Community Staff',
    avatar: 'ben_coughenour.jpg',
    github: 'sskwrl',
    desc: 'Help desk'
  },

  {
    name: 'Heitor Ribeiro',
    role: 'Community Staff',
    avatar: 'heitor_ribeiro.jpg',
    github: 'bloodf',
    desc: 'Writes articles and offers community support.'
  },

  {
    name: 'Jesús Villanueva',
    role: 'Senior Developer',
    avatar: 'jesus_villanueva.jpg',
    github: 'jesusvilla',
    desc: 'UI components, App Extensions and Help desk'
  },

  {
    name: 'Adam Purdy',
    role: 'Community Staff',
    avatar: 'adam_purdy.jpg',
    github: 'adamkpurdy',
    desc: 'Firebase Support Owner & Maintainer, Quasar support member.'
  },

  {
    name: 'Ross Ball',
    role: 'Designer',
    avatar: 'ross_ball.jpeg',
    github: 'rossity',
    desc: 'Quasar Themes'
  },

  {
    name: 'Dmitrij Polianin',
    role: 'Trainer / Community Staff',
    avatar: 'dmitrij_polianin.jpg',
    email: 'dmitrij.polyanin@gmail.com',
    github: 'DmitrijOkeanij',
    desc: 'Russian Community maintainer and Quasar Trainer.'
  }
]
<|endoftext|>


<commit_before>
angular.module('dashboard', ['ngAnimate', 'ui.bootstrap'])
    .controller('DashboardController', function($scope,$uibModal, UserFactory,moment) {
        $scope.locations = (UserFactory.currentUser.data.locations !== undefined) ?
          UserFactory.currentUser.data.locations : [];

        $scope.addbar = {
            text: '',
            placeholder: 'Add location'
        };

        $scope.currentLocation = $scope.locations[0];
        $scope.currentReservations = [];

        // $scope.currentRoom = [];

        //change the drop down and sets the selected room in scope
        $(".main").on('click', ".dropdown-menu#room li a", function() {
            $scope.roomInput = this.text

            $(this).parents(".dropdown").find('.btn').html($(this).text() + ' ');
            $(this).parents(".dropdown").find('.btn').val($(this).data('value'));
        });

        //change the drop down and sets the selected time in scope
        $(".main").on('click', ".dropdown-menu#time li a", function() {
            $scope.timeInput = this.text
            $(this).parents(".dropdown").find('.btn').html($(this).text() + ' ');
            $(this).parents(".dropdown").find('.btn').val($(this).data('value'));
        });

        $scope.roomInput = ""
        $scope.calendarInput = ""
        $scope.timeInput = ""
        $scope.resDescInput = ""
        $scope.confirmReservation = function(){
            var date =  $scope.eve.eventDate
            var formatted = moment(date).format('DD/MM/YYYY');
            // $scope.calendarInput = $scope.eve.eventDate || ""

            var timeFormatted = function(time){
                var momentObj = moment(time, ["h:mm A"])
                var formattedTime = momentObj.format("HH:mm")
                return formattedTime
            }

            var AddHour = function(time){
                var momentObj = moment(time, ["h:mm A"])
                var newHour = momentObj.add(1,'hour')
                var formattedTime = momentObj.format("HH:mm")
                return formattedTime
            }

            var startTime = timeFormatted($scope.timeInput))
            var endTime = AddHour($scope.timeInput)
            var reservationName = $scope.resDescInput
            var roomId = $scope.roomInput

            // console.log($scope.resDescInput)
            // console.log($scope.roomInput)
            // console.log(formatted)
            // console.log($scope.currentLocation.locationName)
            // console.log($scope.timeInput)

             // console.log(endTime)
            // UserFactory.addReservation(locId,roomId,startTime,endTime,reservationName)
        }

        $scope.selectedLocation = function(index) {
            $scope.currentReservations = []
            $scope.currentLocation = $scope.locations[index]

            console.log("was run")
            angular.forEach($scope.currentLocation.rooms, function(index) {
                console.log("reservations: ", index)
                angular.forEach(index.reservations, function(index) {
                    console.log("index: ", index)
                    $scope.currentReservations.push(index)
                })
            })
        }

        $scope.addLocation = function() {
            UserFactory.addLocation($scope.addbar.text)
                .then(function(location) {
                    console.log('location: ', location);

                    $scope.locations.push(location);
                    $scope.addbar.text = '';
                    //$scope.alerts.push({type: 'success', msg: 'Your preferences have been saved!'});
                })
                .catch(function(error) {
                    //$scope.alerts.push({type: 'danger', msg: 'Error saving preferences.'});
                    console.error('Error adding location: ', error);
                });
        };

        $scope.open = function (size) {
          var modalInstance = $uibModal.open({
                animation: $scope.animationsEnabled,
                templateUrl: 'addModal.html',
                controller: 'DashboardController',
                size: size
            });
            $scope.addLocation();
        };

        $scope.openCal = function(){
          $scope.popupCal.opened = true;
        };

        $scope.popupCal = {
          opened: false
        };

        $scope.addUserInput = "";
        $scope.addRoomInput = "";

        $scope.addRoomsUsers = function(){
          var usersList = $scope.addUserInput.split(',');
          var roomsList = $scope.addRoomInput.split(',');

          UserFactory.addRoomsAndUsers($scope.currentLocation.id, usersList, roomsList);
        }
    });
<commit_msg>[fix] typeo2<commit_after>
angular.module('dashboard', ['ngAnimate', 'ui.bootstrap'])
    .controller('DashboardController', function($scope,$uibModal, UserFactory,moment) {
        $scope.locations = (UserFactory.currentUser.data.locations !== undefined) ?
          UserFactory.currentUser.data.locations : [];

        $scope.addbar = {
            text: '',
            placeholder: 'Add location'
        };

        $scope.currentLocation = $scope.locations[0];
        $scope.currentReservations = [];

        // $scope.currentRoom = [];

        //change the drop down and sets the selected room in scope
        $(".main").on('click', ".dropdown-menu#room li a", function() {
            $scope.roomInput = this.text

            $(this).parents(".dropdown").find('.btn').html($(this).text() + ' ');
            $(this).parents(".dropdown").find('.btn').val($(this).data('value'));
        });

        //change the drop down and sets the selected time in scope
        $(".main").on('click', ".dropdown-menu#time li a", function() {
            $scope.timeInput = this.text
            $(this).parents(".dropdown").find('.btn').html($(this).text() + ' ');
            $(this).parents(".dropdown").find('.btn').val($(this).data('value'));
        });

        $scope.roomInput = ""
        $scope.calendarInput = ""
        $scope.timeInput = ""
        $scope.resDescInput = ""
        $scope.confirmReservation = function(){
            var date =  $scope.eve.eventDate
            var formatted = moment(date).format('DD/MM/YYYY');
            // $scope.calendarInput = $scope.eve.eventDate || ""

            var timeFormatted = function(time){
                var momentObj = moment(time, ["h:mm A"])
                var formattedTime = momentObj.format("HH:mm")
                return formattedTime
            }

            var AddHour = function(time){
                var momentObj = moment(time, ["h:mm A"])
                var newHour = momentObj.add(1,'hour')
                var formattedTime = momentObj.format("HH:mm")
                return formattedTime
            }

            var startTime = timeFormatted($scope.timeInput)
            var endTime = AddHour($scope.timeInput)
            var reservationName = $scope.resDescInput
            var roomId = $scope.roomInput

            // console.log($scope.resDescInput)
            // console.log($scope.roomInput)
            // console.log(formatted)
            // console.log($scope.currentLocation.locationName)
            // console.log($scope.timeInput)

             // console.log(endTime)
            // UserFactory.addReservation(locId,roomId,startTime,endTime,reservationName)
        }

        $scope.selectedLocation = function(index) {
            $scope.currentReservations = []
            $scope.currentLocation = $scope.locations[index]
            console.log($scope.currentLocation)

            console.log("was run")
            angular.forEach($scope.currentLocation.rooms, function(index) {
                console.log("reservations: ", index)
                angular.forEach(index.reservations, function(index) {
                    console.log("index: ", index)
                    $scope.currentReservations.push(index)
                })
            })
        }

        $scope.addLocation = function() {
            UserFactory.addLocation($scope.addbar.text)
                .then(function(location) {
                    console.log('location: ', location);

                    $scope.locations.push(location);
                    $scope.addbar.text = '';
                    //$scope.alerts.push({type: 'success', msg: 'Your preferences have been saved!'});
                })
                .catch(function(error) {
                    //$scope.alerts.push({type: 'danger', msg: 'Error saving preferences.'});
                    console.error('Error adding location: ', error);
                });
        };

        $scope.open = function (size) {
          var modalInstance = $uibModal.open({
                animation: $scope.animationsEnabled,
                templateUrl: 'addModal.html',
                controller: 'DashboardController',
                size: size
            });
            $scope.addLocation();
        };

        $scope.openCal = function(){
          $scope.popupCal.opened = true;
        };

        $scope.popupCal = {
          opened: false
        };

        $scope.addUserInput = "";
        $scope.addRoomInput = "";

        $scope.addRoomsUsers = function(){
          var usersList = $scope.addUserInput.split(',');
          var roomsList = $scope.addRoomInput.split(',');

          UserFactory.addRoomsAndUsers($scope.currentLocation.id, usersList, roomsList);
        }
    });
<|endoftext|>


<commit_before>/* global BackboneWizard, Marionette, Backbone, $ */

window.BackboneWizard = {};

var app = new Marionette.Application();

app.addRegions({
    wizard: '#wizard'
});

app.addInitializer(function () {
    BackboneWizard.itemList = new app.Collections.ItemList();
    BackboneWizard.transaction = new app.Models.Transaction();
    BackboneWizard.state = 'index';

    $.get('./appData.json').done(function (data) {
        BackboneWizard.transaction.set(data);
    });

    $.get('./itemData.json').done(function (data) {
        BackboneWizard.itemList.add(data, { merge: true });
    });

    BackboneWizard.wizardController = new app.Controllers.WizardController();

    BackboneWizard.wizardRouter = new app.Routers.WizardRouter({
        controller: BackboneWizard.wizardController
    });

    Backbone.history.start();
});
<commit_msg>Remove controller from the global namespace.<commit_after>/* global BackboneWizard, Marionette, Backbone, $ */

window.BackboneWizard = {};

var app = new Marionette.Application();

app.addRegions({
    wizard: '#wizard'
});

app.addInitializer(function () {
    var wizardController = new app.Controllers.WizardController();

    BackboneWizard.itemList = new app.Collections.ItemList();
    BackboneWizard.transaction = new app.Models.Transaction();
    BackboneWizard.state = 'index';

    $.get('./appData.json').done(function (data) {
        BackboneWizard.transaction.set(data);
    });

    $.get('./itemData.json').done(function (data) {
        BackboneWizard.itemList.add(data, { merge: true });
    });

    BackboneWizard.wizardRouter = new app.Routers.WizardRouter({
        controller: wizardController
    });

    Backbone.history.start();
});
<|endoftext|>