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

const templateUtil = require('./template-util')
const queryConfig = require('../db/query-config.js')
const queryZcl = require('../db/query-zcl.js')
const bin = require('../util/bin.js')
const types = require('../util/types.js')

/**
 * Returns number of endpoint types.
 *
 * @param {*} options
 * @returns number of endpoint types
 */
function endpoint_type_count(options) {
  return this.endpointTypes.length
}
/**
 * Returns number of endpoints.
 *
 * @param {*} options
 * @returns number of endpoints
 */
function endpoint_count(options) {
  return this.endpoints.length
}
/**
 * Creates array of endpointId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_endpoint_array(options) {
  var epIds = []
  this.endpoints.forEach((ep) => {
    epIds.push('0x' + bin.int16ToHex(ep.endpointId))
  })
  return '{ ' + epIds.join(', ') + ' }'
}

/**
 * Creates array of profileId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_profile_id_array(options) {
  var profileIds = []
  this.endpoints.forEach((ep) => {
    profileIds.push('0x' + bin.int16ToHex(parseInt(ep.profileId)))
  })
  return '{ ' + profileIds.join(', ') + ' }'
}

/**
 * Creates array of networkId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_network_array(options) {
  return '{ ' + this.endpoints.map((ep) => ep.networkId).join(', ') + ' }'
}

/**
 * Each element of an array contains an index into the
 * endpoint type array, for the appropriate endpoint.
 *
 * @param {*} options
 * @returns C array of indexes, one for each endpoint.
 */
function endpoint_fixed_endpoint_type_array(options) {
  var indexes = []
  for (var i = 0; i < this.endpoints.length; i++) {
    var epType = this.endpoints[i].endpointTypeRef
    var index = -1
    for (var j = 0; j < this.endpointTypes.length; j++) {
      if (epType == this.endpointTypes[j].id) {
        index = j
      }
    }
    indexes.push(index)
  }
  return '{ ' + indexes.join(', ') + ' }'
}

function createMfgCodes(codeIndexPairs) {
  var ret = '{ \\ \n'
  if (codeIndexPairs.length == 0) {
    ret = ret.concat('  { 0x00, 0x00 } \\\n')
  } else {
    codeIndexPairs.forEach((c) => {
      ret = ret.concat(`  { ${c.index}, ${c.mfgCode} }\\\n`)
    })
  }
  return ret.concat('}\n')
}

/**
 * Generates array of { index , mfgCode } pairs, matching
 * the indexes in attribute table.
 *
 * @param {*} options
 * @returns manufacturer code array
 */
function endpoint_attribute_manufacturer_codes(options) {
  return createMfgCodes(this.attributeMfgCodes)
}

function endpoint_attribute_manufacturer_code_count(options) {
  return this.attributeMfgCodes.length
}

function endpoint_command_manufacturer_codes(options) {
  return createMfgCodes(this.commandMfgCodes)
}

function endpoint_command_manufacturer_code_count(options) {
  return this.commandMfgCodes.length
}

function endpoint_cluster_manufacturer_codes(options) {
  return createMfgCodes(this.clusterMfgCodes)
}

function endpoint_cluster_manufacturer_code_count(options) {
  return this.clusterMfgCodes.length
}

function endpoint_largest_attribute_size(options) {
  return this.largestAttribute
}

function endpoint_singletons_size(options) {
  return this.singletonsSize
}

function endpoint_total_storage_size(options) {
  return this.totalAttributeSize
}

function endpoint_command_count(options) {
  return this.commandList.length
}

