<commit_before>module.exports = function(opts, definition) {
  var table = new Table(this, opts, definition)
  this.contents.push(table)
  return table
}

var utils = require('../utils')

var defaults = {
  size: 12,
  padding: {
    top: 5, bottom: 5,
    left: 8, right: 8
  },
  borderWidth: {
    top: null, bottom: null,
    left: null, right: null
  }
}

var Table = function(doc, opts, definition) {
  if (typeof opts === 'function') {
    definition = opts
    opts = {}
  }

  this.doc  = doc.doc || doc
  this.opts = opts || {}

  mergeOption(defaults, this.opts)

  this.rows = []

  if (definition) definition.call(this, this)
}

Table.prototype.tr = function(opts, definition) {
  var row = new Row(this, opts, definition)
  this.rows.push(row)
  return row
}

Table.prototype.render = function(page, width) {
  var columns = [], self = this
    , maxWidth = minWidth = width

  if (Array.isArray(this.opts.width)) {
    var widths = this.opts.width

    var absolute = 0
    widths.forEach(function(width, i) {
      if (!!~width.toString().indexOf('%'))
        return
      absolute += (columns[i] = parseFloat(width))
    })

    var remaining = maxWidth - absolute
    widths.forEach(function(width, i) {
      if (!!~width.toString().indexOf('%')) {
        columns[i] = utils.resolveWidth(width, remaining)
      }
    })
  } else {
    if ('width' in this.opts)
      minWidth = utils.resolveWidth(widths, maxWidth)

    var highestRowWidth = Math.max.apply(Math, this.rows.map(function(row) {
      return row.cells.map(function(cell, i) {
        if (columns[i] === undefined || (cell.width > columns[i] && !(cell.opts.colspan > 1)))
          columns[i] = cell.width
        return cell.width
      }).reduce(function(lhs, rhs) { return lhs + rhs }, 0)
    }))

    if (highestRowWidth > maxWidth) {
      var widthPerCell = maxWidth / columns.length
        , toShrink = []
        , unused = 0

      for (var i = 0, len = columns.length; i < len; ++i) {
        if (columns[i] < widthPerCell) unused += widthPerCell - columns[i]
        else toShrink.push(i)
      }

      widthPerCell += unused / toShrink.length
      toShrink.forEach(function(i) {
        columns[i] = widthPerCell
      })
    }

    if (minWidth && highestRowWidth < minWidth) {
      var widthPerCell = minWidth / columns.length
        , toExtend = []
        , used = 0

      for (var i = 0, len = columns.length; i < len; ++i) {
        if (columns[i] < widthPerCell) toExtend.push(i)
        used += columns[i]
      }

      var add = (minWidth - used) / toExtend.length
      toExtend.forEach(function(i) {
        columns[i] += add
      })
    }
  }

  var left = page.cursor.x
  for (var i = 0; i < this.rows.length; ++i) {
    var y = page.cursor.y
      , row = this.rows[i]

    var transaction = this.doc.startTransaction()

    var height = row.render(page, columns)

    if (height === false) {
      page.cursor.x = left
      page.cursor.y = y

      transaction.rollback()
      row.allowBreak = pagebreak = true
      --i
      if (this.opts.header === true) {
        page = this.doc.pagebreak()
        y = page.cursor.y
        height = this.rows[0].render(page, columns)
      }
    } else {
      transaction.commit()
    }

    page.cursor.x = left
    page.cursor.y = y - height
  }
}

var Row = function(table, opts, definition) {
  if (typeof opts === 'function') {
    definition = opts
    opts = {}
  }

  this.table = table
  this.doc   = table.doc
  this.opts  = mergeOption(table.opts, opts || {})

  this.cells = []

  this.allowBreak = false

  if (definition) definition.call(this, this)
}

Object.defineProperties(Row.prototype, {
  isFirstRow: {
    enumerable: true,
    get: function() {
      return this.table.rows.indexOf(this) === 0
    }
  },
  isLastRow: {
    enumerable: true,
    get: function() {
      return this.table.rows.indexOf(this) === this.table.rows.length - 1
    }
  }
})

Row.prototype.td = function(text, opts) {
  if (typeof text === 'object') {
    var fn = opts
    opts = text
    text = fn
  }
  var cell = new Cell(this, text, opts)
  this.cells.push(cell)
  return cell
}

Row.prototype.render = function(page, columns) {
  var left = page.cursor.x
    , y = page.cursor.y
    , heights = []
    , borders = []
    , pagebreak = false
    , column = 0

  for (var i = 0, len = this.cells.length; i < len; ++i) {
    var cell = this.cells[i]

    var width = columns[column++]
    if (cell.opts.colspan > 1) {
      for (var j = column, count = column + cell.opts.colspan - 1; j < count; ++j) {
        width += columns[j] || 0
      }
      column += cell.opts.colspan - 1
    }

    !function(x, y, width) {
      borders.push(function(height) {
        cell.drawBorder(page, x, y, width, height)
      })
    }(page.cursor.x, page.cursor.y, width)

    var paddingLeft  = cell.borderLeftWidth + cell.opts.padding.left
      , paddingRight = cell.opts.padding.right + cell.borderRightWidth
      , innerWidth   = width - paddingLeft - paddingRight
    page.cursor.x += paddingLeft
    page.cursor.y -= cell.borderTopWidth + cell.opts.padding.top // padding top
    var pageIndex = this.doc.pages.pages.indexOf(page)
    cell.render(page, innerWidth) // below: padding bottom
    var height = pageIndex + 1 < this.doc.pages.count
        ? y - this.doc.padding.bottom
        : y - page.cursor.y + cell.opts.padding.bottom + cell.borderBottomWidth
    for (var j = pageIndex + 1, count = this.doc.pages.count; j < count; ++j) {
      height += this.doc.height - this.doc.padding.top - this.doc.pages.pages[j].cursor.y
    }
    heights.push(height)
    page.cursor.y = y
    page.cursor.x += innerWidth + paddingRight

    if (this.doc.cursor !== page && !this.allowBreak) {
      return false
    }
  }

  var height = Math.max.apply(Math, heights)
  borders.forEach(function(border) {
    border(height)
  })

  return height
}

var Text = require('./text').Text
  , Fragment = require('../fragment')

var Cell = function(row, text, opts) {
  if (!opts) opts = {}

  this.row  = row
  this.doc  = row.doc
  this.opts = mergeOption(row.opts, opts)

  if (text instanceof Fragment) {
    this.content = text
    this.contents = text.prepared
  } else {
    this.content = new Fragment(this.doc)
    if (typeof text === 'function') {
      text.call(this.content, this.content)
    } else {
      this.content.text(text, this.opts)
    }
  }

  this.innerWidth  = this.content.maxWidth
  this.innerHeight = this.content.minHeight

  this.isFirstColumn = this.row.cells.length === 0
  this.isLastColumn  = true
  if (!this.isFirstColumn)
    this.row.cells[this.row.cells.length - 1].isLastColumn = false
}

Cell.prototype.render = function(page, width) {
  this.content.render(page, width)
}

Cell.prototype.drawBorder = function(page, x, y, width, height, splitBelow, splitAbove) {
  if (y - this.doc.padding.bottom < height) {
    var spaceLeft = height - y + this.doc.padding.bottom
    var pageIndex = this.doc.pages.pages.indexOf(page)
    this.drawBorder(page, x, y, width, y - this.doc.padding.bottom, true, false)
    while (spaceLeft > 0) {
      page = this.doc.pages.pages[++pageIndex]
      if (spaceLeft > this.doc.innerHeight) {
        height = this.doc.innerHeight
        this.drawBorder(page, this.doc.padding.left, this.doc.height - this.doc.padding.top, width, height, true, true)
      } else {
        height = spaceLeft // this.doc.height - this.doc.padding.top - page.cursor.y
        this.drawBorder(page, this.doc.padding.left, this.doc.height - this.doc.padding.top, width, height, false, true)
      }
      spaceLeft -= height
    }
    return
  }

  var border
  // border bottom
  if (this.borderBottomWidth > 0 && !splitBelow) {
    drawLine(page, border = this.borderBottomWidth,
             [x - border / 2, y - height + border / 2],
             [x + width, y - height + border / 2])
  }
    // border top
  if (this.borderTopWidth > 0 && !splitAbove) {
    drawLine(page, border = this.borderTopWidth,
             [x - border / 2, y],
             [x + width, y])
  }

  var downTo = y - height
  if (downTo < this.doc.padding.bottom)
    downTo = this.doc.padding.bottom

  // border right
  if (this.borderRightWidth > 0) {
    drawLine(page, border = this.borderRightWidth,
             [x + width - border / 2, downTo],
             [x + width - border / 2, y - border / 2])
  }

  // border left
  if (this.borderLeftWidth > 0) {
    drawLine(page, border = this.borderLeftWidth,
             [x, y + border / 2],
             [x, downTo])
  }
}

Object.defineProperties(Cell.prototype, {
  width: {
    enumerable: true,
    get: function() {
      return this.borderLeftWidth + this.opts.padding.left
           + this.innerWidth
           + this.opts.padding.right + this.borderRightWidth
    }
  },
  height: {
    enumerable: true,
    get: function() {
      return this.borderTopWidth + this.opts.padding.top
           // + this.opts.font.lineGap / 1000 * this.opts.size
           + this.innerHeight
           + this.opts.padding.bottom + this.borderBottomWidth
    }
  }
})

Object.defineProperties(Cell.prototype, {
  borderTopWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.top || (
        !this.row.isFirstRow ? borderWidth.horizontal || borderWidth.inside || 0
                             : 0
      )
    }
  },
  borderRightWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.right || (
        !this.isLastColumn ? borderWidth.vertical || borderWidth.inside || 0
                           : 0
      )
    }
  },
  borderBottomWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.bottom || (
        !this.row.isLastRow ? borderWidth.horizontal || borderWidth.inside || 0
                            : 0
      )
    }
  },
  borderLeftWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.left || (
        !this.isFirstColumn ? borderWidth.vertical || borderWidth.inside || 0
                            : 0
      )
    }
  }
})