function endpoint_types_list(options) {
  var ret = '{ \\ \n'
  this.endpointList.forEach((ep) => {
    ret = ret.concat(
      `  { ZAP_CLUSTER_INDEX(${ep.clusterIndex}), ${ep.clusterCount}, ${ep.attributeSize} } \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_cluster_list(options) {
  var ret = '{ \\ \n'
  this.clusterList.forEach((c) => {
    ret = ret.concat(
      `  { ${c.clusterId}, ZAP_ATTRIBUTE_INDEX(${c.attributeIndex}), ${c.attributeCount}, ${c.mask}, ${c.functions} } /* ${c.comment} */ \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_command_list(options) {
  var ret = '{ \\ \n'
  this.commandList.forEach((cmd) => {
    ret = ret.concat(
      `  { ${cmd.clusterId}, ${cmd.commandId}, ${cmd.mask} } \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_attribute_list(options) {
  var ret = '{ \\ \n'
  this.attributeList.forEach((at) => {
    ret = ret.concat(
      `  { ${at.id}, ${at.type}, ${at.size}, ${at.mask}, ${at.defaultValue} } \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_fixed_device_id_array(options) {
  return (
    '{ ' + this.deviceList.map((device) => device.deviceId).join(', ') + ' }'
  )
}

function endpoint_fixed_device_version_array(options) {
  return (
    '{ ' +
    this.deviceList.map((device) => device.deviceVersion).join(', ') +
    ' }'
  )
}

////////////////////////////////////////////////////////////////

function endpoint_attribute_min_max_storage(options) {
  var ret = '// TODO: ' + options.name + '\n'
  this.attributes.forEach((at) => {
    ret = ret.concat(`min max: ${at.name} \n`)
  })
  return ret
}

function endpoint_attribute_long_defaults(options) {
  var littleEndian = true
  if (options.hash.endian == 'big') {
    littleEndian = false
  }
  var ret = '// TODO: ' + options.name + '\n'
  this.attributes.forEach((at) => {
    var def = at.defaultValue
    var cBytes = bin.hexToCBytes(def)
    ret = ret.concat(`${cBytes} \n`)
  })
  return ret
}

function endpoint_reporting_config_defaults(options) {
  var ret = '// TODO: ' + options.name + '\n'
  return ret
}

function endpoint_reporting_config_default_count(options) {
  var ret = '// TODO: ' + options.name
  return ret
}

/**
 * Attribute collection works like this:
 *    1.) Go over all the clusters that exist.
 *    2.) If client is included on at least one endpoint add client atts.
 *    3.) If server is included on at least one endpoint add server atts.
 */
function collectAttributes(endpointTypes) {
  var commandMfgCodes = [] // Array of { index, mfgCode } objects
  var clusterMfgCodes = [] // Array of { index, mfgCode } objects
  var attributeMfgCodes = [] // Array of { index, mfgCode } objects
  var attributeList = []
  var commandList = []
  var endpointList = [] // Array of { clusterIndex, clusterCount, attributeSize }
  var clusterList = []
  var longDefaults = []
  var longDefaultsIndex = 0
  var largestAttribute = 0
  var singletonsSize = 0
  var totalAttributeSize = 0
  var clusterIndex = 0
  var deviceList = []

  endpointTypes.forEach((ept) => {
    var endpoint = {
      clusterIndex: clusterIndex,
      clusterCount: 0,
      attributeSize: 0,
    }

    var device = {
      deviceId: 0,
      deviceVersion: 1,
    }

    deviceList.push(device)
    endpointList.push(endpoint)

    var clusterCount = 0
    // Go over all the clusters in the endpoint and add them to the list.
    ept.clusters.forEach((c) => {
      var cluster = {
        clusterId: 0,
        attributeIndex: 0,
        attributeCount: 0,
        mask: 0,
        functions: 'NULL',
        comment: `Endpoint: ${ept.endpointId}, Cluster: ${c.clusterRef}`,
      }
      clusterList.push(cluster)
      clusterIndex++
      clusterCount++
    })
    endpoint.clusterCount = clusterCount

    // Go over the commands
    ept.commands.forEach((cmd) => {
      var cmd = {
        clusterId: 0,
        commandId: cmd.id,
        mask: 0,
      }
      commandList.push(cmd)
    })

    // Go over all the attributes in the endpoint and add them to the list.
    ept.attributes.forEach((a) => {
      if (a.attribute == null) return
      var defaultValue = 0
      if (a.typeSize > 2) {
        // We will need to generate the GENERATED_DEFAULTS
        defaultValue = `ZAP_LONG_DEFAULTS_INDEX(${longDefaultsIndex})`
        longDefaults.push(a)
        longDefaultsIndex += a.typeSize
      }
      if (a.typeSize > largestAttribute) {
        largestAttribute = a.typeSize
      }
      if (a.isSingleton) {
        singletonsSize += a.typeSize
      }
      totalAttributeSize += a.typeSize
      attributeList.push({
        id: a.attribute.code, // attribute code
        type: `ZAP_TYPE(${a.attribute.type.toUpperCase()})`, // type
        size: a.typeSize, // size
        mask: [], // array of special properties
        defaultValue: defaultValue, // default value, pointer to default value, or pointer to min/max/value triplet.
      })
    })
  })
  return Promise.resolve({
    endpointList: endpointList,
    clusterList: clusterList,
    attributeList: attributeList,
    commandList: commandList,
    longDefaults: longDefaults,
    clusterMfgCodes: clusterMfgCodes,
    commandMfgCodes: commandMfgCodes,
    attributeMfgCodes: attributeMfgCodes,
    largestAttribute: largestAttribute,
    singletonsSize: singletonsSize,
    totalAttributeSize: totalAttributeSize,
    deviceList: deviceList,
  })
}

/**
 * Starts the endpoint configuration block.,
 * longDefaults: longDefaults
 *
 * @param {*} options
 * @returns a promise of a rendered block
 */
function endpoint_config(options) {
  var newContext = {
    global: this.global,
    parent: this,
  }
  var db = this.global.db
  var sessionId = this.global.sessionId
  var promise = templateUtil
    .ensureZclPackageId(newContext)
    .then(() => queryConfig.getAllEndpoints(db, sessionId))
    .then((endpoints) => {
      newContext.endpoints = endpoints
      var endpointTypeIds = []
      endpoints.forEach((ep) => {
        endpointTypeIds.push(ep.endpointTypeRef)
      })
      return endpointTypeIds
    })
    .then((endpointTypeIds) => {
      var endpointTypePromises = []
      endpointTypeIds.forEach((eptId) => {
        endpointTypePromises.push(queryConfig.getEndpointType(db, eptId))
      })
      return Promise.all(endpointTypePromises)
    })
    .then((endpointTypes) => {
      var promises = []
      newContext.endpointTypes = endpointTypes
      endpointTypes.forEach((ept) => {
        var id = ept.id
        promises.push(
          queryConfig
            .getEndpointTypeAttributes(db, id)
            .then((attributes) => (ept.attributes = attributes))
            .then((attributes) => {
              var ps = []
              attributes.forEach((at) => {
                if (at.isIncluded) {
                  ps.push(
                    queryZcl
                      .selectAttributeById(db, at.attributeId)
                      .then((a) => (at.attribute = a))
                      .then((a) => {
                        if (a)
                          return types.typeSize(
                            db,
                            newContext.global.zclPackageId,
                            a.type
                          )
                        else return null
                      })
                      .then((size) => (at.typeSize = size))
                  )
                }
              })
              return Promise.all(ps)
            })
        )
        promises.push(
          queryConfig
            .getEndpointTypeCommands(db, id)
            .then((commands) => (ept.commands = commands))
        )
        promises.push(
          queryConfig.getEndpointTypeClusters(db, id).then((clusters) => {
            ept.clusters = clusters.filter((c) => c.enabled)
          })
        )
        promises.push(
          queryConfig.getEndpointTypeCommands(db, id).then((commands) => {
            ept.commands = commands
          })
        )
      })
      return Promise.all(promises).then(() => endpointTypes)
    })
    .then((endpointTypes) => collectAttributes(endpointTypes))
    .then((collection) => {
      Object.assign(newContext, collection)
    })
    .then(() =>
      queryConfig.getAllSessionAttributes(this.global.db, this.global.sessionId)
    )
    .then((atts) => {
      newContext.attributes = atts // TODO: Put attributes into the context
    })
    .then(() => options.fn(newContext))
  return templateUtil.templatePromise(this.global, promise)
}

exports.endpoint_attribute_long_defaults = endpoint_attribute_long_defaults
exports.endpoint_config = endpoint_config
exports.endpoint_attribute_min_max_storage = endpoint_attribute_min_max_storage
exports.endpoint_attribute_list = endpoint_attribute_list
exports.endpoint_cluster_list = endpoint_cluster_list
exports.endpoint_types_list = endpoint_types_list
exports.endpoint_type_count = endpoint_type_count
exports.endpoint_cluster_manufacturer_codes = endpoint_cluster_manufacturer_codes
exports.endpoint_cluster_manufacturer_code_count = endpoint_cluster_manufacturer_code_count
exports.endpoint_command_manufacturer_codes = endpoint_command_manufacturer_codes
exports.endpoint_command_manufacturer_code_count = endpoint_command_manufacturer_code_count
exports.endpoint_attribute_manufacturer_codes = endpoint_attribute_manufacturer_codes
exports.endpoint_attribute_manufacturer_code_count = endpoint_attribute_manufacturer_code_count
exports.endpoint_largest_attribute_size = endpoint_largest_attribute_size
exports.endpoint_total_storage_size = endpoint_total_storage_size
exports.endpoint_singletons_size = endpoint_singletons_size
exports.endpoint_fixed_endpoint_array = endpoint_fixed_endpoint_array
exports.endpoint_fixed_endpoint_type_array = endpoint_fixed_endpoint_type_array
exports.endpoint_fixed_device_id_array = endpoint_fixed_device_id_array
exports.endpoint_fixed_device_version_array = endpoint_fixed_device_version_array
exports.endpoint_fixed_profile_id_array = endpoint_fixed_profile_id_array
exports.endpoint_fixed_network_array = endpoint_fixed_network_array
exports.endpoint_command_list = endpoint_command_list
exports.endpoint_command_count = endpoint_command_count
exports.endpoint_reporting_config_defaults = endpoint_reporting_config_defaults
exports.endpoint_reporting_config_default_count = endpoint_reporting_config_default_count
exports.endpoint_count = endpoint_count
<commit_msg>Add more comments.<commit_after>/**
 *
 *    Copyright (c) 2020 Silicon Labs
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

const templateUtil = require('./template-util')
const queryConfig = require('../db/query-config.js')
const queryZcl = require('../db/query-zcl.js')
const bin = require('../util/bin.js')
const types = require('../util/types.js')

/**
 * Returns number of endpoint types.
 *
 * @param {*} options
 * @returns number of endpoint types
 */
function endpoint_type_count(options) {
  return this.endpointTypes.length
}
/**
 * Returns number of endpoints.
 *
 * @param {*} options
 * @returns number of endpoints
 */
function endpoint_count(options) {
  return this.endpoints.length
}
/**
 * Creates array of endpointId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_endpoint_array(options) {
  var epIds = []
  this.endpoints.forEach((ep) => {
    epIds.push('0x' + bin.int16ToHex(ep.endpointId))
  })
  return '{ ' + epIds.join(', ') + ' }'
}

/**
 * Creates array of profileId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_profile_id_array(options) {
  var profileIds = []
  this.endpoints.forEach((ep) => {
    profileIds.push('0x' + bin.int16ToHex(parseInt(ep.profileId)))
  })
  return '{ ' + profileIds.join(', ') + ' }'
}

/**
 * Creates array of networkId fields on endpoints
 *
 * @param {*} options
 * @returns C array including the { } brackets
 */
function endpoint_fixed_network_array(options) {
  return '{ ' + this.endpoints.map((ep) => ep.networkId).join(', ') + ' }'
}

/**
 * Each element of an array contains an index into the
 * endpoint type array, for the appropriate endpoint.
 *
 * @param {*} options
 * @returns C array of indexes, one for each endpoint.
 */
function endpoint_fixed_endpoint_type_array(options) {
  var indexes = []
  for (var i = 0; i < this.endpoints.length; i++) {
    var epType = this.endpoints[i].endpointTypeRef
    var index = -1
    for (var j = 0; j < this.endpointTypes.length; j++) {
      if (epType == this.endpointTypes[j].id) {
        index = j
      }
    }
    indexes.push(index)
  }
  return '{ ' + indexes.join(', ') + ' }'
}

function createMfgCodes(codeIndexPairs) {
  var ret = '{ \\ \n'
  if (codeIndexPairs.length == 0) {
    ret = ret.concat('  { 0x00, 0x00 } \\\n')
  } else {
    codeIndexPairs.forEach((c) => {
      ret = ret.concat(`  { ${c.index}, ${c.mfgCode} }\\\n`)
    })
  }
  return ret.concat('}\n')
}

/**
 * Generates array of { index , mfgCode } pairs, matching
 * the indexes in attribute table.
 *
 * @param {*} options
 * @returns manufacturer code array
 */
function endpoint_attribute_manufacturer_codes(options) {
  return createMfgCodes(this.attributeMfgCodes)
}

function endpoint_attribute_manufacturer_code_count(options) {
  return this.attributeMfgCodes.length
}

function endpoint_command_manufacturer_codes(options) {
  return createMfgCodes(this.commandMfgCodes)
}

function endpoint_command_manufacturer_code_count(options) {
  return this.commandMfgCodes.length
}

function endpoint_cluster_manufacturer_codes(options) {
  return createMfgCodes(this.clusterMfgCodes)
}

function endpoint_cluster_manufacturer_code_count(options) {
  return this.clusterMfgCodes.length
}

function endpoint_largest_attribute_size(options) {
  return this.largestAttribute
}

function endpoint_singletons_size(options) {
  return this.singletonsSize
}

function endpoint_total_storage_size(options) {
  return this.totalAttributeSize
}

function endpoint_command_count(options) {
  return this.commandList.length
}

function endpoint_types_list(options) {
  var ret = '{ \\ \n'
  this.endpointList.forEach((ep) => {
    ret = ret.concat(
      `  { ZAP_CLUSTER_INDEX(${ep.clusterIndex}), ${ep.clusterCount}, ${ep.attributeSize} } \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_cluster_list(options) {
  var ret = '{ \\ \n'
  this.clusterList.forEach((c) => {
    ret = ret.concat(
      `  { ${c.clusterId}, ZAP_ATTRIBUTE_INDEX(${c.attributeIndex}), ${c.attributeCount}, ${c.mask}, ${c.functions} } /* ${c.comment} */ \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_command_list(options) {
  var ret = '{ \\ \n'
  this.commandList.forEach((cmd) => {
    ret = ret.concat(
      `  { ${cmd.clusterId}, ${cmd.commandId}, ${cmd.mask} } /* ${cmd.comment} */ \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_attribute_list(options) {
  var ret = '{ \\ \n'
  this.attributeList.forEach((at) => {
    ret = ret.concat(
      `  { ${at.id}, ${at.type}, ${at.size}, ${at.mask}, ${at.defaultValue} } /* ${at.comment} */  \\\n`
    )
  })
  return ret.concat('}\n')
}

function endpoint_fixed_device_id_array(options) {
  return (
    '{ ' + this.deviceList.map((device) => device.deviceId).join(', ') + ' }'
  )
}

function endpoint_fixed_device_version_array(options) {
  return (
    '{ ' +
    this.deviceList.map((device) => device.deviceVersion).join(', ') +
    ' }'
  )
}

////////////////////////////////////////////////////////////////

function endpoint_attribute_min_max_storage(options) {
  var ret = '// TODO: ' + options.name + '\n'
  this.attributes.forEach((at) => {
    ret = ret.concat(`min max: ${at.name} \n`)
  })
  return ret
}

function endpoint_attribute_long_defaults(options) {
  var littleEndian = true
  if (options.hash.endian == 'big') {
    littleEndian = false
  }
  var ret = '// TODO: ' + options.name + '\n'
  this.attributes.forEach((at) => {
    var def = at.defaultValue
    var cBytes = bin.hexToCBytes(def)
    ret = ret.concat(`${cBytes} \n`)
  })
  return ret
}

function endpoint_reporting_config_defaults(options) {
  var ret = '// TODO: ' + options.name + '\n'
  return ret
}

function endpoint_reporting_config_default_count(options) {
  var ret = '// TODO: ' + options.name
  return ret
}

/**
 * Attribute collection works like this:
 *    1.) Go over all the clusters that exist.
 *    2.) If client is included on at least one endpoint add client atts.
 *    3.) If server is included on at least one endpoint add server atts.
 */
function collectAttributes(endpointTypes) {
  var commandMfgCodes = [] // Array of { index, mfgCode } objects
  var clusterMfgCodes = [] // Array of { index, mfgCode } objects
  var attributeMfgCodes = [] // Array of { index, mfgCode } objects
  var attributeList = []
  var commandList = []
  var endpointList = [] // Array of { clusterIndex, clusterCount, attributeSize }
  var clusterList = [] // Array of { clusterId, attributeIndex, attributeCount, mask, functions, comment }
  var longDefaults = [] // Array of strings representing bytes
  var longDefaultsIndex = 0
  var largestAttribute = 0
  var singletonsSize = 0
  var totalAttributeSize = 0
  var clusterIndex = 0
  var deviceList = [] // Array of { deviceId, deviceVersion }
  var mimMaxList = []

  endpointTypes.forEach((ept) => {
    var endpoint = {
      clusterIndex: clusterIndex,
      clusterCount: 0,
      attributeSize: 0,
    }

    var device = {
      deviceId: 0,
      deviceVersion: 1,
    }

    deviceList.push(device)
    endpointList.push(endpoint)

    var clusterCount = 0
    // Go over all the clusters in the endpoint and add them to the list.
    ept.clusters.forEach((c) => {
      var cluster = {
        clusterId: 0,
        attributeIndex: 0,
        attributeCount: 0,
        mask: 0,
        functions: 'NULL',
        comment: `Endpoint: ${ept.endpointId}, Cluster: ${c.clusterRef}`,
      }
      clusterList.push(cluster)
      clusterIndex++
      clusterCount++
    })
    endpoint.clusterCount = clusterCount

    // Go over the commands
    ept.commands.forEach((cmd) => {
      var cmd = {
        clusterId: 0,
        commandId: cmd.id,
        mask: 0,
        comment: 'Command',
      }
      commandList.push(cmd)
    })

    // Go over all the attributes in the endpoint and add them to the list.
    ept.attributes.forEach((a) => {
      if (a.attribute == null) return
      var defaultValue = 0
      if (a.typeSize > 2) {
        // We will need to generate the GENERATED_DEFAULTS
        defaultValue = `ZAP_LONG_DEFAULTS_INDEX(${longDefaultsIndex})`
        longDefaults.push(a)
        longDefaultsIndex += a.typeSize
      }
      if (a.typeSize > largestAttribute) {
        largestAttribute = a.typeSize
      }
      if (a.isSingleton) {
        singletonsSize += a.typeSize
      }
      totalAttributeSize += a.typeSize
      attributeList.push({
        id: a.attribute.code, // attribute code
        type: `ZAP_TYPE(${a.attribute.type.toUpperCase()})`, // type
        size: a.typeSize, // size
        mask: [], // array of special properties
        defaultValue: defaultValue, // default value, pointer to default value, or pointer to min/max/value triplet.
        comment: `${a.attribute.label}`,
      })
    })
  })
  return Promise.resolve({
    endpointList: endpointList,
    clusterList: clusterList,
    attributeList: attributeList,
    commandList: commandList,
    longDefaults: longDefaults,
    clusterMfgCodes: clusterMfgCodes,
    commandMfgCodes: commandMfgCodes,
    attributeMfgCodes: attributeMfgCodes,
    largestAttribute: largestAttribute,
    singletonsSize: singletonsSize,
    totalAttributeSize: totalAttributeSize,
    deviceList: deviceList,
  })
}

/**
 * Starts the endpoint configuration block.,
 * longDefaults: longDefaults
 *
 * @param {*} options
 * @returns a promise of a rendered block
 */
function endpoint_config(options) {
  var newContext = {
    global: this.global,
    parent: this,
  }
  var db = this.global.db
  var sessionId = this.global.sessionId
  var promise = templateUtil
    .ensureZclPackageId(newContext)
    .then(() => queryConfig.getAllEndpoints(db, sessionId))
    .then((endpoints) => {
      newContext.endpoints = endpoints
      var endpointTypeIds = []
      endpoints.forEach((ep) => {
        endpointTypeIds.push(ep.endpointTypeRef)
      })
      return endpointTypeIds
    })
    .then((endpointTypeIds) => {
      var endpointTypePromises = []
      endpointTypeIds.forEach((eptId) => {
        endpointTypePromises.push(queryConfig.getEndpointType(db, eptId))
      })
      return Promise.all(endpointTypePromises)
    })
    .then((endpointTypes) => {
      var promises = []
      newContext.endpointTypes = endpointTypes
      endpointTypes.forEach((ept) => {
        var id = ept.id
        promises.push(
          queryConfig
            .getEndpointTypeAttributes(db, id)
            .then((attributes) => (ept.attributes = attributes))
            .then((attributes) => {
              var ps = []
              attributes.forEach((at) => {
                if (at.isIncluded) {
                  ps.push(
                    queryZcl
                      .selectAttributeById(db, at.attributeId)
                      .then((a) => (at.attribute = a))
                      .then((a) => {
                        if (a)
                          return types.typeSize(
                            db,
                            newContext.global.zclPackageId,
                            a.type
                          )
                        else return null
                      })
                      .then((size) => (at.typeSize = size))
                  )
                }
              })
              return Promise.all(ps)
            })
        )
        promises.push(
          queryConfig
            .getEndpointTypeCommands(db, id)
            .then((commands) => (ept.commands = commands))
        )
        promises.push(
          queryConfig.getEndpointTypeClusters(db, id).then((clusters) => {
            ept.clusters = clusters.filter((c) => c.enabled)
          })
        )
        promises.push(
          queryConfig.getEndpointTypeCommands(db, id).then((commands) => {
            ept.commands = commands
          })
        )
      })
      return Promise.all(promises).then(() => endpointTypes)
    })
    .then((endpointTypes) => collectAttributes(endpointTypes))
    .then((collection) => {
      Object.assign(newContext, collection)
    })
    .then(() =>
      queryConfig.getAllSessionAttributes(this.global.db, this.global.sessionId)
    )
    .then((atts) => {
      newContext.attributes = atts // TODO: Put attributes into the context
    })
    .then(() => options.fn(newContext))
  return templateUtil.templatePromise(this.global, promise)
}

exports.endpoint_attribute_long_defaults = endpoint_attribute_long_defaults
exports.endpoint_config = endpoint_config
exports.endpoint_attribute_min_max_storage = endpoint_attribute_min_max_storage
exports.endpoint_attribute_list = endpoint_attribute_list
exports.endpoint_cluster_list = endpoint_cluster_list
exports.endpoint_types_list = endpoint_types_list
exports.endpoint_type_count = endpoint_type_count
exports.endpoint_cluster_manufacturer_codes = endpoint_cluster_manufacturer_codes
exports.endpoint_cluster_manufacturer_code_count = endpoint_cluster_manufacturer_code_count
exports.endpoint_command_manufacturer_codes = endpoint_command_manufacturer_codes
exports.endpoint_command_manufacturer_code_count = endpoint_command_manufacturer_code_count
exports.endpoint_attribute_manufacturer_codes = endpoint_attribute_manufacturer_codes
exports.endpoint_attribute_manufacturer_code_count = endpoint_attribute_manufacturer_code_count
exports.endpoint_largest_attribute_size = endpoint_largest_attribute_size
exports.endpoint_total_storage_size = endpoint_total_storage_size
exports.endpoint_singletons_size = endpoint_singletons_size
exports.endpoint_fixed_endpoint_array = endpoint_fixed_endpoint_array
exports.endpoint_fixed_endpoint_type_array = endpoint_fixed_endpoint_type_array
exports.endpoint_fixed_device_id_array = endpoint_fixed_device_id_array
exports.endpoint_fixed_device_version_array = endpoint_fixed_device_version_array
exports.endpoint_fixed_profile_id_array = endpoint_fixed_profile_id_array
exports.endpoint_fixed_network_array = endpoint_fixed_network_array
exports.endpoint_command_list = endpoint_command_list
exports.endpoint_command_count = endpoint_command_count
exports.endpoint_reporting_config_defaults = endpoint_reporting_config_defaults
exports.endpoint_reporting_config_default_count = endpoint_reporting_config_default_count
exports.endpoint_count = endpoint_count
<|endoftext|>


<commit_before>// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
<commit_msg>Linting - missing ;<commit_after>// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')
<|endoftext|>


<commit_before>angular.module('dogfeed', ['ngRSS']).

/**
 * config: routes
 */
config(['$routeProvider',
function ($routeProvider) {
  $routeProvider.
    when('/', {
      templateUrl: "feeds.html"
    }).
    otherwise({
      redirectTo: "/"
    });
}]).

/**
 * emitters
 */
run(['$rootScope',
function ($rootScope) {
  $rootScope.$on('showModalAddFeed', function(event, args) {
    backdrop_setting = true;
    if ((typeof args === 'object') && (typeof args.locked !== 'undefined')) {
      if (args.locked) {
        backdrop_setting = "static";
      }
    }
    $("#modalAddFeed").modal({
      show: true,
      keyboard: true,
      backdrop: backdrop_setting
    });
  });

  $rootScope.$on('closeModalAddFeed', function(event, args) {
    $("#modalAddFeed").modal('hide');
  });
}]).

/**
 * filter: urlEncode
 */
filter('urlEncode', [
function() {
  return function (text, length, end) {
    return encodeURIComponent(escape(text));
  };
}]).

///////////////////////////////////////////////////////////////////////////
//
// CONTROLLERS
//
///////////////////////////////////////////////////////////////////////////

/**
 * controller: titlebarCtrl
 */
controller('titlebarCtrl',
['$scope', '$rootScope',
function ($scope, $rootScope) {
  $scope.addFeed = function () {
    $rootScope.$broadcast('showModalAddFeed', {locked: false});
  };
}]).

///////////////////////////////////////////////////////////////////////////
//
// DIRECTIVES
//
///////////////////////////////////////////////////////////////////////////

/**
 * directive: message
 */
directive('message',
['$rootScope', '$timeout',
function ($rootScope, $timeout) {
  return {
    restrict: 'A',
    template: '
'+
              '  {{m.title}} ' +
              '  {{m.message}}' +
              '
',
    link: function (scope) {
      scope.haveMessage = false;
      scope.m = {type: '', title: '', message: ''};

      var presets = {
        'remotestorage-connect': {
          type: 'error',
          title : 'Connect to remoteStorage',
          message: 'First things first. You must connect to your remoteStorage'
        },
        'sockethub-config': {
          type: 'error',
          title: 'Sockethub configuration needed',
          message: 'You must fill in your Sockethub connection details'
        },
        'sockethub-connect': {
          type: 'error',
          title: 'Sockethub connection error',
          message: 'Unable to connect to Sockethub please check your configuration and try again'
        },
        'sockethub-register': {
          type: 'error',
          title: 'Sockethub registration problem',
          message: 'We were unable to register with your Sockethub instance'
        },
        'xmpp-connect': {
          type: 'error',
          title: 'XMPP connection failed',
          message: 'There was a problem connecting to the XMPP server, please verify you settings'
        },
        'unknown': {
          type: 'error',
          title: 'An unknown error has occurred',
          message: ''
        }
      };

      $rootScope.$on('message', function (event, e) {
        console.log('message event: ', e);

        var timeout = (typeof e.timeout === 'boolean') ? e.timeout : true;
        scope.haveMessage = false;

        if (typeof e === 'undefined') {
          e = 'no error specified';
        }

        if (typeof presets[e.message] !== 'undefined') {
          scope.m = presets[e.message];
        } else if (typeof e.message === 'string') {
          if (e.type === 'success') {
            scope.m.title = 'Success';
          } else {
            scope.m.title = "Error";
          }
          scope.m.message = e.message;
          scope.m.type = e.type;
        }
        console.log('done processing: ', scope.m);

        scope.haveMessage = true;
        if (timeout) {
          $timeout(function () {
            scope.haveMessage = false;
            scope.m = {type: '', title: '', message: ''};
          }, 4000);
        }
      });
    }
  };
}]);

<commit_msg>dogfeed now initializes sockethub connect<commit_after>angular.module('dogfeed', ['ngRSS', 'ngSockethubClient']).

/**
 * settings
 */
value('settings', {
  sockethub: function () {
    // figure out sockethub connect settings
    var settings = {
      host: 'localhost',
      port: '10550',
      path: '/sockethub',
      tls: false,
      secret: '1234567890'
    };

    return settings;
  }
}).

/**
 * routes
 */
config(['$routeProvider',
function ($routeProvider) {
  $routeProvider.
    when('/', {
      templateUrl: "feeds.html"
    }).
    otherwise({
      redirectTo: "/"
    });
}]).

/**
 * sockethub connect
 */
run(['settings', 'SH', '$rootScope',
function (settings, SH, $rootScope) {
  var s = settings.sockethub();
  // connect to sockethub and register
  SH.setConfig(s).then(function () {
    return SH.connect();
  }).then(function () {
    return SH.register();
  }).then(function () {
    console.log('connected to sockethub');
  }, function (err) {
    console.log('error connection to sockethub: ', err);
    $rootScope.$broadcast('SockethubConnectFailed', {message: err});
  });
}]).

/**
 * emitters
 */
run(['$rootScope',
function ($rootScope) {
  $rootScope.$on('showModalAddFeed', function(event, args) {
    backdrop_setting = true;
    if ((typeof args === 'object') && (typeof args.locked !== 'undefined')) {
      if (args.locked) {
        backdrop_setting = "static";
      }
    }
    $("#modalAddFeed").modal({
      show: true,
      keyboard: true,
      backdrop: backdrop_setting
    });
  });

  $rootScope.$on('closeModalAddFeed', function(event, args) {
    $("#modalAddFeed").modal('hide');
  });
}]).

/**
 * filter: urlEncode
 */
filter('urlEncode', [
function() {
  return function (text, length, end) {
    return encodeURIComponent(escape(text));
  };
}]).

///////////////////////////////////////////////////////////////////////////
//
// CONTROLLERS
//
///////////////////////////////////////////////////////////////////////////

/**
 * controller: titlebarCtrl
 */
controller('titlebarCtrl',
['$scope', '$rootScope',
function ($scope, $rootScope) {
  $scope.addFeed = function () {
    $rootScope.$broadcast('showModalAddFeed', {locked: false});
  };
}]).

///////////////////////////////////////////////////////////////////////////
//
// DIRECTIVES
//
///////////////////////////////////////////////////////////////////////////

/**
 * directive: message
 */
directive('message',
['$rootScope', '$timeout',
function ($rootScope, $timeout) {
  return {
    restrict: 'A',
    template: '
'+
              '  {{m.title}} ' +
              '  {{m.message}}' +
              '
',
    link: function (scope) {
      scope.haveMessage = false;
      scope.m = {type: '', title: '', message: ''};

      var presets = {
        'remotestorage-connect': {
          type: 'error',
          title : 'Connect to remoteStorage',
          message: 'First things first. You must connect to your remoteStorage'
        },
        'sockethub-config': {
          type: 'error',
          title: 'Sockethub configuration needed',
          message: 'You must fill in your Sockethub connection details'
        },
        'sockethub-connect': {
          type: 'error',
          title: 'Sockethub connection error',
          message: 'Unable to connect to Sockethub please check your configuration and try again'
        },
        'sockethub-register': {
          type: 'error',
          title: 'Sockethub registration problem',
          message: 'We were unable to register with your Sockethub instance'
        },
        'xmpp-connect': {
          type: 'error',
          title: 'XMPP connection failed',
          message: 'There was a problem connecting to the XMPP server, please verify you settings'
        },
        'unknown': {
          type: 'error',
          title: 'An unknown error has occurred',
          message: ''
        }
      };

      $rootScope.$on('message', function (event, e) {
        console.log('message event: ', e);

        var timeout = (typeof e.timeout === 'boolean') ? e.timeout : true;
        scope.haveMessage = false;

        if (typeof e === 'undefined') {
          e = 'no error specified';
        }

        if (typeof presets[e.message] !== 'undefined') {
          scope.m = presets[e.message];
        } else if (typeof e.message === 'string') {
          if (e.type === 'success') {
            scope.m.title = 'Success';
          } else {
            scope.m.title = "Error";
          }
          scope.m.message = e.message;
          scope.m.type = e.type;
        }
        console.log('done processing: ', scope.m);

        scope.haveMessage = true;
        if (timeout) {
          $timeout(function () {
            scope.haveMessage = false;
            scope.m = {type: '', title: '', message: ''};
          }, 4000);
        }
      });
    }
  };
}]);

<|endoftext|>


<commit_before>import { StringUtil } from '../../Components/StringUtil'

class Quote {
  constructor ({data}) {
    this.data = {
      text: data.text,
      author: data.author,
      alignment: (Object.values(this.alignments).includes(data.alignment) && data.alignment) || this.defaultAlignment
    }
    this.settings = [
      {
        name: 'left',
        icon: `<svg width="16" height="11" viewBox="0 0 16 11" xmlns="http://www.w3.org/2000/svg" ><path d="M1.069 0H13.33a1.069 1.069 0 0 1 0 2.138H1.07a1.069 1.069 0 1 1 0-2.138zm0 4.275H9.03a1.069 1.069 0 1 1 0 2.137H1.07a1.069 1.069 0 1 1 0-2.137zm0 4.275h9.812a1.069 1.069 0 0 1 0 2.137H1.07a1.069 1.069 0 0 1 0-2.137z" /></svg>`,
      },
      {
        name: 'center',
        icon: `<svg width="16" height="11" viewBox="0 0 16 11" xmlns="http://www.w3.org/2000/svg" ><path d="M1.069 0H13.33a1.069 1.069 0 0 1 0 2.138H1.07a1.069 1.069 0 1 1 0-2.138zm3.15 4.275h5.962a1.069 1.069 0 0 1 0 2.137H4.22a1.069 1.069 0 1 1 0-2.137zM1.069 8.55H13.33a1.069 1.069 0 0 1 0 2.137H1.07a1.069 1.069 0 0 1 0-2.137z"/></svg>`,
      }
    ]
  }

  static get toolbox () {
    return {
      icon: '<svg width="15" height="14" viewBox="0 0 15 14" xmlns="http://www.w3.org/2000/svg"><path d="M13.53 6.185l.027.025a1.109 1.109 0 0 1 0 1.568l-5.644 5.644a1.109 1.109 0 1 1-1.569-1.568l4.838-4.837L6.396 2.23A1.125 1.125 0 1 1 7.986.64l5.52 5.518.025.027zm-5.815 0l.026.025a1.109 1.109 0 0 1 0 1.568l-5.644 5.644a1.109 1.109 0 1 1-1.568-1.568l4.837-4.837L.58 2.23A1.125 1.125 0 0 1 2.171.64L7.69 6.158l.025.027z" /></svg>',
      title: 'Quote'
    }
  }

  /**
   * Allowed quote alignments
   *
   * @returns {{left: string, center: string}}
   */
  get alignments () {
    return {
      left: 'left',
      center: 'center'
    }
  }

  /**
   * Default quote alignment
   *
   * @returns {string}
   */
  get defaultAlignment () {
    return this.alignments.left
  }

  /**
   * CSS classes
   *
   * @returns {{wrapper: string, wrapperLabel: string, input: string, label: string, settingsWrapper: string, settingsButton: string, settingsButtonActive: string}}
   */
  get CSS () {
    return {
      wrapper: 'ce-wrapper',
      wrapperLabel: 'ce-wrapper-label',
      input: 'ce-input',
      label: 'ce-label',
      settingsWrapper: 'cdx-quote-settings',
      settingsButton: 'ce-settings__button',
      settingsButtonActive: 'cdx-settings-button--active',
    }
  }

  renderSettings () {
    const wrapper = this._make('div')

    this.settings
      .map(tune => {
        const el = this._make('div', this.CSS.settingsButton, {
          innerHTML: tune.icon,
          title: `${tune.name} alignment`
        })

        el.classList.toggle(this.CSS.settingsButtonActive, tune.name === this.data.alignment)

        wrapper.appendChild(el)

        return el
      })
      .forEach((element, index, elements) => {
        element.addEventListener('click', () => {
          this._toggleTune(this.settings[index].name)

          elements.forEach((el, i) => {
            const { name } = this.settings[i]

            el.classList.toggle(this.CSS.settingsButtonActive, name === this.data.alignment)
          })
        })
      })

    return wrapper
  }

  /**
   * Toggle quote`s alignment
   *
   * @param {string} tune - alignment
   * @private
   */
  _toggleTune (tune) {
    this.data.alignment = tune
  }

  render () {
    // wrapper
    const wrapper = this._make('div', this.CSS.wrapper)
    const wrapperContent = this._make('div')
    const wrapperTitle = this._make('label', this.CSS.wrapperLabel,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Quote'))
      }
    )

    // Quote text
    const labelText = this._make('label', this.CSS.label,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Text'))
      }
    )
    const inputText = this._make('textarea', this.CSS.input,
      {
        value: this.data && this.data.text ? this.data.text : '',
        rows: 7
      },
      {
        'data-input-text': ''
      }
    )

    // Quote text
    const labelAuthor = this._make('label', this.CSS.label,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Author'))
      }
    )
    const inputAuthor = this._make('input', this.CSS.input,
      {
        type: 'text',
        value: this.data && this.data.author ? this.data.author : ''
      },
      {
        'data-input-author': ''
      }
    )

    // append to wrapper
    wrapperContent.appendChild(labelText)
    wrapperContent.appendChild(inputText)
    wrapperContent.appendChild(labelAuthor)
    wrapperContent.appendChild(inputAuthor)

    wrapper.appendChild(wrapperTitle)
    wrapper.appendChild(wrapperContent)

    return wrapper
  }

  save (blockContent) {
    const inputText = blockContent.querySelector('[data-input-text]')
    const inputAuthor = blockContent.querySelector('[data-input-author]')

    return Object.assign(this.data, {
      text: inputText.value,
      author: inputAuthor.value
    })
  }

  /**
   * Helper for making Elements with attributes
   *
   * @param  {string} tagName           - new Element tag name
   * @param  {Array|string} classNames  - list or name of CSS classname(s)
   * @param  {object} attributes        - any attributes
   * @returns {Element}
   */
  _make (tagName, classNames = null, attributes = {}, customAttributes = {}) {
    const el = document.createElement(tagName)

    if (Array.isArray(classNames)) {
      el.classList.add(...classNames)
    } else if (classNames) {
      el.classList.add(classNames)
    }

    for (const attrName in attributes) {
      el[attrName] = attributes[attrName]
    }

    for (const attrName in customAttributes) {
      el.setAttribute(attrName, customAttributes[attrName])
    }

    return el
  }
}

export default Quote
<commit_msg>Remove unnecessary commas<commit_after>import { StringUtil } from '../../Components/StringUtil'

class Quote {
  constructor ({data}) {
    this.data = {
      text: data.text,
      author: data.author,
      alignment: (Object.values(this.alignments).includes(data.alignment) && data.alignment) || this.defaultAlignment
    }
    this.settings = [
      {
        name: 'left',
        icon: `<svg width="16" height="11" viewBox="0 0 16 11" xmlns="http://www.w3.org/2000/svg" ><path d="M1.069 0H13.33a1.069 1.069 0 0 1 0 2.138H1.07a1.069 1.069 0 1 1 0-2.138zm0 4.275H9.03a1.069 1.069 0 1 1 0 2.137H1.07a1.069 1.069 0 1 1 0-2.137zm0 4.275h9.812a1.069 1.069 0 0 1 0 2.137H1.07a1.069 1.069 0 0 1 0-2.137z" /></svg>`
      },
      {
        name: 'center',
        icon: `<svg width="16" height="11" viewBox="0 0 16 11" xmlns="http://www.w3.org/2000/svg" ><path d="M1.069 0H13.33a1.069 1.069 0 0 1 0 2.138H1.07a1.069 1.069 0 1 1 0-2.138zm3.15 4.275h5.962a1.069 1.069 0 0 1 0 2.137H4.22a1.069 1.069 0 1 1 0-2.137zM1.069 8.55H13.33a1.069 1.069 0 0 1 0 2.137H1.07a1.069 1.069 0 0 1 0-2.137z"/></svg>`
      }
    ]
  }

  static get toolbox () {
    return {
      icon: '<svg width="15" height="14" viewBox="0 0 15 14" xmlns="http://www.w3.org/2000/svg"><path d="M13.53 6.185l.027.025a1.109 1.109 0 0 1 0 1.568l-5.644 5.644a1.109 1.109 0 1 1-1.569-1.568l4.838-4.837L6.396 2.23A1.125 1.125 0 1 1 7.986.64l5.52 5.518.025.027zm-5.815 0l.026.025a1.109 1.109 0 0 1 0 1.568l-5.644 5.644a1.109 1.109 0 1 1-1.568-1.568l4.837-4.837L.58 2.23A1.125 1.125 0 0 1 2.171.64L7.69 6.158l.025.027z" /></svg>',
      title: 'Quote'
    }
  }

  /**
   * Allowed quote alignments
   *
   * @returns {{left: string, center: string}}
   */
  get alignments () {
    return {
      left: 'left',
      center: 'center'
    }
  }

  /**
   * Default quote alignment
   *
   * @returns {string}
   */
  get defaultAlignment () {
    return this.alignments.left
  }

  /**
   * CSS classes
   *
   * @returns {{wrapper: string, wrapperLabel: string, input: string, label: string, settingsWrapper: string, settingsButton: string, settingsButtonActive: string}}
   */
  get CSS () {
    return {
      wrapper: 'ce-wrapper',
      wrapperLabel: 'ce-wrapper-label',
      input: 'ce-input',
      label: 'ce-label',
      settingsWrapper: 'cdx-quote-settings',
      settingsButton: 'ce-settings__button',
      settingsButtonActive: 'cdx-settings-button--active'
    }
  }

  renderSettings () {
    const wrapper = this._make('div')

    this.settings
      .map(tune => {
        const el = this._make('div', this.CSS.settingsButton, {
          innerHTML: tune.icon,
          title: `${tune.name} alignment`
        })

        el.classList.toggle(this.CSS.settingsButtonActive, tune.name === this.data.alignment)

        wrapper.appendChild(el)

        return el
      })
      .forEach((element, index, elements) => {
        element.addEventListener('click', () => {
          this._toggleTune(this.settings[index].name)

          elements.forEach((el, i) => {
            const { name } = this.settings[i]

            el.classList.toggle(this.CSS.settingsButtonActive, name === this.data.alignment)
          })
        })
      })

    return wrapper
  }

  /**
   * Toggle quote`s alignment
   *
   * @param {string} tune - alignment
   * @private
   */
  _toggleTune (tune) {
    this.data.alignment = tune
  }

  render () {
    // wrapper
    const wrapper = this._make('div', this.CSS.wrapper)
    const wrapperContent = this._make('div')
    const wrapperTitle = this._make('label', this.CSS.wrapperLabel,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Quote'))
      }
    )

    // Quote text
    const labelText = this._make('label', this.CSS.label,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Text'))
      }
    )
    const inputText = this._make('textarea', this.CSS.input,
      {
        value: this.data && this.data.text ? this.data.text : '',
        rows: 7
      },
      {
        'data-input-text': ''
      }
    )

    // Quote text
    const labelAuthor = this._make('label', this.CSS.label,
      {
        innerHTML: StringUtil.ucfirst(window.backend.locale.lbl('Author'))
      }
    )
    const inputAuthor = this._make('input', this.CSS.input,
      {
        type: 'text',
        value: this.data && this.data.author ? this.data.author : ''
      },
      {
        'data-input-author': ''
      }
    )

    // append to wrapper
    wrapperContent.appendChild(labelText)
    wrapperContent.appendChild(inputText)
    wrapperContent.appendChild(labelAuthor)
    wrapperContent.appendChild(inputAuthor)

    wrapper.appendChild(wrapperTitle)
    wrapper.appendChild(wrapperContent)

    return wrapper
  }

  save (blockContent) {
    const inputText = blockContent.querySelector('[data-input-text]')
    const inputAuthor = blockContent.querySelector('[data-input-author]')

    return Object.assign(this.data, {
      text: inputText.value,
      author: inputAuthor.value
    })
  }

  /**
   * Helper for making Elements with attributes
   *
   * @param  {string} tagName           - new Element tag name
   * @param  {Array|string} classNames  - list or name of CSS classname(s)
   * @param  {object} attributes        - any attributes
   * @returns {Element}
   */
  _make (tagName, classNames = null, attributes = {}, customAttributes = {}) {
    const el = document.createElement(tagName)

    if (Array.isArray(classNames)) {
      el.classList.add(...classNames)
    } else if (classNames) {
      el.classList.add(classNames)
    }

    for (const attrName in attributes) {
      el[attrName] = attributes[attrName]
    }

    for (const attrName in customAttributes) {
      el.setAttribute(attrName, customAttributes[attrName])
    }

    return el
  }
}

export default Quote
<|endoftext|>


<commit_before>var MT;
(function () {
    "use strict";

    MT = (function () {
        var initialTime,
            currentTime,
            elapsedTime,
            elapsedTimeHours,
            elapsedTimeMinutes,
            elapsedTimeSeconds,
            timerIsRunning = false,
            attendees = 0,
            salary = 0,
            sum = 0,
            timerDomElement,
            timeDomElement,
            moneyDomElement,
            //playpauseDomElement,
            settingsIconDomElement,
            settingsDomElement,
            inputAttendeesDomElement,
            inputSalaryDomElement,
            inputCurrencyDomElement,
            inputSubmitDomElement,
            settingsAreOpen = true,
            CHARACTERS_CURRENCY = ['€', '$', '£', '¥', '¤'], // EUR, USD, GBP, YEN, CUR
            currencyIndex = 0,
            currentCurrency = CHARACTERS_CURRENCY[currencyIndex],
            timerInterval,
            valueIsHuge = false,

            updateCosts = function () {
                sum = ((attendees * salary * (elapsedTime / 3600000)))
                sum = Math.round(sum * 100) / 100;
                if (sum > 9999 && valueIsHuge === false) {
                    document.querySelector('.money').className += ' money--hugevalue';
                    valueIsHuge = true;
                } else if (sum > 10) {
                    sum = parseInt(sum, 10)
                }
                moneyDomElement.innerHTML = sum.toLocaleString();
            },

            updateTime = function () {
                elapsedTimeSeconds = Math.floor((elapsedTime / 1000) % 60);
                elapsedTimeMinutes = Math.floor((elapsedTime / 60000) % 60);
                elapsedTimeHours = Math.floor((elapsedTime / 1000) / 3600);

                elapsedTimeSeconds = (elapsedTimeSeconds > 9) ? elapsedTimeSeconds : '0' + elapsedTimeSeconds.toString();
                elapsedTimeMinutes = (elapsedTimeMinutes > 9) ? elapsedTimeMinutes : '0' + elapsedTimeMinutes.toString();

                timeDomElement.innerHTML = elapsedTimeHours + ':' + elapsedTimeMinutes + ':' + elapsedTimeSeconds;
            },

            tick = function () {
                currentTime = Date.parse(new Date());
                elapsedTime = currentTime - initialTime;
                updateCosts();
                updateTime();
            },

            initTimer = function () {
                timerDomElement.style.display = 'block';
                //playpauseDomElement.className = 'running';
                //clearInterval(initialTime); // DEBUG
                initialTime = Date.parse(new Date());
                timerInterval = window.setInterval(MT.tick, 1000);
            },

            cacheDomElements = function () {
                timerDomElement = document.getElementById('timer');
                //playpauseDomElement = document.getElementById('playpause');
                timeDomElement = document.getElementById('time');
                moneyDomElement = document.getElementById('value');
                settingsIconDomElement = document.getElementById('settingsIcon');
                settingsDomElement = document.getElementById('settings');
                inputCurrencyDomElement = document.getElementsByClassName('currency');
                inputAttendeesDomElement = document.getElementById('inputAttendees');
                inputSalaryDomElement = document.getElementById('inputSalary');
                inputSubmitDomElement = document.getElementById('inputSubmit');
            },

            openSettings = function () {
                settingsAreOpen = true;
                settingsDomElement.className = 'active';
                settingsIconDomElement.className = 'active';
            },

            closeSettings = function () {
                settingsAreOpen = false;
                settingsDomElement.className = '';
                settingsIconDomElement.className = '';
            },

            handleClickOnSettingsIcon = function () {
                if (settingsAreOpen) {
                    closeSettings();
                } else {
                    openSettings();
                }
            },

            /*handleClickOnPlaypause = function () {
                if (playpauseDomElement.className === 'running') {
                    playpauseDomElement.className = ''
                } else {
                    playpauseDomElement.className = 'running';
                }
            },*/

            handleClickOnCurrency = function () {
                currencyIndex++;
                currencyIndex = currencyIndex % CHARACTERS_CURRENCY.length;
                currentCurrency = CHARACTERS_CURRENCY[currencyIndex];
                for (var i = 0; i < inputCurrencyDomElement.length; i++) {
                    inputCurrencyDomElement.item(i).innerHTML = currentCurrency;
                }
            },

            handleClickOnSubmit = function () {
                attendees = parseInt(inputAttendeesDomElement.value, 10);
                salary = parseInt(inputSalaryDomElement.value, 10);

                inputAttendeesDomElement.value = attendees;
                inputSalaryDomElement.value = salary;

                if (attendees > 0 && salary > 0) {
                    initTimer();
                    closeSettings();
                }

            },

            registerClickEvents = function () {
                //playpauseDomElement.addEventListener('click', MT.handleClickOnPlaypause, false);
                settingsIconDomElement.addEventListener('click', MT.handleClickOnSettingsIcon, false);
                for (var i = 0; i < inputCurrencyDomElement.length; i++) {
                    inputCurrencyDomElement.item(i).addEventListener('click', MT.handleClickOnCurrency, false);
                }
                inputSubmitDomElement.addEventListener('click', MT.handleClickOnSubmit, false);
            },

            debugSetBack = function (seconds) {
                initialTime -= seconds * 1000;
            },

            init = function () {
                cacheDomElements();
                registerClickEvents();
            }; // end of var

        return {
            init: init,
            tick: tick,
            handleClickOnSettingsIcon: handleClickOnSettingsIcon,
            handleClickOnCurrency: handleClickOnCurrency,
            //handleClickOnPlaypause: handleClickOnPlaypause,
            handleClickOnSubmit: handleClickOnSubmit
            //,debugSetBack: debugSetBack
        };
    }());
    MT.init();
}());<commit_msg>remove inactive code<commit_after>var MT;
(function () {
    "use strict";

    MT = (function () {
        var initialTime,
            currentTime,
            elapsedTime,
            elapsedTimeHours,
            elapsedTimeMinutes,
            elapsedTimeSeconds,
            attendees = 0,
            salary = 0,
            sum = 0,
            timerDomElement,
            timeDomElement,
            moneyDomElement,
            settingsIconDomElement,
            settingsDomElement,
            inputAttendeesDomElement,
            inputSalaryDomElement,
            inputCurrencyDomElement,
            inputSubmitDomElement,
            settingsAreOpen = true,
            CHARACTERS_CURRENCY = ['€', '$', '£', '¥', '¤'], // EUR, USD, GBP, YEN, CUR
            currencyIndex = 0,
            currentCurrency = CHARACTERS_CURRENCY[currencyIndex],
            valueIsHuge = false,

            updateCosts = function () {
                sum = ((attendees * salary * (elapsedTime / 3600000)))
                sum = Math.round(sum * 100) / 100;
                if (sum > 9999 && valueIsHuge === false) {
                    document.querySelector('.money').className += ' money--hugevalue';
                    valueIsHuge = true;
                } else if (sum > 10) {
                    sum = parseInt(sum, 10)
                }
                moneyDomElement.innerHTML = sum.toLocaleString();
            },

            updateTime = function () {
                elapsedTimeSeconds = Math.floor((elapsedTime / 1000) % 60);
                elapsedTimeMinutes = Math.floor((elapsedTime / 60000) % 60);
                elapsedTimeHours = Math.floor((elapsedTime / 1000) / 3600);

                elapsedTimeSeconds = (elapsedTimeSeconds > 9) ? elapsedTimeSeconds : '0' + elapsedTimeSeconds.toString();
                elapsedTimeMinutes = (elapsedTimeMinutes > 9) ? elapsedTimeMinutes : '0' + elapsedTimeMinutes.toString();

                timeDomElement.innerHTML = elapsedTimeHours + ':' + elapsedTimeMinutes + ':' + elapsedTimeSeconds;
            },

            tick = function () {
                currentTime = Date.parse(new Date());
                elapsedTime = currentTime - initialTime;
                updateCosts();
                updateTime();
            },

            initTimer = function () {
                timerDomElement.style.display = 'block';
                initialTime = Date.parse(new Date());
                timerInterval = window.setInterval(MT.tick, 1000);
            },

            cacheDomElements = function () {
                timerDomElement = document.getElementById('timer');
                timeDomElement = document.getElementById('time');
                moneyDomElement = document.getElementById('value');
                settingsIconDomElement = document.getElementById('settingsIcon');
                settingsDomElement = document.getElementById('settings');
                inputCurrencyDomElement = document.getElementsByClassName('currency');
                inputAttendeesDomElement = document.getElementById('inputAttendees');
                inputSalaryDomElement = document.getElementById('inputSalary');
                inputSubmitDomElement = document.getElementById('inputSubmit');
            },

            openSettings = function () {
                settingsAreOpen = true;
                settingsDomElement.className = 'active';
                settingsIconDomElement.className = 'active';
            },

            closeSettings = function () {
                settingsAreOpen = false;
                settingsDomElement.className = '';
                settingsIconDomElement.className = '';
            },

            handleClickOnSettingsIcon = function () {
                if (settingsAreOpen) {
                    closeSettings();
                } else {
                    openSettings();
                }
            },

            handleClickOnCurrency = function () {
                currencyIndex++;
                currencyIndex = currencyIndex % CHARACTERS_CURRENCY.length;
                currentCurrency = CHARACTERS_CURRENCY[currencyIndex];
                for (var i = 0; i < inputCurrencyDomElement.length; i++) {
                    inputCurrencyDomElement.item(i).innerHTML = currentCurrency;
                }
            },

            handleClickOnSubmit = function () {
                attendees = parseInt(inputAttendeesDomElement.value, 10);
                salary = parseInt(inputSalaryDomElement.value, 10);

                inputAttendeesDomElement.value = attendees;
                inputSalaryDomElement.value = salary;

                if (attendees > 0 && salary > 0) {
                    initTimer();
                    closeSettings();
                }
            },

            registerClickEvents = function () {
                settingsIconDomElement.addEventListener('click', MT.handleClickOnSettingsIcon, false);
                for (var i = 0; i < inputCurrencyDomElement.length; i++) {
                    inputCurrencyDomElement.item(i).addEventListener('click', MT.handleClickOnCurrency, false);
                }
                inputSubmitDomElement.addEventListener('click', MT.handleClickOnSubmit, false);
            },

            debugSetBack = function (seconds) {
                initialTime -= seconds * 1000;
            },

            init = function () {
                cacheDomElements();
                registerClickEvents();
            }; // end of var

        return {
            init: init,
            tick: tick,
            handleClickOnSettingsIcon: handleClickOnSettingsIcon,
            handleClickOnCurrency: handleClickOnCurrency,
            handleClickOnSubmit: handleClickOnSubmit
        };
    }());
    MT.init();
}());<|endoftext|>


<commit_before>angular.module('dogtalk', ['ngSockethubClient', 'ngSockethubRemoteStorage', 'ngRemoteStorage', 'ngXMPPClient', 'ngMessages']).

/**
 * routes
 */
config(['$routeProvider',
function ($routeProvider) {
  $routeProvider.
    when('/settings', {
      templateUrl: "settings.html",
      controller: "settingsCtrl"
    }).
    when('/', {
      templateUrl: "talk.html",
      controller: "talkCtrl"
    }).
    when('/talk/:address', {
      templateUrl: "talk.html",
      controller: "talkCtrl"
    }).
    otherwise({
      redirectTo: "/"
    });
}]).

/**
 * remotestorage config
 */
run(['RemoteStorageConfig',
function (RScfg) {
  RScfg.modules = [
    ['sockethub', 'rw', {'cache': false}],
    ['messages', 'rw', {'cache': false}],
    ['contacts', 'rw', {'cache': false}]
  ];
}]).

/**
 * check remoteStorage connections
 */
run(['$rootScope', 'RS', '$timeout',
function ($rootScope, RS, $timeout) {
  if (!RS.isConnected()) {
    $timeout(function () {
      if (!RS.isConnected()) {
        $rootScope.$broadcast('message', {message: 'remotestorage-connect', timeout: false});
      }
    }, 1000);
  }
}]).

/**
 * sockethub config & connect
 */
run(['SockethubBootstrap',
function (SockethubBootstrap) {
  SockethubBootstrap.run({
    // default connection settings, if none found in remoteStorage
    host: 'silverbucket.net',
    port: '443',
    path: '/sockethub',
    tls: true,
    secret: '1234567890'
  });
}]).

/**
 * get xmpp config
 */
run(['SH', '$rootScope', 'RS', 'XMPP', 'XMPPSettings',
function (SH, $rootScope, RS, XMPP, settings) {
  RS.call('messages', 'getAccount', ['xmpp', 'default']).then(function (c) {
    console.log('GOT XMPP CONFIG: ', c);
    var cfg = {};

    if (c === undefined) {
      $rootScope.$broadcast('showModalSettingsXmpp', {
        message: 'No existing XMPP configuration information found',
        locked: false
      });
      $rootScope.$broadcast('message', {
        message: 'xmpp-connection',
        type: 'error',
        timeout: false
        //important: true
      });
    } else {
      XMPP.connect(c).then(function () {
        console.log('xmpp connected');
      }, function (err) {
        $rootScope.$broadcast('showModalSettingsXmpp', { message: 'Error connecting via XMPP '+err, locked: false });
        console.log('xmpp ERROR', err);
        $rootScope.$broadcast('message', {
          message: err,
          type: 'error',
          timeout: true
        });
      });
    }

  }, function (err) {
    console.log("RS.call failed: ",err);
  });
}]).

/**
 * emitters
 */

///////////////////////////////////////////////////////////////////////////
//
// CONTROLLERS
//
///////////////////////////////////////////////////////////////////////////

/**
 * controller: appCtrl
 */
controller('appCtrl',
['$scope', '$rootScope', '$route', '$location',
function ($scope, $rootScope, $route, $location) {

  $rootScope.$on("$routeChangeStart", function (event, current, previous, rejection) {
    console.log('routeChangeStart: ', $scope, $rootScope, $route, $location);
  });

  $rootScope.$on("$routeChangeSuccess", function (event, current, previous, rejection) {
    //console.log('routeChangeSuccess: ', $scope, $rootScope, $route, $location);
    console.log('routeChangeSuccess');
  });

  $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
    console.log('routeChangeError: ', rejection);
  });

}]).

/**
 * controller: navCtrl
 */
controller("navCtrl",
['$scope', '$route', '$routeParams', '$location',
function ($scope, $route, $routeParams, $location) {
  $scope.navClass = function (page) {
    var currentRoute = $location.path().substring(1) || 'home';
    return page === currentRoute ? 'active' : '';
  };
}]).

/**
 * controller: settingsCtrl
 */
controller("settingsCtrl",
['$scope', '$route', '$routeParams', '$rootScope', 'SockethubSettings', 'XMPP', 'RS',
function ($scope, $route, $routeParams, $rootScope, SockethubSettings, XMPP, RS) {

  $scope.sockethubSettings = function () {
    $rootScope.$broadcast('showModalSockethubSettings', { locked: false });
  };

  /*
   FIXME: ...
   $scope.$watch('SockethubSettings.connected', function (newVal, oldVal) {
    if (SockethubSettings.connected) {
      SockethubSettings.conn.port = Number(SockethubSettings.conn.port);
      RS.call('sockethub', 'writeConfig', [SockethubSettings.conn]).then(function () {
        console.log("Sockethub config saved to remoteStorage");
      }, function (err) {
        console.log('Failed saving Sockethub config to remoteStorage: ', err);
      });
    }
  });
  */

}]).

/**
 * controller: talkCtrl
 */
controller("talkCtrl",
['$scope', '$route', '$routeParams', '$location', 'XMPP', '$rootScope', 'XMPPSettings',
function ($scope, $route, $routeParams, $location, XMPP, $rootScope, XMPPSettings) {
  console.log('--- talkCtrl run');

  $scope.model = {
    presence: XMPP.presence.data,
    contacts: XMPP.contacts.data,
    config: XMPPSettings.conn,
    requests: XMPP.requests.data
  };

  XMPP.initListener();  // initialize listener for incoming xmpp platform messages

  $scope.model.currentAddress = ($routeParams.address) ? $routeParams.address : 'none';
  $scope.model.currentName = ($scope.model.contacts[$routeParams.address]) ? $scope.model.contacts[$routeParams.address].name : '';
  $scope.model.currentConversation = ($scope.model.contacts[$routeParams.address]) ? $scope.model.contacts[$routeParams.address].conversation : [];

  $scope.$watch('model.contacts', function (newValue, oldValue) {
    console.log('SCOPE WATCH CONTACTS : ', newValue);
  });

  $scope.conversationSwitch = function (address) {
    console.log('---- talkCtrl.conversationSwitch('+address+')');
    if (address !== $routeParams.address) { return ''; }

    if ($scope.model.contacts[address]) {
      $scope.model.currentAddress = address;
      $scope.model.currentName = $scope.model.contacts[address].name;
      $scope.model.currentConversation = $scope.model.contacts[address].conversation;
      console.log('currentConversation: ',$scope.model.currentConversation);
    } else {
      console.log('talkCtrl.conversationSwitch() - not in history');
    }

    return 'active';
  };

  $scope.sendMsg = function (text) {
    $scope.model.saving = true;
    XMPP.sendMsg($scope.model.config.username, $scope.model.currentAddress, text).then(function () {
      $scope.model.sendText = '';
      $scope.model.saving = false;
    }, function (err) {
      console.log('sendMsg error: '+err);
      $scope.model.saving = false;
    });

  };

  $scope.isFromMe = function (address) {
    if ($scope.model.config.username === address) {
      return true;
    } else {
      return false;
    }
  };

  $scope.acceptBuddyRequest = function (address) {
    $scope.model.saving = true;
    if ($scope.model.requests[address]) {
      XMPP.requests.accept($scope.model.config.username, address).then(function () {
        $scope.model.saving = false;
        delete $scope.model.requests[address];
        return true;
      }, function (err) {
        $scope.model.saving = false;
        return false;
      });
    } else {
      $scope.model.saving = false;
      return false;
    }
  };

  /*
  $scope.$watch('model.currentAddress', function (address) {
    if (!address) { return false; }

    if ($scope.model.contacts[address]) {
      $scope.model.currentAddress = address;
      $scope.model.currentName = $scope.model.contacts[address].name;
      $scope.model.currentConversation = $scope.model.contacts[address].conversation;
      console.log('WATCH updated: ',$scope.model.current);
    } else {
      console.log('WATCH - not in history');
    }

  });
  */

}]).

/**
 * controller: log
 */
controller("logCtrl",
['$scope', '$route', '$routeParams', '$location',
function ($scope, $route, $routeParams, $location) {
  $scope.model = {
    message: "this is the log page fool!"
  };
}]);

<commit_msg>improved xmpp settings modal window, show existing data in form, etc.<commit_after>angular.module('dogtalk', ['ngSockethubClient', 'ngSockethubRemoteStorage', 'ngRemoteStorage', 'ngXMPPClient', 'ngMessages']).

/**
 * routes
 */
config(['$routeProvider',
function ($routeProvider) {
  $routeProvider.
    when('/settings', {
      templateUrl: "settings.html",
      controller: "settingsCtrl"
    }).
    when('/', {
      templateUrl: "talk.html",
      controller: "talkCtrl"
    }).
    when('/talk/:address', {
      templateUrl: "talk.html",
      controller: "talkCtrl"
    }).
    otherwise({
      redirectTo: "/"
    });
}]).

/**
 * remotestorage config
 */
run(['RemoteStorageConfig',
function (RScfg) {
  RScfg.modules = [
    ['sockethub', 'rw', {'cache': false}],
    ['messages', 'rw', {'cache': false}],
    ['contacts', 'rw', {'cache': false}]
  ];
}]).

/**
 * check remoteStorage connections
 */
run(['$rootScope', 'RS', '$timeout',
function ($rootScope, RS, $timeout) {
  if (!RS.isConnected()) {
    $timeout(function () {
      if (!RS.isConnected()) {
        $rootScope.$broadcast('message', {message: 'remotestorage-connect', timeout: false});
      }
    }, 1000);
  }
}]).

/**
 * sockethub config & connect
 */
run(['SockethubBootstrap',
function (SockethubBootstrap) {
  SockethubBootstrap.run({
    // default connection settings, if none found in remoteStorage
    host: 'silverbucket.net',
    port: '443',
    path: '/sockethub',
    tls: true,
    secret: '1234567890'
  });
}]).

/**
 * get xmpp config
 */
run(['SH', '$rootScope', 'RS', 'XMPP', 'XMPPSettings',
function (SH, $rootScope, RS, XMPP, settings) {
  RS.call('messages', 'getAccount', ['xmpp', 'default']).then(function (c) {
    console.log('GOT XMPP CONFIG: ', c);
    var cfg = {};

    if (c === undefined) {
      $rootScope.$broadcast('showModalSettingsXmpp', {
        message: 'No existing XMPP configuration information found',
        locked: false
      });
      $rootScope.$broadcast('message', {
        message: 'xmpp-connection',
        type: 'error',
        timeout: false
        //important: true
      });
    } else {
      XMPP.connect(c).then(function () {
        console.log('xmpp connected');
      }, function (err) {
        $rootScope.$broadcast('showModalSettingsXmpp', { message: 'Error connecting via XMPP '+err, locked: false });
        console.log('xmpp ERROR', err);
        $rootScope.$broadcast('message', {
          message: err,
          type: 'error',
          timeout: true
        });
      });
    }

  }, function (err) {
    console.log("RS.call failed: ",err);
  });
}]).

/**
 * emitters
 */

///////////////////////////////////////////////////////////////////////////
//
// CONTROLLERS
//
///////////////////////////////////////////////////////////////////////////

/**
 * controller: appCtrl
 */
controller('appCtrl',
['$scope', '$rootScope', '$route', '$location',
function ($scope, $rootScope, $route, $location) {

  $rootScope.$on("$routeChangeStart", function (event, current, previous, rejection) {
    console.log('routeChangeStart: ', $scope, $rootScope, $route, $location);
  });

  $rootScope.$on("$routeChangeSuccess", function (event, current, previous, rejection) {
    //console.log('routeChangeSuccess: ', $scope, $rootScope, $route, $location);
    console.log('routeChangeSuccess');
  });

  $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
    console.log('routeChangeError: ', rejection);
  });

}]).

/**
 * controller: navCtrl
 */
controller("navCtrl",
['$scope', '$route', '$routeParams', '$location',
function ($scope, $route, $routeParams, $location) {
  $scope.navClass = function (page) {
    var currentRoute = $location.path().substring(1) || 'home';
    return page === currentRoute ? 'active' : '';
  };
}]).

/**
 * controller: settingsCtrl
 */
controller("settingsCtrl",
['$scope', '$route', '$routeParams', '$rootScope', 'SockethubSettings', 'XMPP', 'RS',
function ($scope, $route, $routeParams, $rootScope, SockethubSettings, XMPP, RS) {

  $scope.sockethubSettings = function () {
    $rootScope.$broadcast('showModalSockethubSettings', { locked: false });
  };

  $scope.xmppSettings = function () {
    $rootScope.$broadcast('showModalSettingsXmpp', { locked: false });
  };

  /*
   FIXME: ...
   $scope.$watch('SockethubSettings.connected', function (newVal, oldVal) {
    if (SockethubSettings.connected) {
      SockethubSettings.conn.port = Number(SockethubSettings.conn.port);
      RS.call('sockethub', 'writeConfig', [SockethubSettings.conn]).then(function () {
        console.log("Sockethub config saved to remoteStorage");
      }, function (err) {
        console.log('Failed saving Sockethub config to remoteStorage: ', err);
      });
    }
  });
  */

}]).

/**
 * controller: talkCtrl
 */
controller("talkCtrl",
['$scope', '$route', '$routeParams', '$location', 'XMPP', '$rootScope', 'XMPPSettings',
function ($scope, $route, $routeParams, $location, XMPP, $rootScope, XMPPSettings) {
  console.log('--- talkCtrl run');

  $scope.model = {
    presence: XMPP.presence.data,
    contacts: XMPP.contacts.data,
    config: XMPPSettings.conn,
    requests: XMPP.requests.data
  };

  XMPP.initListener();  // initialize listener for incoming xmpp platform messages

  $scope.model.currentAddress = ($routeParams.address) ? $routeParams.address : 'none';
  $scope.model.currentName = ($scope.model.contacts[$routeParams.address]) ? $scope.model.contacts[$routeParams.address].name : '';
  $scope.model.currentConversation = ($scope.model.contacts[$routeParams.address]) ? $scope.model.contacts[$routeParams.address].conversation : [];

  $scope.$watch('model.contacts', function (newValue, oldValue) {
    console.log('SCOPE WATCH CONTACTS : ', newValue);
  });

  $scope.conversationSwitch = function (address) {
    console.log('---- talkCtrl.conversationSwitch('+address+')');
    if (address !== $routeParams.address) { return ''; }

    if ($scope.model.contacts[address]) {
      $scope.model.currentAddress = address;
      $scope.model.currentName = $scope.model.contacts[address].name;
      $scope.model.currentConversation = $scope.model.contacts[address].conversation;
      console.log('currentConversation: ',$scope.model.currentConversation);
    } else {
      console.log('talkCtrl.conversationSwitch() - not in history');
    }

    return 'active';
  };

  $scope.sendMsg = function (text) {
    $scope.model.saving = true;
    XMPP.sendMsg($scope.model.config.username, $scope.model.currentAddress, text).then(function () {
      $scope.model.sendText = '';
      $scope.model.saving = false;
    }, function (err) {
      console.log('sendMsg error: '+err);
      $scope.model.saving = false;
    });

  };

  $scope.isFromMe = function (address) {
    if ($scope.model.config.username === address) {
      return true;
    } else {
      return false;
    }
  };

  $scope.acceptBuddyRequest = function (address) {
    $scope.model.saving = true;
    if ($scope.model.requests[address]) {
      XMPP.requests.accept($scope.model.config.username, address).then(function () {
        $scope.model.saving = false;
        delete $scope.model.requests[address];
        return true;
      }, function (err) {
        $scope.model.saving = false;
        return false;
      });
    } else {
      $scope.model.saving = false;
      return false;
    }
  };

  /*
  $scope.$watch('model.currentAddress', function (address) {
    if (!address) { return false; }

    if ($scope.model.contacts[address]) {
      $scope.model.currentAddress = address;
      $scope.model.currentName = $scope.model.contacts[address].name;
      $scope.model.currentConversation = $scope.model.contacts[address].conversation;
      console.log('WATCH updated: ',$scope.model.current);
    } else {
      console.log('WATCH - not in history');
    }

  });
  */

}]).

/**
 * controller: log
 */
controller("logCtrl",
['$scope', '$route', '$routeParams', '$location',
function ($scope, $route, $routeParams, $location) {
  $scope.model = {
    message: "this is the log page fool!"
  };
}]);

<|endoftext|>


<commit_before>gpf.require.define({
    dom: "../dom.js",
    "tile:sources": "sources.js",
    "tile:plato": "plato.js",
    "tile:coverage": "coverage.js",
    "tile:tests": "tests.js",
    "tile:hosts": "hosts.js",
    "tile:doc": "doc.js",
    "tile:github": "github.js"

}, function (require) {
    "use strict";

    var dom = require.dom,
        tiles = Object.keys(require)
            .filter(function (name) {
                return 0 === name.indexOf("tile:");
            })
            .map(function (name) {
                return new require[name]();
            }),
        tilesById = {};

    function refreshContent (tile, dynamicContent) {
        var dynamicRoot = document.getElementById(tile.getId()).querySelector(".dynamic");
        dom.clear(dynamicRoot);
        dynamicContent.forEach(function (tag) {
            tag.appendTo(dynamicRoot);
        });
    }

    function refresh (tile) {
        return tile.getDynamicContent()
            .then(refreshContent.bind(null, tile));
    }

    var tilesRoot = document.getElementById("tiles");
    tiles.forEach(function (tile) {
        tilesById[tile.getId()] = tile;
        tile.render().appendTo(tilesRoot);
        refresh(tile);
    });

    document.addEventListener("click", function (event) {
        var target = event.target,
            link;
        while (target && !(link = target.getAttribute && target.getAttribute("link"))) {
            target = target.parentNode;
        }
        if ("host" === link) {
            var versionSelect = document.getElementById("hostsVersion"),
                version = versionSelect.options[versionSelect.selectedIndex].value,
                envName = target.innerHTML;
            link = "grunt/exec:test" + envName.charAt(0).toUpperCase() + envName.substr(1) + version;
        }
        if (link) {
            window.open(link);
        }
    });

    window.onpopstate = function () {
        tiles.forEach(refresh);
    };

    if (typeof Chartist !== "undefined") {
        var _lastChartsId;

        document.addEventListener("mouseover", function (event) {
            var charts = document.querySelector(".charts"),
                target = event.target,
                targetRect,
                left,
                top,
                bodyWidth;
            while (target && !(target.id && target.tagName.toLowerCase() === "li" && !target.getAttribute("link"))) {
                target = target.parentNode;
            }
            if (target) {
                if (target.id === _lastChartsId) {
                    return;
                }
                _lastChartsId = target.id;
                targetRect = target.getBoundingClientRect();
                left = targetRect.left;
                top = targetRect.top + targetRect.height + 4;
                bodyWidth = document.body.getBoundingClientRect().width;
                if (left + 640 > bodyWidth) {
                    left = bodyWidth - 640;
                }
                charts.innerHTML = "";
                if (tilesById[target.id].drawCharts()) {
                    charts.setAttribute("style", "left: " + left + "px; top: " + top + "px;");
                } else {
                    charts.setAttribute("style", "display: none;");
                }

            } else {
                _lastChartsId = undefined;
                charts.setAttribute("style", "display: none;");
            }
        });

        dom.div({
            className: "charts",
            style: "display: none"
        }).appendTo(document.body);
    }

});
<commit_msg>Linter errors (#274)<commit_after>gpf.require.define({
    dom: "../dom.js",
    "tile:sources": "sources.js",
    "tile:plato": "plato.js",
    "tile:coverage": "coverage.js",
    "tile:tests": "tests.js",
    "tile:hosts": "hosts.js",
    "tile:doc": "doc.js",
    "tile:github": "github.js"

}, function (require) {
    "use strict";

    var dom = require.dom,
        tiles = Object.keys(require)
            .filter(function (name) {
                return 0 === name.indexOf("tile:");
            })
            .map(function (name) {
                return new require[name]();
            }),
        tilesById = {};

    function refreshContent (tile, dynamicContent) {
        var dynamicRoot = document.getElementById(tile.getId()).querySelector(".dynamic");
        dom.clear(dynamicRoot);
        dynamicContent.forEach(function (tag) {
            tag.appendTo(dynamicRoot);
        });
    }

    function refresh (tile) {
        return tile.getDynamicContent()
            .then(refreshContent.bind(null, tile));
    }

    var tilesRoot = document.getElementById("tiles");
    tiles.forEach(function (tile) {
        tilesById[tile.getId()] = tile;
        tile.render().appendTo(tilesRoot);
        refresh(tile);
    });

    document.addEventListener("click", function (event) {
        var target = event.target,
            link;
        while (target && !(link = target.getAttribute && target.getAttribute("link"))) {
            target = target.parentNode;
        }
        if ("host" === link) {
            var versionSelect = document.getElementById("hostsVersion"),
                version = versionSelect.options[versionSelect.selectedIndex].value,
                envName = target.innerHTML;
            link = "grunt/exec:test" + envName.charAt(0).toUpperCase() + envName.substr(1) + version;
        }
        if (link) {
            window.open(link);
        }
    });

    window.onpopstate = function () {
        tiles.forEach(refresh);
    };

    var _lastChartsId;

    function renderCharts (target) {
        var charts = document.querySelector(".charts"),
            targetRect = target.getBoundingClientRect(),
            left = targetRect.left,
            top = targetRect.top + targetRect.height + 4,
            bodyWidth = document.body.getBoundingClientRect().width;
        if (left + 640 > bodyWidth) {
            left = bodyWidth - 640;
        }
        charts.innerHTML = "";
        if (tilesById[target.id].drawCharts()) {
            charts.setAttribute("style", "left: " + left + "px; top: " + top + "px;");
        } else {
            charts.setAttribute("style", "display: none;");
        }
    }

    if (typeof Chartist !== "undefined") {

        document.addEventListener("mouseover", function (event) {
            var target = event.target;
            while (target && !(target.id && target.tagName.toLowerCase() === "li" && !target.getAttribute("link"))) {
                target = target.parentNode;
            }
            if (target) {
                if (target.id === _lastChartsId) {
                    return;
                }
                _lastChartsId = target.id;
                renderCharts(target);

            } else {
                _lastChartsId = undefined;
                document.querySelector(".charts").setAttribute("style", "display: none;");
            }
        });

        dom.div({
            className: "charts",
            style: "display: none"
        }).appendTo(document.body);
    }

});
<|endoftext|>