// Helper Functions

function mergeOption(from, into) {
  for (var key in from) {
    if (key === 'width') continue
    var val = into[key]
    if (val === undefined || val === null)
      into[key] = from[key]
    else {
      switch(key) {
      case 'padding':
        val = expandOption(val, { top: 0, right: 0, bottom: 0, left: 0 })
        break
      case 'borderWidth':
        val = expandOption(val, { top: null, right: null, bottom: null, left: null,
                                  inside: null, horizontal: null, vertical: null })
        break
      default:
        continue
      }
      if (typeof val === 'object')
        into[key] = mergeOption(from[key], val)
    }
  }
  return into
}

function expandOption(option, defaults) {
  if (typeof option === 'object') {
    if (Array.isArray(option)) {
      if (option.length === 2)
        return { top: option[0], right: option[1], bottom: option[0], left: option[1] }
      else
        return { top: option[0], right: option[1], bottom: option[2], left: option[3] }
    } else {
      return mergeOption(defaults, option)
    }
  } else {
    return { top: option, right: option, bottom: option, left: option }
  }
}

function drawLine(page, width, from, to) {
  page.contents.writeLine('0 0 0 RG')
  page.contents.writeLine(width + ' w')
  page.contents.writeLine(from[0] + ' ' + from[1] + ' m ' + to[0] + ' ' + to[1] + ' l S')
  page.contents.writeLine('')
}<commit_msg>Fix Table Page Breaks<commit_after>module.exports = function(opts, definition) {
  var table = new Table(this, opts, definition)
  this.contents.push(table)
  return table
}

var utils = require('../utils')

var defaults = {
  size: 12,
  padding: {
    top: 5, bottom: 5,
    left: 8, right: 8
  },
  borderWidth: {
    top: null, bottom: null,
    left: null, right: null
  }
}

var Table = function(doc, opts, definition) {
  if (typeof opts === 'function') {
    definition = opts
    opts = {}
  }

  this.doc  = doc.doc || doc
  this.opts = opts || {}

  mergeOption(defaults, this.opts)

  this.rows = []

  if (definition) definition.call(this, this)
}

Table.prototype.tr = function(opts, definition) {
  var row = new Row(this, opts, definition)
  this.rows.push(row)
  return row
}

Table.prototype.render = function(page, width) {
  var columns = [], self = this
    , maxWidth = minWidth = width

  if (Array.isArray(this.opts.width)) {
    var widths = this.opts.width

    var absolute = 0
    widths.forEach(function(width, i) {
      if (!!~width.toString().indexOf('%'))
        return
      absolute += (columns[i] = parseFloat(width))
    })

    var remaining = maxWidth - absolute
    widths.forEach(function(width, i) {
      if (!!~width.toString().indexOf('%')) {
        columns[i] = utils.resolveWidth(width, remaining)
      }
    })
  } else {
    if ('width' in this.opts)
      minWidth = utils.resolveWidth(widths, maxWidth)

    var highestRowWidth = Math.max.apply(Math, this.rows.map(function(row) {
      return row.cells.map(function(cell, i) {
        if (columns[i] === undefined || (cell.width > columns[i] && !(cell.opts.colspan > 1)))
          columns[i] = cell.width
        return cell.width
      }).reduce(function(lhs, rhs) { return lhs + rhs }, 0)
    }))

    if (highestRowWidth > maxWidth) {
      var widthPerCell = maxWidth / columns.length
        , toShrink = []
        , unused = 0

      for (var i = 0, len = columns.length; i < len; ++i) {
        if (columns[i] < widthPerCell) unused += widthPerCell - columns[i]
        else toShrink.push(i)
      }

      widthPerCell += unused / toShrink.length
      toShrink.forEach(function(i) {
        columns[i] = widthPerCell
      })
    }

    if (minWidth && highestRowWidth < minWidth) {
      var widthPerCell = minWidth / columns.length
        , toExtend = []
        , used = 0

      for (var i = 0, len = columns.length; i < len; ++i) {
        if (columns[i] < widthPerCell) toExtend.push(i)
        used += columns[i]
      }

      var add = (minWidth - used) / toExtend.length
      toExtend.forEach(function(i) {
        columns[i] += add
      })
    }
  }

  var left = page.cursor.x
  for (var i = 0; i < this.rows.length; ++i) {
    var y = page.cursor.y
      , row = this.rows[i]

    var transaction = this.doc.startTransaction()

    var height = row.render(page, columns)

    if (height === false) {
      page.cursor.x = left
      page.cursor.y = y

      transaction.rollback()
      row.allowBreak = pagebreak = true
      --i
      page = this.doc.pagebreak()
      page.cursor.x = left
      y = page.cursor.y
      if (this.opts.header === true) {
        height = this.rows[0].render(page, columns)
      }
    } else {
      transaction.commit()
    }

    page.cursor.x = left
    page.cursor.y = y - height
  }
}

var Row = function(table, opts, definition) {
  if (typeof opts === 'function') {
    definition = opts
    opts = {}
  }

  this.table = table
  this.doc   = table.doc
  this.opts  = mergeOption(table.opts, opts || {})

  this.cells = []

  this.allowBreak = false

  if (definition) definition.call(this, this)
}

Object.defineProperties(Row.prototype, {
  isFirstRow: {
    enumerable: true,
    get: function() {
      return this.table.rows.indexOf(this) === 0
    }
  },
  isLastRow: {
    enumerable: true,
    get: function() {
      return this.table.rows.indexOf(this) === this.table.rows.length - 1
    }
  }
})

Row.prototype.td = function(text, opts) {
  if (typeof text === 'object') {
    var fn = opts
    opts = text
    text = fn
  }
  var cell = new Cell(this, text, opts)
  this.cells.push(cell)
  return cell
}

Row.prototype.render = function(page, columns) {
  var left = page.cursor.x
    , y = page.cursor.y
    , heights = []
    , borders = []
    , pagebreak = false
    , column = 0

  for (var i = 0, len = this.cells.length; i < len; ++i) {
    var cell = this.cells[i]

    var width = columns[column++]
    if (cell.opts.colspan > 1) {
      for (var j = column, count = column + cell.opts.colspan - 1; j < count; ++j) {
        width += columns[j] || 0
      }
      column += cell.opts.colspan - 1
    }

    !function(x, y, width) {
      borders.push(function(height) {
        cell.drawBorder(page, x, y, width, height)
      })
    }(page.cursor.x, page.cursor.y, width)

    var paddingLeft  = cell.borderLeftWidth + cell.opts.padding.left
      , paddingRight = cell.opts.padding.right + cell.borderRightWidth
      , innerWidth   = width - paddingLeft - paddingRight
    page.cursor.x += paddingLeft
    page.cursor.y -= cell.borderTopWidth + cell.opts.padding.top // padding top
    var pageIndex = this.doc.pages.pages.indexOf(page)
    cell.render(page, innerWidth) // below: padding bottom
    var height = pageIndex + 1 < this.doc.pages.count
        ? y - this.doc.padding.bottom
        : y - page.cursor.y + cell.opts.padding.bottom + cell.borderBottomWidth
    for (var j = pageIndex + 1, count = this.doc.pages.count; j < count; ++j) {
      height += this.doc.height - this.doc.padding.top - this.doc.pages.pages[j].cursor.y
    }
    heights.push(height)
    page.cursor.y = y
    page.cursor.x += innerWidth + paddingRight

    if (this.doc.cursor !== page && !this.allowBreak) {
      return false
    }
  }

  var height = Math.max.apply(Math, heights)
  borders.forEach(function(border) {
    border(height)
  })

  return height
}

var Text = require('./text').Text
  , Fragment = require('../fragment')

var Cell = function(row, text, opts) {
  if (!opts) opts = {}

  this.row  = row
  this.doc  = row.doc
  this.opts = mergeOption(row.opts, opts)

  if (text instanceof Fragment) {
    this.content = text
    this.contents = text.prepared
  } else {
    this.content = new Fragment(this.doc)
    if (typeof text === 'function') {
      text.call(this.content, this.content)
    } else {
      this.content.text(text, this.opts)
    }
  }

  this.innerWidth  = this.content.maxWidth
  this.innerHeight = this.content.minHeight

  this.isFirstColumn = this.row.cells.length === 0
  this.isLastColumn  = true
  if (!this.isFirstColumn)
    this.row.cells[this.row.cells.length - 1].isLastColumn = false
}

Cell.prototype.render = function(page, width) {
  this.content.render(page, width)
}

Cell.prototype.drawBorder = function(page, x, y, width, height, splitBelow, splitAbove) {
  if (y - this.doc.padding.bottom < height) {
    var spaceLeft = height - y + this.doc.padding.bottom
    var pageIndex = this.doc.pages.pages.indexOf(page)
    this.drawBorder(page, x, y, width, y - this.doc.padding.bottom, true, false)
    while (spaceLeft > 0) {
      page = this.doc.pages.pages[++pageIndex]
      if (spaceLeft > this.doc.innerHeight) {
        height = this.doc.innerHeight
        this.drawBorder(page, this.doc.padding.left, this.doc.height - this.doc.padding.top, width, height, true, true)
      } else {
        height = spaceLeft // this.doc.height - this.doc.padding.top - page.cursor.y
        this.drawBorder(page, this.doc.padding.left, this.doc.height - this.doc.padding.top, width, height, false, true)
      }
      spaceLeft -= height
    }
    return
  }

  var border
  // border bottom
  if (this.borderBottomWidth > 0 && !splitBelow) {
    drawLine(page, border = this.borderBottomWidth,
             [x - border / 2, y - height + border / 2],
             [x + width, y - height + border / 2])
  }
    // border top
  if (this.borderTopWidth > 0 && !splitAbove) {
    drawLine(page, border = this.borderTopWidth,
             [x - border / 2, y],
             [x + width, y])
  }

  var downTo = y - height
  if (downTo < this.doc.padding.bottom)
    downTo = this.doc.padding.bottom

  // border right
  if (this.borderRightWidth > 0) {
    drawLine(page, border = this.borderRightWidth,
             [x + width - border / 2, downTo],
             [x + width - border / 2, y - border / 2])
  }

  // border left
  if (this.borderLeftWidth > 0) {
    drawLine(page, border = this.borderLeftWidth,
             [x, y + border / 2],
             [x, downTo])
  }
}

Object.defineProperties(Cell.prototype, {
  width: {
    enumerable: true,
    get: function() {
      return this.borderLeftWidth + this.opts.padding.left
           + this.innerWidth
           + this.opts.padding.right + this.borderRightWidth
    }
  },
  height: {
    enumerable: true,
    get: function() {
      return this.borderTopWidth + this.opts.padding.top
           // + this.opts.font.lineGap / 1000 * this.opts.size
           + this.innerHeight
           + this.opts.padding.bottom + this.borderBottomWidth
    }
  }
})

Object.defineProperties(Cell.prototype, {
  borderTopWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.top || (
        !this.row.isFirstRow ? borderWidth.horizontal || borderWidth.inside || 0
                             : 0
      )
    }
  },
  borderRightWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.right || (
        !this.isLastColumn ? borderWidth.vertical || borderWidth.inside || 0
                           : 0
      )
    }
  },
  borderBottomWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.bottom || (
        !this.row.isLastRow ? borderWidth.horizontal || borderWidth.inside || 0
                            : 0
      )
    }
  },
  borderLeftWidth: {
    enumerable: true,
    get: function() {
      var borderWidth = this.opts.borderWidth
      return borderWidth.left || (
        !this.isFirstColumn ? borderWidth.vertical || borderWidth.inside || 0
                            : 0
      )
    }
  }
})

// Helper Functions

function mergeOption(from, into) {
  for (var key in from) {
    if (key === 'width') continue
    var val = into[key]
    if (val === undefined || val === null)
      into[key] = from[key]
    else {
      switch(key) {
      case 'padding':
        val = expandOption(val, { top: 0, right: 0, bottom: 0, left: 0 })
        break
      case 'borderWidth':
        val = expandOption(val, { top: null, right: null, bottom: null, left: null,
                                  inside: null, horizontal: null, vertical: null })
        break
      default:
        continue
      }
      if (typeof val === 'object')
        into[key] = mergeOption(from[key], val)
    }
  }
  return into
}

function expandOption(option, defaults) {
  if (typeof option === 'object') {
    if (Array.isArray(option)) {
      if (option.length === 2)
        return { top: option[0], right: option[1], bottom: option[0], left: option[1] }
      else
        return { top: option[0], right: option[1], bottom: option[2], left: option[3] }
    } else {
      return mergeOption(defaults, option)
    }
  } else {
    return { top: option, right: option, bottom: option, left: option }
  }
}

function drawLine(page, width, from, to) {
  page.contents.writeLine('0 0 0 RG')
  page.contents.writeLine(width + ' w')
  page.contents.writeLine(from[0] + ' ' + from[1] + ' m ' + to[0] + ' ' + to[1] + ' l S')
  page.contents.writeLine('')
}<|endoftext|>


<commit_before>
// Set the color of all polygons in this solid
CSG.prototype.setColor = function(r, g, b) {
  this.toPolygons().map(function(polygon) {
    polygon.shared = [r, g, b];
  });
};

// Convert from CSG solid to GL.Mesh object
CSG.prototype.toMesh = function() {
  var polygons = this.toPolygons();
  var geometry = new THREE.Geometry();
  var vertices = geometry.vertices;
  var faces = geometry.faces;
  var CSGVertexMap = {};
  var vertCtr = 0;
  var i, pos,polygon,polyIpolyIndex,polyIndexes,pos,vertex,face, mapIndex;
  for (i in polygons) {
    polygon = polygons[i];
    polyIndexes = [];
    for (vertex of polygon.vertices) {
      pos = vertex.pos;
      CSGVertexKey = pos.x.toFixed(TO_FIXED_DECIMAL_PLACES) + '_' + pos.y.toFixed(TO_FIXED_DECIMAL_PLACES) + '_' + pos.z.toFixed(TO_FIXED_DECIMAL_PLACES);
      if (CSGVertexMap.hasOwnProperty(CSGVertexKey)) {
        mapIndex = CSGVertexMap[CSGVertexKey];
      } else {
        vertices.push(new THREE.Vector3(pos.x,pos.y,pos.z));
        CSGVertexMap[CSGVertexKey] = vertCtr;
        mapIndex = vertCtr;
        vertCtr++;
      }
      polyIndexes.push(mapIndex);
    }
    for (polyIndex = 2; polyIndex < polyIndexes.length; ++polyIndex) {
      face = new THREE.Face3(polyIndexes[0], polyIndexes[polyIndex - 1], polyIndexes[polyIndex]);
      faces.push(face);
    }
  }
  geometry.elementsNeedUpdate = true;
  return(geometry);
};

CSG.Node.prototype.pointInside = function(testPoint) {
  var COPLANAR = 0;
  var FRONT = 1;
  var BACK = 2;

  console.log('Entering pointInside, with normal:', this.plane.normal, 'w:', this.plane.w);
  var t = this.plane.normal.dot(testPoint) - this.plane.w;
  var type = (t < -CSG.Plane.EPSILON) ? BACK : (t > CSG.Plane.EPSILON) ? FRONT : COPLANAR;

  if ((this.front == null) && (this.back == null)) {
    console.log('reached leaf, type:', type);
    return(type == BACK); // reached leaf, return whether we are inside this plane
  }

  switch (type) {
    case FRONT:
      if (this.front == null) {
        console.log('leaf, point is in front');
        return(false);
      }
      console.log('Point in front, recursing:');
      return(this.front.pointInside(testPoint));
    case BACK:
      if (this.back == null) {
        console.log('leaf, point is in back');
        return(true);
      }
      console.log('Point in back, recursing:');
      return(this.back.pointInside(testPoint));
    case COPLANAR:
      console.log('Point coplanar, recursing front:');
      var p1 = false, p2 = false;
      if (this.front) {
        p1 = this.front.pointInside(testPoint);
      }
      console.log('Point coplanar, recursing back:');
      if (this.back) {
        var p2 = this.back.pointInside(testPoint);
      }
      if (p1 == p2) {
        console.log('point coplanar, returning:', p1);
        return(p1);
      } else {
        console.log('point coplanar, returning false');
        return(false);
      }
  }
  return(false);
}
<commit_msg>add technical reference comment<commit_after>
// Set the color of all polygons in this solid
CSG.prototype.setColor = function(r, g, b) {
  this.toPolygons().map(function(polygon) {
    polygon.shared = [r, g, b];
  });
};

// Convert from CSG solid to GL.Mesh object
CSG.prototype.toMesh = function() {
  var polygons = this.toPolygons();
  var geometry = new THREE.Geometry();
  var vertices = geometry.vertices;
  var faces = geometry.faces;
  var CSGVertexMap = {};
  var vertCtr = 0;
  var i, pos,polygon,polyIpolyIndex,polyIndexes,pos,vertex,face, mapIndex;
  for (i in polygons) {
    polygon = polygons[i];
    polyIndexes = [];
    for (vertex of polygon.vertices) {
      pos = vertex.pos;
      CSGVertexKey = pos.x.toFixed(TO_FIXED_DECIMAL_PLACES) + '_' + pos.y.toFixed(TO_FIXED_DECIMAL_PLACES) + '_' + pos.z.toFixed(TO_FIXED_DECIMAL_PLACES);
      if (CSGVertexMap.hasOwnProperty(CSGVertexKey)) {
        mapIndex = CSGVertexMap[CSGVertexKey];
      } else {
        vertices.push(new THREE.Vector3(pos.x,pos.y,pos.z));
        CSGVertexMap[CSGVertexKey] = vertCtr;
        mapIndex = vertCtr;
        vertCtr++;
      }
      polyIndexes.push(mapIndex);
    }
    for (polyIndex = 2; polyIndex < polyIndexes.length; ++polyIndex) {
      face = new THREE.Face3(polyIndexes[0], polyIndexes[polyIndex - 1], polyIndexes[polyIndex]);
      faces.push(face);
    }
  }
  geometry.elementsNeedUpdate = true;
  return(geometry);
};

// Cf: Foley & Van Dam, https://books.google.com/books?id=-4ngT05gmAQC&pg=PA556&lpg=PA556&dq=point+inside+bsp+tree+solid&source=bl&ots=QXMqeVkzmd&sig=yqc3nNCupSWKVpEUpG1RpCJutfY&hl=en&sa=X&ved=0ahUKEwjz1PiXj9_RAhUD-mMKHYY0CDIQ6AEIJjAC#v=onepage&q=point%20inside%20bsp%20tree%20solid&f=false

CSG.Node.prototype.pointInside = function(testPoint) {
  var COPLANAR = 0;
  var FRONT = 1;
  var BACK = 2;

  console.log('Entering pointInside, with normal:', this.plane.normal, 'w:', this.plane.w);
  var t = this.plane.normal.dot(testPoint) - this.plane.w;
  var type = (t < -CSG.Plane.EPSILON) ? BACK : (t > CSG.Plane.EPSILON) ? FRONT : COPLANAR;

  if ((this.front == null) && (this.back == null)) {
    console.log('reached leaf, type:', type);
    return(type == BACK); // reached leaf, return whether we are inside this plane
  }

  switch (type) {
    case FRONT:
      if (this.front == null) {
        console.log('leaf, point is in front');
        return(false);
      }
      console.log('Point in front, recursing:');
      return(this.front.pointInside(testPoint));
    case BACK:
      if (this.back == null) {
        console.log('leaf, point is in back');
        return(true);
      }
      console.log('Point in back, recursing:');
      return(this.back.pointInside(testPoint));
    case COPLANAR:
      console.log('Point coplanar, recursing front:');
      var p1 = false, p2 = false;
      if (this.front) {
        p1 = this.front.pointInside(testPoint);
      }
      console.log('Point coplanar, recursing back:');
      if (this.back) {
        var p2 = this.back.pointInside(testPoint);
      }
      if (p1 == p2) {
        console.log('point coplanar, returning:', p1);
        return(p1);
      } else {
        console.log('point coplanar, returning false');
        return(false);
      }
  }
  return(false);
}
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import ValidationText from '../validationText';
import theme from './theme.css';

class InputBase extends PureComponent {
  state = {
    inputHasfocus: false,
  };

  handleBlur = event => {
    this.setState({ inputHasFocus: false });
    if (this.props.onBlur) {
      this.props.onBlur(event);
    }
  };

  handleChange = event => {
    if (this.props.onChange) {
      this.props.onChange(event);
    }
  };

  handleFocus = event => {
    this.setState({ inputHasFocus: true });
    if (this.props.onFocus) {
      this.props.onFocus(event);
    }
  };

  renderOneOrMultipleElements(prop) {
    if (Array.isArray(prop)) {
      return prop.map((element, index) => React.cloneElement(element, { key: index }));
    }

    return prop;
  }

  renderInput = () => {
    const { bold, ...otherProps } = this.props;

    const classNames = cx(theme['input'], { [theme['is-bold']]: bold });

    const restProps = omit(omitBoxProps(otherProps), [
      'className',
      'connectedLeft',
      'connectedRight',
      'helpText',
      'inverse',
      'onChange',
      'prefix',
      'size',
      'suffix',
    ]);

    const props = {
      className: classNames,
      onBlur: this.handleBlur,
      onChange: this.handleChange,
      onFocus: this.handleFocus,
      ...restProps,
    };

    return <input {...props} />;
  };

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      disabled,
      error,
      helpText,
      inverse,
      prefix,
      size,
      suffix,
      readOnly,
      ...others
    } = this.props;

    const { inputHasFocus } = this.state;

    const classNames = cx(
      theme['wrapper'],
      theme[`is-${size}`],
      {
        [theme['has-error']]: error,
        [theme['has-focus']]: inputHasFocus,
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['is-inverse']]: inverse,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const rest = pickBoxProps(others);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

            {prefix &&
{this.renderOneOrMultipleElements(prefix)}
}
            {this.renderInput()}
            {suffix &&
{this.renderOneOrMultipleElements(suffix)}
}

          {connectedRight}

        <ValidationText error={error} help={helpText} inverse={inverse} />
      </Box>
    );
  }
}

InputBase.propTypes = {
  /** Boolean indicating whether the input text should render in bold. */
  bold: PropTypes.bool,
  /** Sets a class name for the wrapper to give custom styles. */
  className: PropTypes.string,
  /** Element stuck to the left hand side of the component. */
  connectedLeft: PropTypes.element,
  /** Element stuck to the right hand side of the component. */
  connectedRight: PropTypes.element,
  /** Boolean indicating whether the input should render as disabled. */
  disabled: PropTypes.bool,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the input should render as inverse. */
  inverse: PropTypes.bool,
  /** Callback function that is fired when blurring the input field. */
  onBlur: PropTypes.func,
  /** Callback function that is fired when focusing the input field. */
  onFocus: PropTypes.func,
  /** Callback function that is fired when the component's value changes. */
  onChange: PropTypes.func,
  /** The text string/element to use as a prefix inside the input field */
  prefix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Boolean indicating whether the input should render as read only. */
  readOnly: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** The text string/element to use as a suffix inside the input field */
  suffix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Type of the input element. It can be a valid HTML5 input type. */
  type: PropTypes.oneOf([
    'button',
    'checkbox',
    'color',
    'date',
    'datetime-local',
    'email',
    'file',
    'hidden',
    'image',
    'month',
    'number',
    'password',
    'radio',
    'range',
    'reset',
    'search',
    'submit',
    'tel',
    'text',
    'time',
    'url',
    'week',
  ]),
  /** Current value of the input element. */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};

InputBase.defaultProps = {
  inverse: false,
  disabled: false,
  readOnly: false,
  size: 'medium',
};

export default InputBase;
<commit_msg>The internal onFocus/Blur/Change was not called when a handler was provided<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import ValidationText from '../validationText';
import theme from './theme.css';

class InputBase extends PureComponent {
  state = {
    inputHasfocus: false,
  };

  handleBlur = event => {
    this.setState({ inputHasFocus: false });
    if (this.props.onBlur) {
      this.props.onBlur(event);
    }
  };

  handleChange = event => {
    if (this.props.onChange) {
      this.props.onChange(event);
    }
  };

  handleFocus = event => {
    this.setState({ inputHasFocus: true });
    if (this.props.onFocus) {
      this.props.onFocus(event);
    }
  };

  renderOneOrMultipleElements(prop) {
    if (Array.isArray(prop)) {
      return prop.map((element, index) => React.cloneElement(element, { key: index }));
    }

    return prop;
  }

  renderInput = () => {
    const { bold, ...otherProps } = this.props;

    const classNames = cx(theme['input'], { [theme['is-bold']]: bold });

    const restProps = omit(omitBoxProps(otherProps), [
      'className',
      'connectedLeft',
      'connectedRight',
      'helpText',
      'inverse',
      'onChange',
      'prefix',
      'size',
      'suffix',
    ]);

    const props = {
      className: classNames,
      ...restProps,
      onBlur: this.handleBlur,
      onChange: this.handleChange,
      onFocus: this.handleFocus,
    };

    return <input {...props} />;
  };

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      disabled,
      error,
      helpText,
      inverse,
      prefix,
      size,
      suffix,
      readOnly,
      ...others
    } = this.props;

    const { inputHasFocus } = this.state;

    const classNames = cx(
      theme['wrapper'],
      theme[`is-${size}`],
      {
        [theme['has-error']]: error,
        [theme['has-focus']]: inputHasFocus,
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['is-inverse']]: inverse,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const rest = pickBoxProps(others);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

            {prefix &&
{this.renderOneOrMultipleElements(prefix)}
}
            {this.renderInput()}
            {suffix &&
{this.renderOneOrMultipleElements(suffix)}
}

          {connectedRight}

        <ValidationText error={error} help={helpText} inverse={inverse} />
      </Box>
    );
  }
}

InputBase.propTypes = {
  /** Boolean indicating whether the input text should render in bold. */
  bold: PropTypes.bool,
  /** Sets a class name for the wrapper to give custom styles. */
  className: PropTypes.string,
  /** Element stuck to the left hand side of the component. */
  connectedLeft: PropTypes.element,
  /** Element stuck to the right hand side of the component. */
  connectedRight: PropTypes.element,
  /** Boolean indicating whether the input should render as disabled. */
  disabled: PropTypes.bool,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the input should render as inverse. */
  inverse: PropTypes.bool,
  /** Callback function that is fired when blurring the input field. */
  onBlur: PropTypes.func,
  /** Callback function that is fired when focusing the input field. */
  onFocus: PropTypes.func,
  /** Callback function that is fired when the component's value changes. */
  onChange: PropTypes.func,
  /** The text string/element to use as a prefix inside the input field */
  prefix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Boolean indicating whether the input should render as read only. */
  readOnly: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** The text string/element to use as a suffix inside the input field */
  suffix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Type of the input element. It can be a valid HTML5 input type. */
  type: PropTypes.oneOf([
    'button',
    'checkbox',
    'color',
    'date',
    'datetime-local',
    'email',
    'file',
    'hidden',
    'image',
    'month',
    'number',
    'password',
    'radio',
    'range',
    'reset',
    'search',
    'submit',
    'tel',
    'text',
    'time',
    'url',
    'week',
  ]),
  /** Current value of the input element. */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};

InputBase.defaultProps = {
  inverse: false,
  disabled: false,
  readOnly: false,
  size: 'medium',
};

export default InputBase;
<|endoftext|>


<commit_before>const isTrue = require('./isTrue')

class DecoratorPattern {
  constructor (layer) {
    this.layer = layer

    this.layer.on('update', this.processObject.bind(this))
    this.layer.on('remove', this.removeObject.bind(this))
  }

  parseSymbolType (key, value) {
    switch (key) {
      default:
        return value
    }
  }

  parseType (key, value) {
    switch (key) {
      case 'polygon':
      case 'rotate':
        return isTrue(value)
      case 'angleCorrection':
      case 'pixelSize':
      case 'headAngle':
        return parseFloat(value)
      default:
        return value
    }
  }

  processObject (object, data) {
    if (!data.patternFeatures) {
      data.patternFeatures = {}
    }

    for (var k in data.features) {
      let def = k === 'default' ? data.data.style : data.data['style:' + k]

      if (def.pattern && data.styles.includes(k)) {
        let symbol
        let symbolOptions = {}
        let options = {}

        for (let k in def) {
          let m1 = k.match(/^pattern-path-(.*)$/)
          let m2 = k.match(/^pattern-(.*)$/)

          if (m1) {
            symbolOptions[m1[1]] = this.parseSymbolType(m1[1], def[k])
          } else if (m2) {
            options[m2[1]] = this.parseType(m2[1], def[k])
          }
        }

        switch (def.pattern.toString()) {
          case 'dash':
            options.pathOptions = symbolOptions
            symbol = L.Symbol.dash(options)
            break
          case 'arrowHead':
            options.pathOptions = symbolOptions
            symbol = L.Symbol.arrowHead(options)
            break
          case 'marker':
            options.markerOptions = symbolOptions
            symbol = L.Symbol.marker(options)
            break
          default:
            // TODO
        }

        options.symbol = symbol

        if (!data.patternFeatures[k]) {
          data.patternFeatures[k] = L.polylineDecorator(data.features[k])
          data.patternFeatures[k].addTo(this.layer.map)
        }

        data.patternFeatures[k].setPatterns([ options ])
      } else {
        if (data.patternFeatures[k]) {
          this.layer.map.removeLayer(data.patternFeatures[k])
          delete data.patternFeatures[k]
        }
      }
    }
  }

  removeObject (object, data) {
    if (!data.patternFeatures) {
      return
    }

    for (var k in data.features) {
      if (data.patternFeatures[k]) {
        this.layer.map.removeLayer(data.patternFeatures[k])
        delete data.patternFeatures[k]
      }
    }
  }
}

module.exports = DecoratorPattern
<commit_msg>DecoratorPattern: bind popup to features<commit_after>const isTrue = require('./isTrue')

class DecoratorPattern {
  constructor (layer) {
    this.layer = layer

    this.layer.on('update', this.processObject.bind(this))
    this.layer.on('remove', this.removeObject.bind(this))
  }

  parseSymbolType (key, value) {
    switch (key) {
      default:
        return value
    }
  }

  parseType (key, value) {
    switch (key) {
      case 'polygon':
      case 'rotate':
        return isTrue(value)
      case 'angleCorrection':
      case 'pixelSize':
      case 'headAngle':
        return parseFloat(value)
      default:
        return value
    }
  }

  processObject (object, data) {
    if (!data.patternFeatures) {
      data.patternFeatures = {}
    }

    for (var k in data.features) {
      let def = k === 'default' ? data.data.style : data.data['style:' + k]

      if (def.pattern && data.styles.includes(k)) {
        let symbol
        let symbolOptions = {}
        let options = {}

        for (let k in def) {
          let m1 = k.match(/^pattern-path-(.*)$/)
          let m2 = k.match(/^pattern-(.*)$/)

          if (m1) {
            symbolOptions[m1[1]] = this.parseSymbolType(m1[1], def[k])
          } else if (m2) {
            options[m2[1]] = this.parseType(m2[1], def[k])
          }
        }

        switch (def.pattern.toString()) {
          case 'dash':
            options.pathOptions = symbolOptions
            symbol = L.Symbol.dash(options)
            break
          case 'arrowHead':
            options.pathOptions = symbolOptions
            symbol = L.Symbol.arrowHead(options)
            break
          case 'marker':
            options.markerOptions = symbolOptions
            symbol = L.Symbol.marker(options)
            break
          default:
            // TODO
        }

        options.symbol = symbol

        if (!data.patternFeatures[k]) {
          data.patternFeatures[k] = L.polylineDecorator(data.features[k])
          data.patternFeatures[k].addTo(this.layer.map)
        }

        data.patternFeatures[k].setPatterns([ options ])

        if (this.layer._shallBindPopupToStyle(k)) {
          data.patternFeatures[k].bindPopup(data.popup)
        }
      } else {
        if (data.patternFeatures[k]) {
          this.layer.map.removeLayer(data.patternFeatures[k])
          delete data.patternFeatures[k]
        }
      }
    }
  }

  removeObject (object, data) {
    if (!data.patternFeatures) {
      return
    }

    for (var k in data.features) {
      if (data.patternFeatures[k]) {
        this.layer.map.removeLayer(data.patternFeatures[k])
        delete data.patternFeatures[k]
      }
    }
  }
}

module.exports = DecoratorPattern
<|endoftext|>


<commit_before>/**
 * Created by nathandunn on 6/10/17.
 */
import {AnnotationCommand, request, SelectionState} from "substance";

class MarkupApp {

    constructor() {
        this.words = [];
    }

    render(data, callback) {

        // let words = ['organism','unc-5','elegans','epidermal'];
        // alert('rendering with dat: ' + JSON.stringify(data));
        // alert('rendering with words: ' + data.length);

        let cmd = new ToggleStrongCommand();
        let documentSession = window.app.state.documentSession;
        let selectionState = documentSession.getSelectionState();
        let nodes = window.doc.getNodes();

        document.getElementById('message').innerHTML = "Running markup...";
        // n.startsWith('article') // article junk
        // || n.startsWith('ext-link') // what we are tring to create
        // n.startsWith('body') // this is just the intro
        // || n.startsWith('heading') // this is the heading for each paragraph
        let numErrors = 0;
        let totalWordsFound = 0;
        let wordsFound = [];
        let totalWordHits = 0;

        for (let n in nodes) {
            // console.log(n);
            if (n.startsWith('paragraph')
            ) {
                let p = window.doc.get(n);
                // just find the first one
                for (let w in data) {
                    let wordHits = 0;
                    let word = data[w];
                    let found = 0;
                    var reWord = word.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                    var re = new RegExp("\\W" + reWord + "\\W", "g");
                    var hits;
                    while (hits = re.exec(p.content)) {

                        let sel = documentSession.createSelection({
                            type: 'property',
                            path: [p.id, 'content'],
                            startOffset: hits.index + 1,
                            endOffset: hits.index + 1 + word.length
                        });
                        selectionState.setSelection(sel);
                        let cmdState = cmd.getCommandState({
                            selectionState: selectionState,
                            documentSession: documentSession
                        });
                        if (cmdState.mode == "create") {
                            cmd.execute({
                                commandState: {
                                    mode: 'create'
                                },
                                documentSession: documentSession,
                                selectionState: documentSession.getSelectionState()
                            });
                            console.log('Found ' + word);

                        } else {
                            console.log("Annotated words: " + p.content.substring(selectionState.getAnnotationsForType(cmd.getAnnotationType())[0].startOffset, selectionState.getAnnotationsForType(cmd.getAnnotationType())[0].endOffset));
                            if (cmdState.mode == "delete") {
                                console.log('Error trying to annotate: ' + word + ' because it is already linked.');
                            } else if (cmdState.mode == "expand") {
                                console.log('Error trying to annotate: ' + word + ' because part of the word is already linked.');
                            } else if (cmdState.mode == "truncate") {
                                console.log('Error trying to annotate: ' + word + ' because it is part of the linked word.');
                            }
                            ++numErrors;
                        }

                        //found = p.content.indexOf(word,found+1);
                        ++wordHits;
                    }
                    if (wordHits > 0) {
                        ++totalWordsFound;
                        totalWordHits += wordHits;
                        wordHits[word] = wordHits;
                        document.getElementById('message').innerHTML = "Searching: found " + totalWordsFound + " words, hits: "+totalWordHits;
                    }
                }
            }
        }
        document.getElementById('message').innerHTML = "Done: found " + totalWordsFound + " words";
        console.log('total found: ' + totalWordsFound);
        console.log('total errors: ' + numErrors);

        if (callback) callback();
    }

    getWords(callback) {
        let serverURL = window.location.protocol + '//' + window.location.hostname + ':8080/keyWordSet/sampleKeyWordSet';
        console.log('server URL: ' + serverURL);
        request('GET', serverURL, null, function (err, data) {
            if (err) {
                console.error(err);
                this.setState({
                    error: new Error('Loading failed')
                });
                return
            }
            if (data) {
                this.words = [];
                for (let d in data) {
                    this.words.push(data[d].value);
                }
                console.log('finished processing with words: ' + this.words.length);
                // this.render(this.words, cb);
                if (callback) callback(this.words);

                return this.words;
            }
        });
    }

}

class ToggleStrongCommand extends AnnotationCommand {

    // type = 'bold';
    // tagName = 'bold';

    constructor() {
        // super({name: 'bold', nodeType: 'bold'})
        super({name: 'markup', nodeType: 'ext-link'})
    }
}

// ToggleStrongCommand.define({
//     attributes: { type: 'object', default: {} }
// });

// export default ToggleStrongCommand

export default MarkupApp
<commit_msg>updated the markup<commit_after>/**
 * Created by nathandunn on 6/10/17.
 */
import {AnnotationCommand, request, SelectionState} from "substance";

class MarkupApp {

    constructor() {
        this.words = [];
    }

    render(data, callback) {

        // let words = ['organism','unc-5','elegans','epidermal'];
        // alert('rendering with dat: ' + JSON.stringify(data));
        // alert('rendering with words: ' + data.length);

        let cmd = new ToggleStrongCommand();
        let documentSession = window.app.state.documentSession;
        let selectionState = documentSession.getSelectionState();
        let nodes = window.doc.getNodes();

        document.getElementById('message').innerHTML = "Running markup...";
        // n.startsWith('article') // article junk
        // || n.startsWith('ext-link') // what we are tring to create
        // n.startsWith('body') // this is just the intro
        // || n.startsWith('heading') // this is the heading for each paragraph
        let numErrors = 0;
        let totalWordsFound = 0;
        let wordsFound = [];
        let totalWordHits = 0;

        for (let n in nodes) {
            // console.log(n);
            if (n.startsWith('paragraph')
            ) {
                let p = window.doc.get(n);
                // just find the first one
                for (let w in data) {
                    let wordHits = 0;
                    let word = data[w];
                    let found = 0;
                    var reWord = word.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
                    var re = new RegExp("\\W" + reWord + "\\W", "g");
                    var hits;
                    while (hits = re.exec(p.content)) {

                        let sel = documentSession.createSelection({
                            type: 'property',
                            path: [p.id, 'content'],
                            startOffset: hits.index + 1,
                            endOffset: hits.index + 1 + word.length
                        });
                        selectionState.setSelection(sel);
                        let cmdState = cmd.getCommandState({
                            selectionState: selectionState,
                            documentSession: documentSession
                        });
                        if (cmdState.mode == "create") {
                            cmd.execute({
                                commandState: {
                                    mode: 'create'
                                },
                                documentSession: documentSession,
                                selectionState: documentSession.getSelectionState()
                            });
                            console.log('Found ' + word);

                        } else {
                            console.log("Annotated words: " + p.content.substring(selectionState.getAnnotationsForType(cmd.getAnnotationType())[0].startOffset, selectionState.getAnnotationsForType(cmd.getAnnotationType())[0].endOffset));
                            if (cmdState.mode == "delete") {
                                console.log('Error trying to annotate: ' + word + ' because it is already linked.');
                            } else if (cmdState.mode == "expand") {
                                console.log('Error trying to annotate: ' + word + ' because part of the word is already linked.');
                            } else if (cmdState.mode == "truncate") {
                                console.log('Error trying to annotate: ' + word + ' because it is part of the linked word.');
                            }
                            ++numErrors;
                        }

                        //found = p.content.indexOf(word,found+1);
                        ++wordHits;
                    }
                    if (wordHits > 0) {
                        ++totalWordsFound;
                        totalWordHits += wordHits;
                        wordHits[word] = wordHits;
                        document.getElementById('message').innerHTML = "Searching: found " + totalWordsFound + " words, hits: "+totalWordHits;
                    }
                }
            }
        }
        let finalMessage = "Done: found " + totalWordsFound + " words: hits: "+totalWordHits;
        finalMessage += "
";
        for(let hit in wordHits){
            finalMessage += "
"+wordHits[hit] + "
";
        }

        finalMessage += "
";
        document.getElementById('message').innerHTML = finalMessage;
        console.log('total found: ' + totalWordsFound);
        console.log('total errors: ' + numErrors);

        if (callback) callback();
    }

    getWords(callback) {
        let serverURL = window.location.protocol + '//' + window.location.hostname + ':8080/keyWordSet/sampleKeyWordSet';
        console.log('server URL: ' + serverURL);
        request('GET', serverURL, null, function (err, data) {
            if (err) {
                console.error(err);
                this.setState({
                    error: new Error('Loading failed')
                });
                return
            }
            if (data) {
                this.words = [];
                for (let d in data) {
                    this.words.push(data[d].value);
                }
                console.log('finished processing with words: ' + this.words.length);
                // this.render(this.words, cb);
                if (callback) callback(this.words);

                return this.words;
            }
        });
    }

}

class ToggleStrongCommand extends AnnotationCommand {

    // type = 'bold';
    // tagName = 'bold';

    constructor() {
        // super({name: 'bold', nodeType: 'bold'})
        super({name: 'markup', nodeType: 'ext-link'})
    }
}

// ToggleStrongCommand.define({
//     attributes: { type: 'object', default: {} }
// });

// export default ToggleStrongCommand

export default MarkupApp
<|endoftext|>


<commit_before>var _ = require('underscore');

module.exports = function(window, name) {
  // TODO : Look into serialization between the server and the client
  var cache = {};

  window[name] = {
    getItem: function(value) {
      return cache[value];
    },
    setItem: function(value, key) {
      cache[value] = key;
    },
    removeItem: function(value) {
      delete cache[value];
    },

    get length() {
      return _.keys(cache).length;
    }
  };
};
<commit_msg>Implement a shared runtime cache for storage<commit_after>var _ = require('underscore');

// TODO : Remove this in favor of HAPI smart caching
// TODO : Make this conditional as users that implement user behavior on the server will not
// want this.
var globalCache = {};

module.exports = function(window, name) {
  var cache = globalCache[name] = globalCache[name] || {};

  window[name] = {
    getItem: function(value) {
      return cache[value];
    },
    setItem: function(value, key) {
      cache[value] = key;
    },
    removeItem: function(value) {
      delete cache[value];
    },

    get length() {
      return _.keys(cache).length;
    }
  };
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import toSlug from '../../lib/to-slug';
import { Link } from '../../routes';
import { Box, Flex, Text, config } from '../base';
import Icon from '../icon';

const { breakpoints } = config.get();

const Sidebar = ({ open, onDismiss, products, ...props }) => {
  const styles = {
    dismiss: {
      position: 'fixed',
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
      zIndex: 20,
      display: open ? null : 'none',
      [breakpoints[1]]: {
        display: 'none',
      },
    },
    bar: {
      position: 'fixed',
      top: 0,
      bottom: 0,
      left: 0,
      zIndex: 30,
      height: '100vh',
      transform: open ? null : 'translateX(-100%)',
      transition: 'transform .3s cubic-bezier(0.645,  0.045, 0.355, 1.000)',
      overflowX: 'hidden',
      overflowY: 'auto',
      [breakpoints[1]]: {
        transform: null,
      },
    },
    link: {
      cursor: 'pointer',
      textDecoration: 'none',
      opacity: 1,
      transition: 'opacity .15s ease-in',
      ':hover': {
        opacity: 0.5,
        transition: 'opacity .15s ease-in',
      },
      ':focus': {
        opacity: 0.5,
        transition: 'opacity .15s ease-in',
      },
      ':active': {
        opacity: 0.5,
        transition: 'opacity .15s ease-out',
      },
    },
  };

  return (
    <Box>
      <Box
        bgOverlay
        css={styles.dismiss}
        onClick={onDismiss}
      />
      <Box
        {...props}
        bgDark
        width={300}
        css={styles.bar}
      >
        <Flex
          p2
          flexDirection="column"
          justifyContent="flex-start"
          alignItems="center"
          width={1}
          css={{ height: '100%' }}
        >
          <Box width={1} onClick={onDismiss}>
            <Link route="index">
              <Text bold white fontSize={4} css={styles.link}>
                Wattos Space Emporium
              </Text>
            </Link>
          </Box>
          <Flex
            my2
            flexDirection="column"
            justifyContent="space-around"
          >
            <Text my2 bold white caps fontSize={4} is="span">
              Inventory
            </Text>
            {products.map((product, i) => (
              <Box ml1 mb1 key={i} onClick={onDismiss}>
                <Link
                  route="product"
                  params={{ slug: toSlug(product.name) }}
                >
                  <Text gray is="a" css={styles.link}>
                    {product.name}
                  </Text>
                </Link>
              </Box>
            ))}
            <Text left mt3 mb2 bold white caps fontSize={4} is="span">
              About Us
            </Text>
            <Text my2 bold white caps fontSize={4} is="span">
              Another Link
            </Text>
          </Flex>
          <Box center gray width={1} css={{ marginTop: 'auto' }}>
            <Text bold>Wattos Space Emporium</Text>
            <Text>Mos Eisley, Tattooine</Text>
            <Text>© A Long Time Ago</Text>
            <Flex
              mt3
              flexDirection="row"
              flexWrap="no wrap"
              justifyContent="space-around"
              alignItems="center"
            >
              <Icon name="googleplus" />
              <Icon name="twitter" />
              <Icon name="linkedin" />
              <Icon name="github" />
              <Icon name="stackoverflow" />
            </Flex>
          </Box>
        </Flex>
      </Box>
    </Box>
  );
};

Sidebar.propTypes = {
  open: PropTypes.bool,
  products: PropTypes.array,
  onDismiss: PropTypes.func,
};

Sidebar.defaultProps = {
  open: false,
};

export default Sidebar;
<commit_msg>fix sidebar height and inner width<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import toSlug from '../../lib/to-slug';
import { Link } from '../../routes';
import { Box, Flex, Text, config } from '../base';
import Icon from '../icon';

const { breakpoints } = config.get();

const Sidebar = ({ open, onDismiss, products, ...props }) => {
  const styles = {
    dismiss: {
      position: 'fixed',
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
      zIndex: 20,
      display: open ? null : 'none',
      [breakpoints[1]]: {
        display: 'none',
      },
    },
    bar: {
      position: 'fixed',
      top: 0,
      bottom: 0,
      left: 0,
      zIndex: 30,
      // height: '100vh',
      transform: open ? null : 'translateX(-100%)',
      transition: 'transform .3s cubic-bezier(0.645,  0.045, 0.355, 1.000)',
      overflowX: 'hidden',
      overflowY: 'auto',
      [breakpoints[1]]: {
        transform: null,
      },
    },
    link: {
      cursor: 'pointer',
      textDecoration: 'none',
      opacity: 1,
      transition: 'opacity .15s ease-in',
      ':hover': {
        opacity: 0.5,
        transition: 'opacity .15s ease-in',
      },
      ':focus': {
        opacity: 0.5,
        transition: 'opacity .15s ease-in',
      },
      ':active': {
        opacity: 0.5,
        transition: 'opacity .15s ease-out',
      },
    },
  };

  return (
    <Box>
      <Box
        bgOverlay
        css={styles.dismiss}
        onClick={onDismiss}
      />
      <Box
        {...props}
        bgDark
        width={300}
        css={styles.bar}
      >
        <Flex
          p2
          flexDirection="column"
          justifyContent="flex-start"
          alignItems="center"
          width={1}
          css={{ height: '100%' }}
        >
          <Box width={1} onClick={onDismiss}>
            <Link route="index">
              <Text bold white fontSize={4} css={styles.link}>
                Wattos Space Emporium
              </Text>
            </Link>
          </Box>
          <Flex
            my2
            width={1}
            flexDirection="column"
            justifyContent="space-around"
          >
            <Text my2 bold white caps fontSize={4} is="span">
              Inventory
            </Text>
            {products.map((product, i) => (
              <Box ml1 mb1 key={i} onClick={onDismiss}>
                <Link
                  route="product"
                  params={{ slug: toSlug(product.name) }}
                >
                  <Text gray is="a" css={styles.link}>
                    {product.name}
                  </Text>
                </Link>
              </Box>
            ))}
            <Text left mt3 mb2 bold white caps fontSize={4} is="span">
              About Us
            </Text>
            <Text my2 bold white caps fontSize={4} is="span">
              Another Link
            </Text>
          </Flex>
          <Box center gray width={1} css={{ marginTop: 'auto' }}>
            <Text bold>Wattos Space Emporium</Text>
            <Text>Mos Eisley, Tattooine</Text>
            <Text>© A Long Time Ago</Text>
            <Flex
              mt3
              flexDirection="row"
              flexWrap="no wrap"
              justifyContent="space-around"
              alignItems="center"
            >
              <Icon name="googleplus" />
              <Icon name="twitter" />
              <Icon name="linkedin" />
              <Icon name="github" />
              <Icon name="stackoverflow" />
            </Flex>
          </Box>
        </Flex>
      </Box>
    </Box>
  );
};

Sidebar.propTypes = {
  open: PropTypes.bool,
  products: PropTypes.array,
  onDismiss: PropTypes.func,
};

Sidebar.defaultProps = {
  open: false,
};

export default Sidebar;
<|endoftext|>


<commit_before>define(['app',
    "text!views/register/user-preferences/user-alerts.html",
    'underscore',
    'moment',
    'ngDialog',
    'views/search/search-directive',
    'js/common',
    'views/register/directives/register-top-menu',
    'ngDialog',
    'views/register/user-preferences/user-alerts',
    'services/local-storage-service',
    'components/scbd-angularjs-services/services/generic-service',
    'services/role-service'
], function (app, template, _, moment) {

    app.directive("userAlerts", ['$rootScope', 'ngDialog', function ($rootScope, ngDialog) {

        return {
            restrict: "EA",
            template: template,
            replace: true,
            scope: {
                runQuery: '&',
                collection: '@',
                runQueryInPage: '@',
                collectionFilter: '@?'
            },
            link: function ($scope, element, attrs) {},
            controller: ['$rootScope', '$scope', '$http', 'IGenericService', 'realm', '$timeout', '$location', 'roleService', '$route', '$element', 'localStorageService',
                function ($rootScope, $scope, $http, IGenericService, realm, $timeout, $location, roleService, $route, $element, localStorageService) {

                    var systemSearches = [];
                    $scope.user = $rootScope.user;
                    $scope.skipKeywordsFilter = false;
                    $scope.skipTextFilter = false;
                    $scope.systemAlertsSubscription = [];

                    $scope.skipKeywordsFilter = true;
                    $scope.skipTextFilter = true;

                    systemSearches = [{
                        system: true,
                        "filters": [{
                            "type": "custom",
                            "isSystemAlert":"true",
                            "name": "Certificates (IRCC) published indicating that prior informed consent (PIC) has been granted to a user within my jurisdiction",
                            "id": "entitiesToWhomPICGrantedCountry",
                            "query": 'entitiesToWhomPICGrantedCountry_ss:'
                        }],
                        "queryTitle": "Search certificate(s) (IRCC) that are constituted indicating that prior informed consent (PIC) has been granted to a user within my jurisdiction",
                        "meta": {
                            "createdOn": moment.utc().format()
                        }
                    }];

                    if ($scope.user.government) {
                        if (roleService.isPublishingAuthority() ||
                            roleService.isNationalAuthorizedUser() ||
                            roleService.isNationalFocalPoint()) {

                            $scope.showSystemAlerts = true;
                            var query = {
                                realm: realm.value,
                                isSystemAlert: true
                            };

                            IGenericService.query('v2016', 'me/subscriptions', query)
                                .then(function (data) {
                                    $scope.systemAlertsSubscription = data;
                            });
                        }
                    }

                    //==============================================================
                    function loadSavedFilters() {
                        if ($scope.user && $scope.user.isAuthenticated) {
                            var query = {};
                            if ($scope.collectionFilter)
                                query = JSON.parse($scope.collectionFilter);

                            query.realm = realm.value;
                            IGenericService.query('v2016', 'me/subscriptions', query)
                                .then(function (data) {
                                    // if ($scope.collection == "search-queries" && $scope.user.government) {
                                    //     _.first(systemSearches).filters[0].query += $scope.user.government;
                                    //     $scope.userFilters = _.union(systemSearches, data);
                                    // } else
                                        $scope.userFilters = data;
                                });
                        }
                    }

                    //==============================================================
                    $rootScope.$on('signIn', function (evt, user) {
                        $scope.user = user;
                        loadSavedFilters();
                    });

                    //==============================================================
                    $scope.runUserQuery = function (record) {
                        if ($scope.runQuery)
                            $scope.runQuery({
                                filter: record
                            });
                    };

                     //==============================================================
                     $scope.runSystemFilter = function () {
                        $scope.runFilter(systemSearches[0].filters);
                     }
                    //==============================================================
                    $scope.runFilter = function (filters) {

                        if(filters) {

                            localStorageService.set("run-query", filters);

                            if(!$scope.runQueryInPage){
                                window.open(
                                        '/search/run-query/',
                                        '_blank'
                                    );
                            }
                            else
                            {
                                window.location.href =  '/search/run-query';
                            }
                        }
                    };

                    //==============================================================
                    $scope.hasUserSubscribed = function (event) {
                        return $scope.systemAlertsSubscription &&
                            _.some($scope.systemAlertsSubscription, function (alert) {
                                return alert.isSystemAlert &&
                                    _.contains(_.pluck(alert.filters, 'id'), event);
                            });
                    };

                    //==============================================================
                    $scope.subscribe = function (event) {
                        var document = {
                            queryTitle: event + " system alert",
                            isSystemAlert: true,
                            realm: realm.value,
                            sendEmail: true,
                            filters: [{
                                    "type": "national",
                                    "id": event
                                },
                                {
                                    "type": "country",
                                    "id": $scope.user.government
                                }
                            ]
                        };
                        IGenericService.create('v2016', 'me/subscriptions', document)
                            .then(function (data) {
                                document._id = data.id;
                                console.log("ID=" + data.id)
                                $scope.systemAlertsSubscription.push(document);
                            });
                    };

                    //==============================================================
                    $scope.emailSubscribe = function (record, flag) {

                        if (record) {

                            record.sendEmail = flag;

                            operation = IGenericService.update('v2016', 'me/subscriptions', record._id, record);

                            operation.then(function (data) {

                                if (!record._id)
                                    record._id = data.id;

                                //updateRecord(record);
                            });
                        }
                    };

                    //==============================================================
                    $scope.hasUserEmailSubscribed = function (record) {

                        if (record) {

                            if(record.sendEmail){
                                return true;
                            }
                        }
                        return false;
                    };

                    //==============================================================
                    $scope.unsubscribe = function (event) {
                        if ($scope.systemAlertsSubscription) {
                            var event = _.find($scope.systemAlertsSubscription, function (alert) {
                                return alert.isSystemAlert &&
                                    _.contains(_.pluck(alert.filters, 'id'), event);
                            })
                            IGenericService.delete('v2016', 'me/subscriptions', event._id)
                                .then(function (event) {
                                    $scope.systemAlertsSubscription
                                        .splice($scope.systemAlertsSubscription.indexOf(event), 1)
                                });
                        }
                    };

                    //==============================================================
                    $scope.confirmDelete = function (record) {
                        $scope.loading = true;
                        $http.delete('/api/v2016/me/subscriptions/' + record._id)
                            .then(function () {
                                $scope.userFilters.splice($scope.userFilters.indexOf(record), 1);
                            });
                        $scope.loading = false;
                    };

                    //==============================================================
                    $scope.addEdit = function (existingFilter) {
                        if (existingFilter && !existingFilter._id)
                            return;
                        if ($rootScope.user && !$rootScope.user.isAuthenticated) {
                            var signIn = $scope.$on('signIn', function (evt, data) {
                                $scope.addEdit();
                                signIn();
                            });

                            $('#loginDialog').modal("show");
                        } else {

                            var collection = $scope.collection;

                            ngDialog.open({
                                className: 'ngdialog-theme-default wide',
                                template: 'newFilterDialog',
                                controller: ['$scope', 'IGenericService', '$timeout', 'realm', function ($scope, IGenericService, $timeout, realm) {

                                    if (existingFilter) {
                                        $scope.document = angular.copy(existingFilter);
                                        $timeout(function () {
                                            $scope.setSearchFilters(existingFilter.filters);
                                        }, 100);
                                    }
                                    $scope.save = function (document) {
                                        $scope.errors = [];
                                        if (!document || document.queryTitle == '') {
                                            $scope.errors.push('Please enter title of the alert')
                                        }
                                        if (!document || !$scope.setFilters || _.isEmpty($scope.setFilters)) {
                                            $scope.errors.push('Please select at least one filter')
                                        }
                                        if ($scope.errors && $scope.errors.length > 0) {
                                            $("#dialog-errors").animate({
                                                scrollTop: 0
                                            }, 600);
                                            return;
                                        }

                                        $scope.loading = true;
                                        var operation;

                                        document.isSystemAlert = false;
                                        document.filters = _.values($scope.setFilters);
                                        document.realm = realm.value;
                                        if (!document._id)
                                            operation = IGenericService.create('v2016', 'me/subscriptions', document);
                                        else
                                            operation = IGenericService.update('v2016', 'me/subscriptions', document._id, document);

                                        operation.then(function (data) {
                                            $scope.closeDialog();
                                            if (!document._id)
                                                document._id = data.id;
                                            updateRecord(document);
                                        });
                                    };
                                    $scope.closeDialog = function () {
                                        ngDialog.close();
                                    };

                                }]
                            });

                            //==============================================================
                            function updateRecord(document, delay) {
                                if (!$scope.userFilters)
                                    $scope.userFilters = [];
                                var existing = _.findWhere($scope.userFilters, {
                                    '_id': document._id
                                });
                                if (!existing) {
                                    $scope.userFilters.push(document);
                                    existing = document;
                                }
                                existing.pendingStatus = true;
                                IGenericService.get('v2016', 'me/subscriptions', document._id)
                                    .then(function (data) {
                                        existing = _.extend(existing, data);
                                        existing.pendingStatus = false;
                                    })
                                    .catch(function (err) {
                                        if (err && err.status == 404) {
                                            delay = (delay || 0) + 1000
                                            $timeout(updateRecord(document, delay), delay);
                                        }
                                    });
                            }
                        }
                    };

                    loadSavedFilters();
                }
            ]
        };
    }]);
});
<commit_msg>fix alert issue<commit_after>define(['app',
    "text!views/register/user-preferences/user-alerts.html",
    'underscore',
    'moment',
    'ngDialog',
    'views/search/search-directive',
    'js/common',
    'views/register/directives/register-top-menu',
    'ngDialog',
    'views/register/user-preferences/user-alerts',
    'services/local-storage-service',
    'components/scbd-angularjs-services/services/generic-service',
    'services/role-service'
], function (app, template, _, moment) {

    app.directive("userAlerts", ['$rootScope', 'ngDialog', function ($rootScope, ngDialog) {

        return {
            restrict: "EA",
            template: template,
            replace: true,
            scope: {
                runQuery: '&',
                collection: '@',
                runQueryInPage: '@',
                collectionFilter: '@?'
            },
            link: function ($scope, element, attrs) {},
            controller: ['$rootScope', '$scope', '$http', 'IGenericService', 'realm', '$timeout', '$location', 'roleService', '$route', '$element', 'localStorageService',
                function ($rootScope, $scope, $http, IGenericService, realm, $timeout, $location, roleService, $route, $element, localStorageService) {

                    var systemSearches = [];
                    $scope.user = $rootScope.user;
                    $scope.skipKeywordsFilter = false;
                    $scope.skipTextFilter = false;
                    $scope.systemAlertsSubscription = [];

                    $scope.skipKeywordsFilter = true;
                    $scope.skipTextFilter = true;

                    systemSearches = [{
                        system: true,
                        "filters": [{
                            "type": "custom",
                            "isSystemAlert":"true",
                            "name": "Certificates (IRCC) published indicating that prior informed consent (PIC) has been granted to a user within my jurisdiction",
                            "id": "entitiesToWhomPICGrantedCountry",
                            "query": 'entitiesToWhomPICGrantedCountry_ss:' + $scope.user.government
                        }],
                        "queryTitle": "Search certificate(s) (IRCC) that are constituted indicating that prior informed consent (PIC) has been granted to a user within my jurisdiction",
                        "meta": {
                            "createdOn": moment.utc().format()
                        }
                    }];

                    if ($scope.user.government) {
                        if (roleService.isPublishingAuthority() ||
                            roleService.isNationalAuthorizedUser() ||
                            roleService.isNationalFocalPoint()) {

                            $scope.showSystemAlerts = true;
                            var query = {
                                realm: realm.value,
                                isSystemAlert: true
                            };

                            IGenericService.query('v2016', 'me/subscriptions', query)
                                .then(function (data) {
                                    $scope.systemAlertsSubscription = data;
                            });
                        }
                    }

                    //==============================================================
                    function loadSavedFilters() {
                        if ($scope.user && $scope.user.isAuthenticated) {
                            var query = {};
                            if ($scope.collectionFilter)
                                query = JSON.parse($scope.collectionFilter);

                            query.realm = realm.value;
                            IGenericService.query('v2016', 'me/subscriptions', query)
                                .then(function (data) {
                                    // if ($scope.collection == "search-queries" && $scope.user.government) {
                                    //     _.first(systemSearches).filters[0].query += $scope.user.government;
                                    //     $scope.userFilters = _.union(systemSearches, data);
                                    // } else
                                        $scope.userFilters = data;
                                });
                        }
                    }

                    //==============================================================
                    $rootScope.$on('signIn', function (evt, user) {
                        $scope.user = user;
                        loadSavedFilters();
                    });

                    //==============================================================
                    $scope.runUserQuery = function (record) {
                        if ($scope.runQuery)
                            $scope.runQuery({
                                filter: record
                            });
                    };

                     //==============================================================
                     $scope.runSystemFilter = function () {
                        $scope.runFilter(systemSearches[0].filters);
                     }
                    //==============================================================
                    $scope.runFilter = function (filters) {

                        if(filters) {

                            localStorageService.set("run-query", filters);

                            if(!$scope.runQueryInPage){
                                window.open(
                                        '/search/run-query/',
                                        '_blank'
                                    );
                            }
                            else
                            {
                                window.location.href =  '/search/run-query';
                            }
                        }
                    };

                    //==============================================================
                    $scope.hasUserSubscribed = function (event) {
                        return $scope.systemAlertsSubscription &&
                            _.some($scope.systemAlertsSubscription, function (alert) {
                                return alert.isSystemAlert &&
                                    _.contains(_.pluck(alert.filters, 'id'), event);
                            });
                    };

                    //==============================================================
                    $scope.subscribe = function (event) {
                        var document = {
                            queryTitle: event + " system alert",
                            isSystemAlert: true,
                            realm: realm.value,
                            sendEmail: true,
                            filters: [{
                                    "type": "national",
                                    "id": event
                                },
                                {
                                    "type": "country",
                                    "id": $scope.user.government
                                }
                            ]
                        };
                        IGenericService.create('v2016', 'me/subscriptions', document)
                            .then(function (data) {
                                document._id = data.id;
                                console.log("ID=" + data.id)
                                $scope.systemAlertsSubscription.push(document);
                            });
                    };

                    //==============================================================
                    $scope.emailSubscribe = function (record, flag) {

                        if (record) {

                            record.sendEmail = flag;

                            operation = IGenericService.update('v2016', 'me/subscriptions', record._id, record);

                            operation.then(function (data) {

                                if (!record._id)
                                    record._id = data.id;

                                //updateRecord(record);
                            });
                        }
                    };

                    //==============================================================
                    $scope.hasUserEmailSubscribed = function (record) {

                        if (record) {

                            if(record.sendEmail){
                                return true;
                            }
                        }
                        return false;
                    };

                    //==============================================================
                    $scope.unsubscribe = function (event) {
                        if ($scope.systemAlertsSubscription) {
                            var event = _.find($scope.systemAlertsSubscription, function (alert) {
                                return alert.isSystemAlert &&
                                    _.contains(_.pluck(alert.filters, 'id'), event);
                            })
                            IGenericService.delete('v2016', 'me/subscriptions', event._id)
                                .then(function (event) {
                                    $scope.systemAlertsSubscription
                                        .splice($scope.systemAlertsSubscription.indexOf(event), 1)
                                });
                        }
                    };

                    //==============================================================
                    $scope.confirmDelete = function (record) {
                        $scope.loading = true;
                        $http.delete('/api/v2016/me/subscriptions/' + record._id)
                            .then(function () {
                                $scope.userFilters.splice($scope.userFilters.indexOf(record), 1);
                            });
                        $scope.loading = false;
                    };

                    //==============================================================
                    $scope.addEdit = function (existingFilter) {
                        if (existingFilter && !existingFilter._id)
                            return;
                        if ($rootScope.user && !$rootScope.user.isAuthenticated) {
                            var signIn = $scope.$on('signIn', function (evt, data) {
                                $scope.addEdit();
                                signIn();
                            });

                            $('#loginDialog').modal("show");
                        } else {

                            var collection = $scope.collection;

                            ngDialog.open({
                                className: 'ngdialog-theme-default wide',
                                template: 'newFilterDialog',
                                controller: ['$scope', 'IGenericService', '$timeout', 'realm', function ($scope, IGenericService, $timeout, realm) {

                                    if (existingFilter) {
                                        $scope.document = angular.copy(existingFilter);
                                        $timeout(function () {
                                            $scope.setSearchFilters(existingFilter.filters);
                                        }, 100);
                                    }
                                    $scope.save = function (document) {
                                        $scope.errors = [];
                                        if (!document || document.queryTitle == '') {
                                            $scope.errors.push('Please enter title of the alert')
                                        }
                                        if (!document || !$scope.setFilters || _.isEmpty($scope.setFilters)) {
                                            $scope.errors.push('Please select at least one filter')
                                        }
                                        if ($scope.errors && $scope.errors.length > 0) {
                                            $("#dialog-errors").animate({
                                                scrollTop: 0
                                            }, 600);
                                            return;
                                        }

                                        $scope.loading = true;
                                        var operation;

                                        document.isSystemAlert = false;
                                        document.filters = _.values($scope.setFilters);
                                        document.realm = realm.value;
                                        if (!document._id)
                                            operation = IGenericService.create('v2016', 'me/subscriptions', document);
                                        else
                                            operation = IGenericService.update('v2016', 'me/subscriptions', document._id, document);

                                        operation.then(function (data) {
                                            $scope.closeDialog();
                                            if (!document._id)
                                                document._id = data.id;
                                            updateRecord(document);
                                        });
                                    };
                                    $scope.closeDialog = function () {
                                        ngDialog.close();
                                    };

                                }]
                            });

                            //==============================================================
                            function updateRecord(document, delay) {
                                if (!$scope.userFilters)
                                    $scope.userFilters = [];
                                var existing = _.findWhere($scope.userFilters, {
                                    '_id': document._id
                                });
                                if (!existing) {
                                    $scope.userFilters.push(document);
                                    existing = document;
                                }
                                existing.pendingStatus = true;
                                IGenericService.get('v2016', 'me/subscriptions', document._id)
                                    .then(function (data) {
                                        existing = _.extend(existing, data);
                                        existing.pendingStatus = false;
                                    })
                                    .catch(function (err) {
                                        if (err && err.status == 404) {
                                            delay = (delay || 0) + 1000
                                            $timeout(updateRecord(document, delay), delay);
                                        }
                                    });
                            }
                        }
                    };

                    loadSavedFilters();
                }
            ]
        };
    }]);
});
<|endoftext|>