<commit_before>// Chart functions and settings

function pieChart(series) {
  var chart = {
    chart: {
      type: 'pie',
      animation: false,
      spacingBottom: 30
    },
    title: {
      text: null
    },
	plotOptions: {
      pie: {
          allowPointSelect: true,
          dataLabels: {
               enabled: false
           },
          showInLegend: true
	  }
	},
    legend: {
      enabled: true,
      verticalAlign: 'bottom',
      align: 'center',
      layout: 'horizontal',
      style: {
        fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    series: [{
		colorByPoint: true,
		data: series,
		name: i18n.gettext("Count")
    }]
  };
  return chart;
}

function sitesBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'bar',
      animation: false
    },
	  tooltip: {
		  valueDecimals: 1,
		  valueSuffix: '%'
	  },
    title: {
      text: null
    },
    xAxis: {
      categories: categories,
    },
    yAxis: {
      min: 0,
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      labels: {
        formatter: function() {
			return Math.round(Math.abs(this.value),1) + '%';
        }
      }
    },
    series: series
  };
  return chart;
}

function genderBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'column',
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    xAxis: {
      categories: categories,
      labels: {
        step: 1
      },
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      }
    },
    series: series
  };
  return chart;
}

function communicableDiseasesBarChart(categories, series, labels) {

  var chart = {
    chart: {
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    plotOptions: {
      spline: {
        marker: {
          enabled: false
        }
      }
    },
    xAxis: {
      categories: categories,
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      allowDecimals: false,
      min: 0
    },
    series: [{
      type: 'column',
      name: i18n.gettext('Confirmed'),
      data: series[0]
    },{
      type: 'spline',
      name: i18n.gettext('Suspected'),
      data: series[1],
    }]
  };
	return chart;
}

function PipBarChart(weeks, suspected, confirmed, labels) {

	var series = [];
		series.push({
			type: 'spline',
			name: i18n.gettext('Suspected'),
			data: suspected,
			color: "#365286"
		});
	colors = {"B": '#0F79BD',
			  "H3": "#E8E801",
			  "H1N1": "#D22727",
			  "Mixed": "#8F908E"
			 };
	for(var serie in confirmed){
		series.push( {
			'type': 'column',
			'name': confirmed[serie].title,
			'data': confirmed[serie].values,
			'color': colors[confirmed[serie].title]
		});
	}

  var chart = {
		chart: {
			animation: false
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		plotOptions: {
			spline: {
				marker: {
					enabled: false
				}
			},
			series: {
                stacking: 'normal',
				lineWidth: 5
            },
			 column: {
				 pointPadding: 0,
				 borderWidth: 0,
				 groupPadding: 0,
				 shadow: false
			 }
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

function refugeeCommunicableDiseasesChart(categories, series, labels) {
  var chart = {
    chart: {
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: false,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    plotOptions: {
      spline: {
        marker: {
          enabled: false
        }
      }
    },
    xAxis: {
      categories: categories,
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
	  labels: {
        formatter: function () {
          return this.value;
        }
	  },
      allowDecimals: true,
	  min: 0
    },
      series: [
		  {
			  type: 'column',
			  name: i18n.gettext('Suspected'),
			  data: series[0],
			  lineWidth: 5
		  }]
  };
	return chart;
}

//Completeness bar chart for the AFRO Bulletin
function completenessBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'bar',
      animation: false
    },
	  tooltip: {
		  valueDecimals: 1,
		  valueSuffix: '%'
	  },
    title: {
      text: null
    },
    xAxis: {
      min: 0,
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      labels: {
        formatter: function() {
			return Math.round(Math.abs(this.value),1) + '%';
        }
      }
    },
    yAxis: {
      categories: categories,
    },
    series: series
  };
  return chart;
}

//Measles bar chart for the afro bulletin.
function measlesBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'column',
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    xAxis: {
      categories: categories,
      labels: {
        step: 1
      },
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      }
    },
    series: series
  };
  return chart;
}

//Malaria bar chart for the afro bulletin.
function malariaChart(weeks, series, labels) {

  var chart = {
		chart: {
			animation: false,
      type: 'column'
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		plotOptions: {
			spline: {
				marker: {
					enabled: false
				}
			},
			series: {

				lineWidth: 5
      },
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

//Malaria bar chart for the afro bulletin.
function malnutritionChart(weeks, series, labels) {

  var chart = {
		chart: {
			animation: false,
      type: 'spline'
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

// Global chart settings
/*$(function() {
      Highcharts.setOptions({
        colors: ["#0098CB", "#EE2631", "#27EE00", "#074EBF", "#F78900", "#ff0066", "#eeaaee",
          "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
        chart: {
          animation: false,
          backgroundColor: null,
          style: {
            fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
          }
      	},
        credits: {
          enabled: false
        },
        tooltip: {
          enabled: false
        },
        legend: {
          enabled: false
        },
        exporting: {
          enabled: false
        },
        plotOptions: {
          series: {
            animation: false
          },
          pie: {
            states: {
              hover: {
                enabled: false
              }
            },
            dataLabels: {
              enabled: false
            },
            showInLegend: true,
          }
        }
      });
    }
);*/

<commit_msg>corrected AFRO figure-completeness<commit_after>// Chart functions and settings

function pieChart(series) {
  var chart = {
    chart: {
      type: 'pie',
      animation: false,
      spacingBottom: 30
    },
    title: {
      text: null
    },
	plotOptions: {
      pie: {
          allowPointSelect: true,
          dataLabels: {
               enabled: false
           },
          showInLegend: true
	  }
	},
    legend: {
      enabled: true,
      verticalAlign: 'bottom',
      align: 'center',
      layout: 'horizontal',
      style: {
        fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    series: [{
		colorByPoint: true,
		data: series,
		name: i18n.gettext("Count")
    }]
  };
  return chart;
}

function sitesBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'bar',
      animation: false
    },
	  tooltip: {
		  valueDecimals: 1,
		  valueSuffix: '%'
	  },
    title: {
      text: null
    },
    xAxis: {
      categories: categories,
    },
    yAxis: {
      min: 0,
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      labels: {
        formatter: function() {
			return Math.round(Math.abs(this.value),1) + '%';
        }
      }
    },
    series: series
  };
  return chart;
}

function genderBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'column',
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    xAxis: {
      categories: categories,
      labels: {
        step: 1
      },
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      }
    },
    series: series
  };
  return chart;
}

function communicableDiseasesBarChart(categories, series, labels) {

  var chart = {
    chart: {
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    plotOptions: {
      spline: {
        marker: {
          enabled: false
        }
      }
    },
    xAxis: {
      categories: categories,
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      allowDecimals: false,
      min: 0
    },
    series: [{
      type: 'column',
      name: i18n.gettext('Confirmed'),
      data: series[0]
    },{
      type: 'spline',
      name: i18n.gettext('Suspected'),
      data: series[1],
    }]
  };
	return chart;
}

function PipBarChart(weeks, suspected, confirmed, labels) {

	var series = [];
		series.push({
			type: 'spline',
			name: i18n.gettext('Suspected'),
			data: suspected,
			color: "#365286"
		});
	colors = {"B": '#0F79BD',
			  "H3": "#E8E801",
			  "H1N1": "#D22727",
			  "Mixed": "#8F908E"
			 };
	for(var serie in confirmed){
		series.push( {
			'type': 'column',
			'name': confirmed[serie].title,
			'data': confirmed[serie].values,
			'color': colors[confirmed[serie].title]
		});
	}

  var chart = {
		chart: {
			animation: false
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		plotOptions: {
			spline: {
				marker: {
					enabled: false
				}
			},
			series: {
                stacking: 'normal',
				lineWidth: 5
            },
			 column: {
				 pointPadding: 0,
				 borderWidth: 0,
				 groupPadding: 0,
				 shadow: false
			 }
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

function refugeeCommunicableDiseasesChart(categories, series, labels) {
  var chart = {
    chart: {
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: false,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    plotOptions: {
      spline: {
        marker: {
          enabled: false
        }
      }
    },
    xAxis: {
      categories: categories,
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
	  labels: {
        formatter: function () {
          return this.value;
        }
	  },
      allowDecimals: true,
	  min: 0
    },
      series: [
		  {
			  type: 'column',
			  name: i18n.gettext('Suspected'),
			  data: series[0],
			  lineWidth: 5
		  }]
  };
	return chart;
}

//Completeness bar chart for the AFRO Bulletin
function completenessBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'bar',
      animation: false
    },
	  tooltip: {
		  valueDecimals: 1,
		  valueSuffix: '%'
	  },
    title: {
      text: null
    },
    yAxis: {
      min: 0,
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      },
      labels: {
        formatter: function() {
			return Math.round(Math.abs(this.value),1) + '%';
        }
      }
    },
    xAxis: {
      categories: categories
    },
    series: series
  };
  return chart;
}

//Measles bar chart for the afro bulletin.
function measlesBarChart(categories, series, labels) {
  var chart = {
    chart: {
      type: 'column',
      animation: false
    },
    title: {
      text: null
    },
    legend: {
      enabled: true,
      style: {
        fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
      }
    },
    xAxis: {
      categories: categories,
      labels: {
        step: 1
      },
      title: {
        text: labels.xAxis.text,
        align: 'middle'
      }
    },
    yAxis: {
      title: {
        text: labels.yAxis.text,
        align: 'middle'
      }
    },
    series: series
  };
  return chart;
}

//Malaria bar chart for the afro bulletin.
function malariaChart(weeks, series, labels) {

  var chart = {
		chart: {
			animation: false,
      type: 'column'
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		plotOptions: {
			spline: {
				marker: {
					enabled: false
				}
			},
			series: {

				lineWidth: 5
      },
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

//Malaria bar chart for the afro bulletin.
function malnutritionChart(weeks, series, labels) {

  var chart = {
		chart: {
			animation: false,
      type: 'spline'
		},
		title: {
			text: null
		},
		legend: {
			enabled: true,
			style: {
				fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
			}
		},
		xAxis: {
			categories: weeks,
			title: {
				text: labels.xAxis.text,
				align: 'middle'
			}
		},
		yAxis: {
			title: {
				text: labels.yAxis.text,
				align: 'middle'
			},
			allowDecimals: false,
			min: 0
		},
		series: series
	};
	return chart;
}

// Global chart settings
/*$(function() {
      Highcharts.setOptions({
        colors: ["#0098CB", "#EE2631", "#27EE00", "#074EBF", "#F78900", "#ff0066", "#eeaaee",
          "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
        chart: {
          animation: false,
          backgroundColor: null,
          style: {
            fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif'
          }
      	},
        credits: {
          enabled: false
        },
        tooltip: {
          enabled: false
        },
        legend: {
          enabled: false
        },
        exporting: {
          enabled: false
        },
        plotOptions: {
          series: {
            animation: false
          },
          pie: {
            states: {
              hover: {
                enabled: false
              }
            },
            dataLabels: {
              enabled: false
            },
            showInLegend: true,
          }
        }
      });
    }
);*/

<|endoftext|>


<commit_before>
/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
    "ui":  false,
    "files": "build/*",
    "watchOptions": {},
    "server": {
      baseDir: "build",
      directory: true
    },
    "proxy": false,
    "port": 3000,
    "middleware": false,
    "serveStatic": [],
    "ghostMode": {
        "clicks": true,
        "scroll": true,
        "forms": {
            "submit": true,
            "inputs": true,
            "toggles": true
        }
    },
    "logLevel": "info",
    "logPrefix": "BS",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "rewriteRules": [],
    "open": false,
    "browser": "default",
    "cors": true,
    "xip": false,
    "hostnameSuffix": false,
    "reloadOnRestart": false,
    "notify": true,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "scrollRestoreTechnique": "window.name",
    "scrollElements": [],
    "scrollElementMapping": [],
    "reloadDelay": 0,
    "reloadDebounce": 0,
    "reloadThrottle": 0,
    "plugins": [],
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "localOnly": false,
    "codeSync": true,
    "timestamps": true,
    "clientEvents": [
        "scroll",
        "scroll:element",
        "input:text",
        "input:toggles",
        "form:submit",
        "form:reset",
        "click"
    ],
    "socket": {
        "socketIoOptions": {
            "log": false
        },
        "socketIoClientConfig": {
            "reconnectionAttempts": 50
        },
        "path": "/browser-sync/socket.io",
        "clientPath": "/browser-sync",
        "namespace": "/browser-sync",
        "clients": {
            "heartbeatTimeout": 5000
        }
    },
    "tagNames": {
        "less": "link",
        "scss": "link",
        "css": "link",
        "jpg": "img",
        "jpeg": "img",
        "png": "img",
        "svg": "img",
        "gif": "img",
        "js": "script"
    }
};
<commit_msg>Configure browser sync just needed options<commit_after>
/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
    ui: false,
    files: "build/*",
    server: {
        baseDir: "build",
        directory: true
    },
    port: 3000,
    open: false,
    cors: true
};
<|endoftext|>


<commit_before>var insertCss = require('insert-css')
var path = require('path')
var merge = require('lodash/merge')
var ipc = require('electron').ipcRenderer
var remote = require('electron').remote
var dialog = require('electron').dialog
var shell = require('electron').shell

var progressBar = require('./progressBar')
var welcomeScreen = require('./welcome')
var overlay = require('./overlay')
var log = require('../lib/log').Browser()
var i18n = require('../lib/i18n')
var package = require('../package.json')

var prevhash = localStorage.getItem('location')
if (location.hash) localStorage.setItem('location', location.hash)
else if (prevhash) location.hash = prevhash

window.addEventListener('hashchange', function (ev) {
  localStorage.setItem('location', location.hash)
})

var $overlay = document.getElementById('overlay')
var $welcome = document.getElementById('welcome')
var $map = document.getElementById('container')

var showedWelcome = localStorage.getItem('showedWelcome')
if (!showedWelcome) {
  localStorage.setItem('showedWelcome', true)
  welcomeScreen($overlay, $welcome, $map)
} else openMap()

updateSettings()

var serverUrl = 'http://' + remote.getGlobal('osmServerHost')
var id = iD.Context()
  .assetPath('vendor/iD/')
  .preauth({url: serverUrl})
  .minEditableZoom(14)

id.version = package.version

var customDefs = id.container()
  .append('svg')
  .style('position', 'absolute')
  .style('width', '0px')
  .style('height', '0px')
  .attr('id', 'custom-defs')
  .append('defs')

customDefs.append('svg')

id.ui()(document.getElementById('container'), function onLoad () {
  var links = document.querySelectorAll('a[href^="http"]')
  links.forEach(function (link) {
    var href = link.getAttribute('href')
    link.onclick = function (event) {
      event.preventDefault()
      shell.openExternal(href)
      return false
    }
  })

  var contributeBtn = document.querySelector(".overlay-layer-attribution a")
  if (contributeBtn) contributeBtn.innerHTML = i18n('feedback-contribute-button')

  // Update label on map move
  var aboutList = id.container().select('#about-list')
  var map = id.map();
  var latlon = aboutList.append('li')
  .append('span')
  .text(latlonToPosString(map.center()))
  map.on('move', function () {
    var pos = map.center()
    var s = latlonToPosString(pos)
    latlon.text(s)
  })

  updateSettings()
})

window.onbeforeunload = function () { id.save() }

function openMap () {
  $overlay.innerHTML = overlay()
  $overlay.style = 'visibility: visible;'
  $map.style = 'visibility: visible;'
  $welcome.style = 'display: none;'
}

ipc.on('updated-settings', function () {
  updateSettings()
  ipc.send('refresh-window')
})
ipc.on('import-error', console.error)
ipc.on('import-complete', importComplete)
ipc.on('import-progress', importProgress)
ipc.on('zoom-to-data-request', zoomToDataRequest)
ipc.on('zoom-to-data-response', zoomToDataResponse)
ipc.on('zoom-to-latlon-response', zoomToLatLonResponse)

function updateSettings () {
  var presets = ipc.sendSync('get-user-data', 'presets')
  var customCss = ipc.sendSync('get-user-data', 'css')
  var imagery = ipc.sendSync('get-user-data', 'imagery')
  var icons = ipc.sendSync('get-user-data', 'icons')

  if (presets) {
    if (!id) iD.data.presets = merge(iD.data.presets, presets)
  }
  if (customCss) insertCss(customCss)
  if (imagery) {
    if (!imagery.id) {
      imagery = imagery.map(function (i) { i.id = i.name; return i; })
      console.warn('imagery.json should include an id -- using name instead.', imagery)
    }
    iD.data.imagery = imagery
  }
  if (icons) {
    var parser = new DOMParser()
    var iconsSvg = parser.parseFromString(icons, 'image/svg+xml').documentElement
    var defs = customDefs && customDefs.node()
    if (defs) defs.replaceChild(iconsSvg, defs.firstChild)
  }
  log('settings updated')
}

function zoomToDataRequest () {
  ipc.send('zoom-to-data-get-centroid')
}

function importComplete (_, filename) {
  var progress = document.body.querySelector('#progress')
  progress.innerHTML = ''
}

function importProgress (_, filename, index, total) {
  var progress = document.body.querySelector('#progress')
  progress.innerHTML = progressBar(path.basename(filename), index, total)
}

function zoomToDataResponse (_, loc) {
  translateAndZoomToLocation(loc, 14)
}

function translateAndZoomToLocation (loc, zoom) {
  id.map().centerEase(loc, 1000)
  setTimeout(function () {
    id.map().zoom(zoom)
  }, 1000)
}
function zoomToLatLonResponse (_, lat, lon) {
  id.map().centerEase([lat, lon], 1000)
  setTimeout(function () {
    id.map().zoom(15)
  }, 1000)
}

function latlonToPosString (pos) {
  pos[0] = (Math.floor(pos[0] * 1000000) / 1000000).toString()
  pos[1] = (Math.floor(pos[1] * 1000000) / 1000000).toString()
  while (pos[0].length < 10) pos[0] += '0'
  while (pos[1].length < 10) pos[1] += '0'
  return pos.toString()
}
<commit_msg>fix: only merge the subset of preset fields that are necessary for iD to run<commit_after>var insertCss = require('insert-css')
var path = require('path')
var merge = require('lodash/merge')
var ipc = require('electron').ipcRenderer
var remote = require('electron').remote
var dialog = require('electron').dialog
var shell = require('electron').shell

var progressBar = require('./progressBar')
var welcomeScreen = require('./welcome')
var overlay = require('./overlay')
var log = require('../lib/log').Browser()
var i18n = require('../lib/i18n')
var package = require('../package.json')

var prevhash = localStorage.getItem('location')
if (location.hash) localStorage.setItem('location', location.hash)
else if (prevhash) location.hash = prevhash

window.addEventListener('hashchange', function (ev) {
  localStorage.setItem('location', location.hash)
})

var $overlay = document.getElementById('overlay')
var $welcome = document.getElementById('welcome')
var $map = document.getElementById('container')

var showedWelcome = localStorage.getItem('showedWelcome')
if (!showedWelcome) {
  localStorage.setItem('showedWelcome', true)
  welcomeScreen($overlay, $welcome, $map)
} else openMap()

updateSettings()

var serverUrl = 'http://' + remote.getGlobal('osmServerHost')
var id = iD.Context()
  .assetPath('vendor/iD/')
  .preauth({url: serverUrl})
  .minEditableZoom(14)

id.version = package.version

var customDefs = id.container()
  .append('svg')
  .style('position', 'absolute')
  .style('width', '0px')
  .style('height', '0px')
  .attr('id', 'custom-defs')
  .append('defs')

customDefs.append('svg')

id.ui()(document.getElementById('container'), function onLoad () {
  var links = document.querySelectorAll('a[href^="http"]')
  links.forEach(function (link) {
    var href = link.getAttribute('href')
    link.onclick = function (event) {
      event.preventDefault()
      shell.openExternal(href)
      return false
    }
  })

  var contributeBtn = document.querySelector(".overlay-layer-attribution a")
  if (contributeBtn) contributeBtn.innerHTML = i18n('feedback-contribute-button')

  // Update label on map move
  var aboutList = id.container().select('#about-list')
  var map = id.map();
  var latlon = aboutList.append('li')
  .append('span')
  .text(latlonToPosString(map.center()))
  map.on('move', function () {
    var pos = map.center()
    var s = latlonToPosString(pos)
    latlon.text(s)
  })

  updateSettings()
})

window.onbeforeunload = function () { id.save() }

function openMap () {
  $overlay.innerHTML = overlay()
  $overlay.style = 'visibility: visible;'
  $map.style = 'visibility: visible;'
  $welcome.style = 'display: none;'
}

ipc.on('updated-settings', function () {
  updateSettings()
  ipc.send('refresh-window')
})
ipc.on('import-error', console.error)
ipc.on('import-complete', importComplete)
ipc.on('import-progress', importProgress)
ipc.on('zoom-to-data-request', zoomToDataRequest)
ipc.on('zoom-to-data-response', zoomToDataResponse)
ipc.on('zoom-to-latlon-response', zoomToLatLonResponse)

function updateSettings () {
  var presets = ipc.sendSync('get-user-data', 'presets')
  var customCss = ipc.sendSync('get-user-data', 'css')
  var imagery = ipc.sendSync('get-user-data', 'imagery')
  var icons = ipc.sendSync('get-user-data', 'icons')

  if (presets) {
    if (!id) {
      presets.fields = merge(iD.data.presets.fields, presets.fields)
      iD.data.presets = presets
    }
  }
  if (customCss) insertCss(customCss)
  if (imagery) {
    if (!imagery.id) {
      imagery = imagery.map(function (i) { i.id = i.name; return i; })
      console.warn('imagery.json should include an id -- using name instead.', imagery)
    }
    iD.data.imagery = imagery
  }
  if (icons) {
    var parser = new DOMParser()
    var iconsSvg = parser.parseFromString(icons, 'image/svg+xml').documentElement
    var defs = customDefs && customDefs.node()
    if (defs) defs.replaceChild(iconsSvg, defs.firstChild)
  }
  log('settings updated')
}

function zoomToDataRequest () {
  ipc.send('zoom-to-data-get-centroid')
}

function importComplete (_, filename) {
  var progress = document.body.querySelector('#progress')
  progress.innerHTML = ''
}

function importProgress (_, filename, index, total) {
  var progress = document.body.querySelector('#progress')
  progress.innerHTML = progressBar(path.basename(filename), index, total)
}

function zoomToDataResponse (_, loc) {
  translateAndZoomToLocation(loc, 14)
}

function translateAndZoomToLocation (loc, zoom) {
  id.map().centerEase(loc, 1000)
  setTimeout(function () {
    id.map().zoom(zoom)
  }, 1000)
}
function zoomToLatLonResponse (_, lat, lon) {
  id.map().centerEase([lat, lon], 1000)
  setTimeout(function () {
    id.map().zoom(15)
  }, 1000)
}

function latlonToPosString (pos) {
  pos[0] = (Math.floor(pos[0] * 1000000) / 1000000).toString()
  pos[1] = (Math.floor(pos[1] * 1000000) / 1000000).toString()
  while (pos[0].length < 10) pos[0] += '0'
  while (pos[1].length < 10) pos[1] += '0'
  return pos.toString()
}
<|endoftext|>


<commit_before>import Orbit from 'orbit/core';
import Transformable from 'orbit/transformable';
import Requestable from 'orbit/requestable';

var RestStore = function(idField) {
  Orbit.assert('RestStore requires Orbit.Promise be defined', Orbit.Promise);
  Orbit.assert('RestStore requires Orbit.ajax be defined', Orbit.ajax);

  this.idField = idField || 'id';
  this.headers = undefined;

  this._cache = {};

  Transformable.extend(this);
  Requestable.extend(this, ['find', 'create', 'update', 'patch', 'destroy']);
};

RestStore.prototype = {
  constructor: RestStore,

  /////////////////////////////////////////////////////////////////////////////
  // Transformable interface implementation
  /////////////////////////////////////////////////////////////////////////////

  _insertRecord: function(data) {
    var _this = this;
    var orbitId = data[Orbit.idField];

    return this.ajax(this.buildURL(), 'POST', {data: this.serialize(data)}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId) {
          record[Orbit.idField] = orbitId;
          _this._cache[orbitId] = record;
        }

        return record;
      }
    );
  },

  _updateRecord: function(data) {
    var _this = this;
    var orbitId = data[Orbit.idField];

    return this.ajax(this.buildURL(data[this.idField]), 'PUT', {data: data}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId) {
          record[Orbit.idField] = orbitId;
          _this._cache[orbitId] = record;
        }

        return record;
      }
    );
  },

  _patchRecord: function(data) {
    var _this = this,
        id = data[this.idField],
        orbitId = data[Orbit.idField];

    delete data[this.idField];

    return this.ajax(this.buildURL(id), 'PATCH', {data: data}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId) {
          record[Orbit.idField] = orbitId;
          _this._cache[orbitId] = record;
        }

        return record;
      }
    );
  },

  _destroyRecord: function(data) {
    return this.ajax(this.buildURL(data[this.idField]), 'DELETE');
  },

  /////////////////////////////////////////////////////////////////////////////
  // Requestable interface implementation
  /////////////////////////////////////////////////////////////////////////////

  _find: function(id) {
    return this.ajax(this.buildURL(id), 'GET');
  },

  _create: function(data) {
    return this.insertRecord(data);
  },

  _update: function(data) {
    return this.updateRecord(data);
  },

  _patch: function(data) {
    return this.patchRecord(data);
  },

  _destroy: function(data) {
    return this.destroyRecord(data);
  },

  /////////////////////////////////////////////////////////////////////////////
  // Public
  /////////////////////////////////////////////////////////////////////////////

  retrieve: function(id) {
    if (typeof id === 'object') {
      id = id[Orbit.idField];
    }
    return this._cache[id];
  },

  /////////////////////////////////////////////////////////////////////////////
  // Internals
  /////////////////////////////////////////////////////////////////////////////

  ajax: function(url, type, hash) {
    var _this = this;

    return new Orbit.Promise(function(resolve, reject) {
      hash = hash || {};
      hash.url = url;
      hash.type = type;
      hash.dataType = 'json';
      hash.context = _this;

      if (hash.data && type !== 'GET') {
        hash.contentType = 'application/json; charset=utf-8';
        hash.data = JSON.stringify(hash.data);
      }

      if (_this.headers !== undefined) {
        var headers = _this.headers;
        hash.beforeSend = function (xhr) {
          for (var key in headers) {
            if (headers.hasOwnProperty(key)) {
              xhr.setRequestHeader(key, headers[key]);
            }
          }
        };
      }

      hash.success = function(json) {
        console.log('ajax success', json);
        resolve(json);
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        if (jqXHR) {
          jqXHR.then = null;
        }
        console.log('ajax error', jqXHR);

        reject(jqXHR);
      };

      Orbit.ajax(hash);
    });
  },

  buildURL: function(id) {
    var host = this.host,
        namespace = this.namespace,
        url = [];

    if (host) { url.push(host); }
    if (namespace) { url.push(namespace); }
    if (id) { url.push(id); }

    url = url.join('/');
    if (!host) { url = '/' + url; }

    return url;
  },

  serialize: function(data) {
    var serialized = Orbit.clone(data);
    delete serialized[Orbit.idField];
    return serialized;
  },

  deserialize: function(data) {
    return data;
  }
};

export default RestStore;<commit_msg>Fix serialization for updates and patches; Always assign an orbitId on inserts<commit_after>import Orbit from 'orbit/core';
import Transformable from 'orbit/transformable';
import Requestable from 'orbit/requestable';

var RestStore = function(idField) {
  Orbit.assert('RestStore requires Orbit.Promise be defined', Orbit.Promise);
  Orbit.assert('RestStore requires Orbit.ajax be defined', Orbit.ajax);

  this.idField = idField || 'id';
  this.headers = undefined;

  this._cache = {};

  Transformable.extend(this);
  Requestable.extend(this, ['find', 'create', 'update', 'patch', 'destroy']);
};

RestStore.prototype = {
  constructor: RestStore,

  /////////////////////////////////////////////////////////////////////////////
  // Transformable interface implementation
  /////////////////////////////////////////////////////////////////////////////

  _insertRecord: function(data) {
    var _this = this;
    var orbitId = data[Orbit.idField];

    return this.ajax(this.buildURL(), 'POST', {data: this.serialize(data)}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId === undefined) {
          orbitId = Orbit.generateId();
        }
        record[Orbit.idField] = orbitId;
        _this._cache[orbitId] = record;

        return record;
      }
    );
  },

  _updateRecord: function(data) {
    var _this = this;
    var orbitId = data[Orbit.idField];

    return this.ajax(this.buildURL(data[this.idField]), 'PUT', {data: this.serialize(data)}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId) {
          record[Orbit.idField] = orbitId;
          _this._cache[orbitId] = record;
        }

        return record;
      }
    );
  },

  _patchRecord: function(data) {
    var _this = this,
        id = data[this.idField],
        orbitId = data[Orbit.idField];

    delete data[this.idField];

    return this.ajax(this.buildURL(id), 'PATCH', {data: this.serialize(data)}).then(
      function(raw) {
        var record = _this.deserialize(raw);

        if (orbitId) {
          record[Orbit.idField] = orbitId;
          _this._cache[orbitId] = record;
        }

        return record;
      }
    );
  },

  _destroyRecord: function(data) {
    return this.ajax(this.buildURL(data[this.idField]), 'DELETE');
  },

  /////////////////////////////////////////////////////////////////////////////
  // Requestable interface implementation
  /////////////////////////////////////////////////////////////////////////////

  _find: function(id) {
    return this.ajax(this.buildURL(id), 'GET');
  },

  _create: function(data) {
    return this.insertRecord(data);
  },

  _update: function(data) {
    return this.updateRecord(data);
  },

  _patch: function(data) {
    return this.patchRecord(data);
  },

  _destroy: function(data) {
    return this.destroyRecord(data);
  },

  /////////////////////////////////////////////////////////////////////////////
  // Public
  /////////////////////////////////////////////////////////////////////////////

  retrieve: function(id) {
    if (typeof id === 'object') {
      id = id[Orbit.idField];
    }
    return this._cache[id];
  },

  /////////////////////////////////////////////////////////////////////////////
  // Internals
  /////////////////////////////////////////////////////////////////////////////

  ajax: function(url, type, hash) {
    var _this = this;

    return new Orbit.Promise(function(resolve, reject) {
      hash = hash || {};
      hash.url = url;
      hash.type = type;
      hash.dataType = 'json';
      hash.context = _this;

      if (hash.data && type !== 'GET') {
        hash.contentType = 'application/json; charset=utf-8';
        hash.data = JSON.stringify(hash.data);
      }

      if (_this.headers !== undefined) {
        var headers = _this.headers;
        hash.beforeSend = function (xhr) {
          for (var key in headers) {
            if (headers.hasOwnProperty(key)) {
              xhr.setRequestHeader(key, headers[key]);
            }
          }
        };
      }

      hash.success = function(json) {
        console.log('ajax success', json);
        resolve(json);
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        if (jqXHR) {
          jqXHR.then = null;
        }
        console.log('ajax error', jqXHR);

        reject(jqXHR);
      };

      Orbit.ajax(hash);
    });
  },

  buildURL: function(id) {
    var host = this.host,
        namespace = this.namespace,
        url = [];

    if (host) { url.push(host); }
    if (namespace) { url.push(namespace); }
    if (id) { url.push(id); }

    url = url.join('/');
    if (!host) { url = '/' + url; }

    return url;
  },

  serialize: function(data) {
    var serialized = Orbit.clone(data);
    delete serialized[Orbit.idField];
    return serialized;
  },

  deserialize: function(data) {
    return data;
  }
};

export default RestStore;<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

document.addEventListener('DOMContentLoaded', function() {
  PhotoImport.load();
});

/**
 * The main Photo App object.
 * @param {HTMLElement} dom Container.
 * @param {FileSystem} filesystem Local file system.
 * @param {Object} params Parameters.
 * @constructor
 */
function PhotoImport(dom, filesystem, params) {
  this.filesystem_ = filesystem;
  this.dom_ = dom;
  this.document_ = this.dom_.ownerDocument;
  this.metadataCache_ = params.metadataCache;
  this.volumeManager_ = new VolumeManager();
  this.copyManager_ = FileCopyManagerWrapper.getInstance(this.filesystem_.root);
  this.mediaFilesList_ = null;
  this.destination_ = null;

  this.initDom_();
  this.initDestination_();
  this.loadSource_(params.source);
}

PhotoImport.prototype = { __proto__: cr.EventTarget.prototype };

/**
 * Single item width.
 * Keep in sync with .grid-item rule in photo_import.css.
 */
PhotoImport.ITEM_WIDTH = 164 + 8;

/**
 * Directory name on the GData containing the imported photos.
 * TODO(dgozman): localize
 */
PhotoImport.GDATA_PHOTOS_DIR = 'My Photos';

/**
 * Loads app in the document body.
 * @param {FileSystem=} opt_filesystem Local file system.
 * @param {Object} opt_params Parameters.
 */
PhotoImport.load = function(opt_filesystem, opt_params) {
  ImageUtil.metrics = metrics;

  var hash = location.hash ? location.hash.substr(1) : '';
  var params = opt_params || {};
  if (!params.source) params.source = hash;
  if (!params.metadataCache) params.metadataCache = MetadataCache.createFull();

  function onFilesystem(filesystem) {
    var dom = document.querySelector('.photo-import');
    new PhotoImport(dom, filesystem, params);
  }

  var api = chrome.fileBrowserPrivate || window.top.chrome.fileBrowserPrivate;
  api.getStrings(function(strings) {
    loadTimeData.data = strings;

    if (opt_filesystem) {
      onFilesystem(opt_filesystem);
    } else {
      api.requestLocalFileSystem(onFilesystem);
    }
  });
};

/**
 * One-time initialization of dom elements.
 * @private
 */
PhotoImport.prototype.initDom_ = function() {
  this.dom_.setAttribute('loading', '');
  this.dom_.ownerDocument.defaultView.addEventListener(
      'resize', this.onResize_.bind(this));

  this.spinner_ = this.dom_.querySelector('.spinner');

  this.document_.querySelector('title').textContent =
      loadTimeData.getString('PHOTO_IMPORT_TITLE');
  this.dom_.querySelector('.caption').textContent =
      loadTimeData.getString('PHOTO_IMPORT_CAPTION');
  this.selectAllNone_ = this.dom_.querySelector('.select');
  this.selectAllNone_.addEventListener('click',
      this.onSelectAllNone_.bind(this));

  this.dom_.querySelector('label[for=delete-after-checkbox]').textContent =
      loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER');
  this.selectedCount_ = this.dom_.querySelector('.selected-count');

  this.importButton_ = this.dom_.querySelector('button.import');
  this.importButton_.textContent =
      loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON');
  this.importButton_.addEventListener('click', this.onImportClick_.bind(this));

  this.grid_ = this.dom_.querySelector('grid');
  cr.ui.Grid.decorate(this.grid_);
  this.grid_.itemConstructor = GridItem.bind(null, this);
  this.fileList_ = new cr.ui.ArrayDataModel([]);
  this.grid_.selectionModel = new cr.ui.ListSelectionModel();
  this.grid_.dataModel = this.fileList_;
  this.grid_.selectionModel.addEventListener('change',
      this.onSelectionChanged_.bind(this));
  this.onSelectionChanged_();

  this.importingDialog_ = new ImportingDialog(this.dom_, this.copyManager_,
      this.metadataCache_);
};

/**
 * One-time initialization of destination directory.
 * @private
 */
PhotoImport.prototype.initDestination_ = function() {
  var onError = this.onError_.bind(
      this, loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));

  var onDirectory = function(dir) {
    this.destination_ = dir;
    // This may enable the import button, so check that.
    this.onSelectionChanged_();
  }.bind(this);

  var onMounted = function() {
    var dir = PathUtil.join(RootDirectory.GDATA, PhotoImport.GDATA_PHOTOS_DIR);
    util.getOrCreateDirectory(this.filesystem_.root, dir, onDirectory, onError);
  }.bind(this);

  if (this.volumeManager_.isMounted(RootDirectory.GDATA)) {
    onMounted();
  } else {
    this.volumeManager_.mountGData(onMounted, onError);
  }
};

/**
 * Load the source contents.
 * @param {string} source Path to source.
 * @private
 */
PhotoImport.prototype.loadSource_ = function(source) {
  var onTraversed = function(results) {
    this.dom_.removeAttribute('loading');
    this.mediaFilesList_ = results.filter(FileType.isImageOrVideo);
    this.fillGrid_();
  }.bind(this);

  var onEntry = function(entry) {
    util.traverseTree(entry, onTraversed, 0 /* infinite depth */,
        FileType.isVisible);
  }.bind(this);

  var onError = this.onError_.bind(
      this, loadTimeData.getString('PHOTO_IMPORT_SOURCE_ERROR'));

  util.resolvePath(this.filesystem_.root, source, onEntry, onError);
};

/**
 * Renders files into grid.
 * @private
 */
PhotoImport.prototype.fillGrid_ = function() {
  if (!this.mediaFilesList_) return;
  this.fileList_.splice(0, this.fileList_.length);
  this.fileList_.push.apply(this.fileList_, this.mediaFilesList_);
};

/**
 * Creates groups for files based on modification date.
 * @param {Array.<Entry>} files File list.
 * @param {Object} filesystem Filesystem metadata.
 * @return {Array.<Object>} List of grouped items.
 * @private
 */
PhotoImport.prototype.createGroups_ = function(files, filesystem) {
  var dateFormatter = v8Intl.DateTimeFormat(
      [] /* default locale */,
      {year: 'numeric', month: 'short', day: 'numeric'});

  var columns = this.grid_.columns;

  var unknownGroup = {
    type: 'group',
    date: 0,
    title: loadTimeData.getString('PHOTO_IMPORT_UNKNOWN_DATE'),
    items: []
  };

  var groupsMap = {};

  for (var index = 0; index < files.length; index++) {
    var props = filesystem[index];
    var item = { type: 'entry', entry: files[index] };

    if (!props || !props.modificationTime) {
      item.group = unknownGroup;
      unknownGroup.items.push(item);
      continue;
    }

    var date = new Date(props.modificationTime);
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);

    var time = date.getTime();
    if (!(time in groupsMap)) {
      groupsMap[time] = {
        type: 'group',
        date: date,
        title: dateFormatter.format(date),
        items: []
      };
    }

    var group = groupsMap[time];
    group.items.push(item);
    item.group = group;
  }

  var groups = [];
  for (var time in groupsMap) {
    if (groupsMap.hasOwnProperty(time)) {
      groups.push(groupsMap[time]);
    }
  }
  if (unknownGroup.items.length > 0)
    groups.push(unknownGroup);

  groups.sort(function(a, b) {
    return b.date.getTime() - a.date.getTime();
  });

  var list = [];
  for (var index = 0; index < groups.length; index++) {
    var group = groups[index];

    list.push(group);
    for (var t = 1; t < columns; t++) {
      list.push({ type: 'empty' });
    }

    for (var j = 0; j < group.items.length; j++) {
      list.push(group.items[j]);
    }

    var count = group.items.length;
    while (count % columns != 0) {
      list.push({ type: 'empty' });
      count++;
    }
  }

  return list;
};

/**
 * Decorates grid item.
 * @param {HTMLLIElement} li The list item.
 * @param {FileEntry} entry The file entry.
 * @private
 */
PhotoImport.prototype.decorateGridItem_ = function(li, entry) {
  li.className = 'grid-item';
  li.entry = entry;

  var frame = this.document_.createElement('div');
  frame.className = 'grid-frame';
  li.appendChild(frame);

  var box = this.document_.createElement('div');
  box.className = 'img-container';
  this.metadataCache_.get(entry, 'thumbnail|filesystem',
      function(metadata) {
        new ThumbnailLoader(entry.toURL(),
                            ThumbnailLoader.LoaderType.IMAGE,
                            metadata).
            load(box, ThumbnailLoader.FillMode.FIT);
      });
  frame.appendChild(box);

  var check = this.document_.createElement('div');
  check.className = 'check';
  li.appendChild(check);
};

/**
 * Handles the 'pick all/none' action.
 * @private
 */
PhotoImport.prototype.onSelectAllNone_ = function() {
  var sm = this.grid_.selectionModel;
  if (sm.selectedIndexes.length == this.fileList_.length) {
    sm.unselectAll();
  } else {
    sm.selectAll();
  }
};

/**
 * Show error message.
 * @param {string} message Error message.
 * @private
 */
PhotoImport.prototype.onError_ = function(message) {
  // TODO
};

/**
 * Resize event handler.
 * @private
 */
PhotoImport.prototype.onResize_ = function() {
  var g = this.grid_;
  g.startBatchUpdates();
  setTimeout(function() {
    g.columns = 0;
    g.redraw();
    g.endBatchUpdates();
  }, 0);
};

/**
 * @return {Array.<Object>} The list of selected entries.
 * @private
 */
PhotoImport.prototype.getSelectedItems_ = function() {
  var indexes = this.grid_.selectionModel.selectedIndexes;
  var list = [];
  for (var i = 0; i < indexes.length; i++) {
    list.push(this.fileList_.item(indexes[i]));
  }
  return list;
};

/**
 * Event handler for picked items change.
 * @private
 */
PhotoImport.prototype.onSelectionChanged_ = function() {
  var count = this.grid_.selectionModel.selectedIndexes.length;
  this.selectedCount_.textContent = count == 0 ? '' :
      count == 1 ? loadTimeData.getString('PHOTO_IMPORT_ONE_SELECTED') :
                   loadTimeData.getStringF('PHOTO_IMPORT_MANY_SELECTED', count);
  this.importButton_.disabled = count == 0 || this.destination_ == null;
  this.selectAllNone_.textContent = loadTimeData.getString(
      count == this.fileList_.length && count > 0 ?
          'PHOTO_IMPORT_SELECT_NONE' : 'PHOTO_IMPORT_SELECT_ALL');
};

/**
 * Event handler for import button click.
 * @param {Event} event The event.
 * @private
 */
PhotoImport.prototype.onImportClick_ = function(event) {
  var entries = this.getSelectedItems_();
  var move = this.dom_.querySelector('#delete-after-checkbox').checked;

  var percentage = Math.round(entries.length / this.fileList_.length * 100);
  metrics.recordMediumCount('PhotoImport.ImportCount', entries.length);
  metrics.recordSmallCount('PhotoImport.ImportPercentage', percentage);

  this.importingDialog_.show(entries, this.destination_, move);
};

/**
 * Item in the grid.
 * @param {PhotoImport} app Application instance.
 * @param {Entry} entry File entry.
 * @constructor
 */
function GridItem(app, entry) {
  var li = app.document_.createElement('li');
  li.__proto__ = GridItem.prototype;
  app.decorateGridItem_(li, entry);
  return li;
}

GridItem.prototype = {
  __proto__: cr.ui.ListItem.prototype,
  get label() {},
  set label(value) {}
};

/**
 * Creates a selection controller that is to be used with grid.
 * @param {cr.ui.ListSelectionModel} selectionModel The selection model to
 *     interact with.
 * @param {cr.ui.Grid} grid The grid to interact with.
 * @constructor
 * @extends {!cr.ui.ListSelectionController}
 */
function GridSelectionController(selectionModel, grid) {
  this.selectionModel_ = selectionModel;
  this.grid_ = grid;
}

/**
 * Extends cr.ui.ListSelectionController.
 */
GridSelectionController.prototype.__proto__ =
    cr.ui.ListSelectionController.prototype;

/** @override */
GridSelectionController.prototype.getIndexBelow = function(index) {
  if (index == this.getLastIndex()) {
    return -1;
  }

  var dm = this.grid_.dataModel;
  var columns = this.grid_.columns;
  var min = (Math.floor(index / columns) + 1) * columns;

  for (var row = 1; true; row++) {
    var end = index + columns * row;
    var start = Math.max(min, index + columns * (row - 1));
    if (start > dm.length) break;

    for (var i = end; i > start; i--) {
      if (i < dm.length && dm.item(i).type == 'entry')
        return i;
    }
  }

  return this.getLastIndex();
};

/** @override */
GridSelectionController.prototype.getIndexAbove = function(index) {
  if (index == this.getFirstIndex()) {
    return -1;
  }

  var dm = this.grid_.dataModel;
  index -= this.grid_.columns;
  while (index >= 0 && dm.item(index).type != 'entry') {
    index--;
  }

  return index < 0 ? this.getFirstIndex() : index;
};

/** @override */
GridSelectionController.prototype.getIndexBefore = function(index) {
  var dm = this.grid_.dataModel;
  index--;
  while (index >= 0 && dm.item(index).type != 'entry') {
    index--;
  }
  return index;
};

/** @override */
GridSelectionController.prototype.getIndexAfter = function(index) {
  var dm = this.grid_.dataModel;
  index++;
  while (index < dm.length && dm.item(index).type != 'entry') {
    index++;
  }
  return index == dm.length ? -1 : index;
};

/** @override */
GridSelectionController.prototype.getFirstIndex = function() {
  var dm = this.grid_.dataModel;
  for (var index = 0; index < dm.length; index++) {
    if (dm.item(index).type == 'entry')
      return index;
  }
  return -1;
};

/** @override */
GridSelectionController.prototype.getLastIndex = function() {
  var dm = this.grid_.dataModel;
  for (var index = dm.length - 1; index >= 0; index--) {
    if (dm.item(index).type == 'entry')
      return index;
  }
  return -1;
};
<commit_msg>Fixed wrong constant names to make Importer working again.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

document.addEventListener('DOMContentLoaded', function() {
  PhotoImport.load();
});

/**
 * The main Photo App object.
 * @param {HTMLElement} dom Container.
 * @param {FileSystem} filesystem Local file system.
 * @param {Object} params Parameters.
 * @constructor
 */
function PhotoImport(dom, filesystem, params) {
  this.filesystem_ = filesystem;
  this.dom_ = dom;
  this.document_ = this.dom_.ownerDocument;
  this.metadataCache_ = params.metadataCache;
  this.volumeManager_ = new VolumeManager();
  this.copyManager_ = FileCopyManagerWrapper.getInstance(this.filesystem_.root);
  this.mediaFilesList_ = null;
  this.destination_ = null;

  this.initDom_();
  this.initDestination_();
  this.loadSource_(params.source);
}

PhotoImport.prototype = { __proto__: cr.EventTarget.prototype };

/**
 * Single item width.
 * Keep in sync with .grid-item rule in photo_import.css.
 */
PhotoImport.ITEM_WIDTH = 164 + 8;

/**
 * Directory name on the Drive containing the imported photos.
 * TODO(dgozman): localize
 */
PhotoImport.DRIVE_PHOTOS_DIR = 'My Photos';

/**
 * Loads app in the document body.
 * @param {FileSystem=} opt_filesystem Local file system.
 * @param {Object} opt_params Parameters.
 */
PhotoImport.load = function(opt_filesystem, opt_params) {
  ImageUtil.metrics = metrics;

  var hash = location.hash ? location.hash.substr(1) : '';
  var params = opt_params || {};
  if (!params.source) params.source = hash;
  if (!params.metadataCache) params.metadataCache = MetadataCache.createFull();

  function onFilesystem(filesystem) {
    var dom = document.querySelector('.photo-import');
    new PhotoImport(dom, filesystem, params);
  }

  var api = chrome.fileBrowserPrivate || window.top.chrome.fileBrowserPrivate;
  api.getStrings(function(strings) {
    loadTimeData.data = strings;

    if (opt_filesystem) {
      onFilesystem(opt_filesystem);
    } else {
      api.requestLocalFileSystem(onFilesystem);
    }
  });
};

/**
 * One-time initialization of dom elements.
 * @private
 */
PhotoImport.prototype.initDom_ = function() {
  this.dom_.setAttribute('loading', '');
  this.dom_.ownerDocument.defaultView.addEventListener(
      'resize', this.onResize_.bind(this));

  this.spinner_ = this.dom_.querySelector('.spinner');

  this.document_.querySelector('title').textContent =
      loadTimeData.getString('PHOTO_IMPORT_TITLE');
  this.dom_.querySelector('.caption').textContent =
      loadTimeData.getString('PHOTO_IMPORT_CAPTION');
  this.selectAllNone_ = this.dom_.querySelector('.select');
  this.selectAllNone_.addEventListener('click',
      this.onSelectAllNone_.bind(this));

  this.dom_.querySelector('label[for=delete-after-checkbox]').textContent =
      loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER');
  this.selectedCount_ = this.dom_.querySelector('.selected-count');

  this.importButton_ = this.dom_.querySelector('button.import');
  this.importButton_.textContent =
      loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON');
  this.importButton_.addEventListener('click', this.onImportClick_.bind(this));

  this.grid_ = this.dom_.querySelector('grid');
  cr.ui.Grid.decorate(this.grid_);
  this.grid_.itemConstructor = GridItem.bind(null, this);
  this.fileList_ = new cr.ui.ArrayDataModel([]);
  this.grid_.selectionModel = new cr.ui.ListSelectionModel();
  this.grid_.dataModel = this.fileList_;
  this.grid_.selectionModel.addEventListener('change',
      this.onSelectionChanged_.bind(this));
  this.onSelectionChanged_();

  this.importingDialog_ = new ImportingDialog(this.dom_, this.copyManager_,
      this.metadataCache_);
};

/**
 * One-time initialization of destination directory.
 * @private
 */
PhotoImport.prototype.initDestination_ = function() {
  var onError = this.onError_.bind(
      this, loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));

  var onDirectory = function(dir) {
    this.destination_ = dir;
    // This may enable the import button, so check that.
    this.onSelectionChanged_();
  }.bind(this);

  var onMounted = function() {
    var dir = PathUtil.join(RootDirectory.DRIVE, PhotoImport.DRIVE_PHOTOS_DIR);
    util.getOrCreateDirectory(this.filesystem_.root, dir, onDirectory, onError);
  }.bind(this);

  if (this.volumeManager_.isMounted(RootDirectory.DRIVE)) {
    onMounted();
  } else {
    this.volumeManager_.mountDrive(onMounted, onError);
  }
};

/**
 * Load the source contents.
 * @param {string} source Path to source.
 * @private
 */
PhotoImport.prototype.loadSource_ = function(source) {
  var onTraversed = function(results) {
    this.dom_.removeAttribute('loading');
    this.mediaFilesList_ = results.filter(FileType.isImageOrVideo);
    this.fillGrid_();
  }.bind(this);

  var onEntry = function(entry) {
    util.traverseTree(entry, onTraversed, 0 /* infinite depth */,
        FileType.isVisible);
  }.bind(this);

  var onError = this.onError_.bind(
      this, loadTimeData.getString('PHOTO_IMPORT_SOURCE_ERROR'));

  util.resolvePath(this.filesystem_.root, source, onEntry, onError);
};

/**
 * Renders files into grid.
 * @private
 */
PhotoImport.prototype.fillGrid_ = function() {
  if (!this.mediaFilesList_) return;
  this.fileList_.splice(0, this.fileList_.length);
  this.fileList_.push.apply(this.fileList_, this.mediaFilesList_);
};

/**
 * Creates groups for files based on modification date.
 * @param {Array.<Entry>} files File list.
 * @param {Object} filesystem Filesystem metadata.
 * @return {Array.<Object>} List of grouped items.
 * @private
 */
PhotoImport.prototype.createGroups_ = function(files, filesystem) {
  var dateFormatter = v8Intl.DateTimeFormat(
      [] /* default locale */,
      {year: 'numeric', month: 'short', day: 'numeric'});

  var columns = this.grid_.columns;

  var unknownGroup = {
    type: 'group',
    date: 0,
    title: loadTimeData.getString('PHOTO_IMPORT_UNKNOWN_DATE'),
    items: []
  };

  var groupsMap = {};

  for (var index = 0; index < files.length; index++) {
    var props = filesystem[index];
    var item = { type: 'entry', entry: files[index] };

    if (!props || !props.modificationTime) {
      item.group = unknownGroup;
      unknownGroup.items.push(item);
      continue;
    }

    var date = new Date(props.modificationTime);
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);

    var time = date.getTime();
    if (!(time in groupsMap)) {
      groupsMap[time] = {
        type: 'group',
        date: date,
        title: dateFormatter.format(date),
        items: []
      };
    }

    var group = groupsMap[time];
    group.items.push(item);
    item.group = group;
  }

  var groups = [];
  for (var time in groupsMap) {
    if (groupsMap.hasOwnProperty(time)) {
      groups.push(groupsMap[time]);
    }
  }
  if (unknownGroup.items.length > 0)
    groups.push(unknownGroup);

  groups.sort(function(a, b) {
    return b.date.getTime() - a.date.getTime();
  });

  var list = [];
  for (var index = 0; index < groups.length; index++) {
    var group = groups[index];

    list.push(group);
    for (var t = 1; t < columns; t++) {
      list.push({ type: 'empty' });
    }

    for (var j = 0; j < group.items.length; j++) {
      list.push(group.items[j]);
    }

    var count = group.items.length;
    while (count % columns != 0) {
      list.push({ type: 'empty' });
      count++;
    }
  }

  return list;
};

/**
 * Decorates grid item.
 * @param {HTMLLIElement} li The list item.
 * @param {FileEntry} entry The file entry.
 * @private
 */
PhotoImport.prototype.decorateGridItem_ = function(li, entry) {
  li.className = 'grid-item';
  li.entry = entry;

  var frame = this.document_.createElement('div');
  frame.className = 'grid-frame';
  li.appendChild(frame);

  var box = this.document_.createElement('div');
  box.className = 'img-container';
  this.metadataCache_.get(entry, 'thumbnail|filesystem',
      function(metadata) {
        new ThumbnailLoader(entry.toURL(),
                            ThumbnailLoader.LoaderType.IMAGE,
                            metadata).
            load(box, ThumbnailLoader.FillMode.FIT);
      });
  frame.appendChild(box);

  var check = this.document_.createElement('div');
  check.className = 'check';
  li.appendChild(check);
};

/**
 * Handles the 'pick all/none' action.
 * @private
 */
PhotoImport.prototype.onSelectAllNone_ = function() {
  var sm = this.grid_.selectionModel;
  if (sm.selectedIndexes.length == this.fileList_.length) {
    sm.unselectAll();
  } else {
    sm.selectAll();
  }
};

/**
 * Show error message.
 * @param {string} message Error message.
 * @private
 */
PhotoImport.prototype.onError_ = function(message) {
  // TODO
};

/**
 * Resize event handler.
 * @private
 */
PhotoImport.prototype.onResize_ = function() {
  var g = this.grid_;
  g.startBatchUpdates();
  setTimeout(function() {
    g.columns = 0;
    g.redraw();
    g.endBatchUpdates();
  }, 0);
};

/**
 * @return {Array.<Object>} The list of selected entries.
 * @private
 */
PhotoImport.prototype.getSelectedItems_ = function() {
  var indexes = this.grid_.selectionModel.selectedIndexes;
  var list = [];
  for (var i = 0; i < indexes.length; i++) {
    list.push(this.fileList_.item(indexes[i]));
  }
  return list;
};

/**
 * Event handler for picked items change.
 * @private
 */
PhotoImport.prototype.onSelectionChanged_ = function() {
  var count = this.grid_.selectionModel.selectedIndexes.length;
  this.selectedCount_.textContent = count == 0 ? '' :
      count == 1 ? loadTimeData.getString('PHOTO_IMPORT_ONE_SELECTED') :
                   loadTimeData.getStringF('PHOTO_IMPORT_MANY_SELECTED', count);
  this.importButton_.disabled = count == 0 || this.destination_ == null;
  this.selectAllNone_.textContent = loadTimeData.getString(
      count == this.fileList_.length && count > 0 ?
          'PHOTO_IMPORT_SELECT_NONE' : 'PHOTO_IMPORT_SELECT_ALL');
};

/**
 * Event handler for import button click.
 * @param {Event} event The event.
 * @private
 */
PhotoImport.prototype.onImportClick_ = function(event) {
  var entries = this.getSelectedItems_();
  var move = this.dom_.querySelector('#delete-after-checkbox').checked;

  var percentage = Math.round(entries.length / this.fileList_.length * 100);
  metrics.recordMediumCount('PhotoImport.ImportCount', entries.length);
  metrics.recordSmallCount('PhotoImport.ImportPercentage', percentage);

  this.importingDialog_.show(entries, this.destination_, move);
};

/**
 * Item in the grid.
 * @param {PhotoImport} app Application instance.
 * @param {Entry} entry File entry.
 * @constructor
 */
function GridItem(app, entry) {
  var li = app.document_.createElement('li');
  li.__proto__ = GridItem.prototype;
  app.decorateGridItem_(li, entry);
  return li;
}

GridItem.prototype = {
  __proto__: cr.ui.ListItem.prototype,
  get label() {},
  set label(value) {}
};

/**
 * Creates a selection controller that is to be used with grid.
 * @param {cr.ui.ListSelectionModel} selectionModel The selection model to
 *     interact with.
 * @param {cr.ui.Grid} grid The grid to interact with.
 * @constructor
 * @extends {!cr.ui.ListSelectionController}
 */
function GridSelectionController(selectionModel, grid) {
  this.selectionModel_ = selectionModel;
  this.grid_ = grid;
}

/**
 * Extends cr.ui.ListSelectionController.
 */
GridSelectionController.prototype.__proto__ =
    cr.ui.ListSelectionController.prototype;

/** @override */
GridSelectionController.prototype.getIndexBelow = function(index) {
  if (index == this.getLastIndex()) {
    return -1;
  }

  var dm = this.grid_.dataModel;
  var columns = this.grid_.columns;
  var min = (Math.floor(index / columns) + 1) * columns;

  for (var row = 1; true; row++) {
    var end = index + columns * row;
    var start = Math.max(min, index + columns * (row - 1));
    if (start > dm.length) break;

    for (var i = end; i > start; i--) {
      if (i < dm.length && dm.item(i).type == 'entry')
        return i;
    }
  }

  return this.getLastIndex();
};

/** @override */
GridSelectionController.prototype.getIndexAbove = function(index) {
  if (index == this.getFirstIndex()) {
    return -1;
  }

  var dm = this.grid_.dataModel;
  index -= this.grid_.columns;
  while (index >= 0 && dm.item(index).type != 'entry') {
    index--;
  }

  return index < 0 ? this.getFirstIndex() : index;
};

/** @override */
GridSelectionController.prototype.getIndexBefore = function(index) {
  var dm = this.grid_.dataModel;
  index--;
  while (index >= 0 && dm.item(index).type != 'entry') {
    index--;
  }
  return index;
};

/** @override */
GridSelectionController.prototype.getIndexAfter = function(index) {
  var dm = this.grid_.dataModel;
  index++;
  while (index < dm.length && dm.item(index).type != 'entry') {
    index++;
  }
  return index == dm.length ? -1 : index;
};

/** @override */
GridSelectionController.prototype.getFirstIndex = function() {
  var dm = this.grid_.dataModel;
  for (var index = 0; index < dm.length; index++) {
    if (dm.item(index).type == 'entry')
      return index;
  }
  return -1;
};

/** @override */
GridSelectionController.prototype.getLastIndex = function() {
  var dm = this.grid_.dataModel;
  for (var index = dm.length - 1; index >= 0; index--) {
    if (dm.item(index).type == 'entry')
      return index;
  }
  return -1;
};
<|endoftext|>


<commit_before>/* eslint-disable */
export default function (data, state, send, done) {
    const accessToken = data.authResponse.accessToken;
    $.ajax({
        type: 'GET',
        url: 'https://0nd54zu4hg.execute-api.us-east-1.amazonaws.com/latest/v1/bots/',
        dataType: 'json',
        headers: {
            authorization: 'Bearer ' + accessToken
            // 'Authorization': 'Bearer ' + accessToken
        }
    }).done(response => {
        console.log(response);
        const jsonData = $.parseJSON(response);
        if (jsonData.hasOwnProperty('facebook')) {
            $('#fb-page-id').value = jsonData.facebook.pages[0].id
            $('#fb-page-token').value = jsonData.facebook.pages[0].accessToken
            $('#fb-app-secret').value = jsonData.facebook.app.secret
        }
    });
}
// 0dd802d3-2aaa-4e00-8e97-c4de32fe58f6
<commit_msg>delete reference old implementation<commit_after><|endoftext|>


<commit_before>const ENV = {
  // general config
  name: '',
  apiEndpoint: 'http://localhost:8080/',
  modePageTitle: 'Waldur | Cloud Service Management',
  shortPageTitle: 'Waldur',

  pageSizes: [5, 10, 20, 50],
  pageSize: 10,
  dashboardEventsCacheTime: 60, // seconds
  showImport: false,
  defaultErrorMessage: gettext('Reason unknown, please contact support.'),

  // build version
  buildId: 'develop',

  currency: '€',
  // Either 'accounting' or 'billing'
  accountingMode: 'accounting',

  defaultCategories: [
    {
      label: gettext('Virtual machines'),
      icon: 'fa-desktop',
      feature: 'vms',
      key: 'vms',
      state: 'appstore.vms',
      description: gettext('Provision virtual machines (VMs) in available Providers.')
    },
    {
      label: gettext('Private clouds'),
      icon: 'fa-cloud',
      feature: 'private_clouds',
      key: 'private_clouds',
      state: 'appstore.private_clouds',
      description: gettext('Purchase bulk resource as Virtual Private Clouds (VPC).'),
    },
    {
      label: gettext('Block storage'),
      icon: 'fa-hdd-o',
      feature: 'storage',
      key: 'storages',
      state: 'appstore.storages',
      description: gettext('Provision persistent storage volumes in available Providers.')
    },
    {
      label: gettext('Batch processing'),
      icon: 'fa-tasks',
      key: 'slurm',
      feature: 'slurm',
      state: 'appstore.slurm',
      description: gettext('Create an allocation for computations in batch resources.')
    },
  ],

  defaultGroup: gettext('Infrastructure'),

  resourcesTypes: {
    vms: 'vms',
    storages: 'storages',
    volumes: 'volumes',
    private_clouds: 'private_clouds',
    slurm: 'slurm',
    jiraProject: 'jiraProject',
  },

  // Index of category inside of appStoreCategories
  AllResources: -1,
  VirtualMachines: 0,
  PrivateClouds: 1,
  Storages: 3,
  Volumes: 4,

  appStoreCategories: [
    {
      name: gettext('Virtual machines'),
      type: 'provider',
      icon: 'desktop',
      key: 'vms',
      services: ['DigitalOcean', 'Azure', 'Amazon', 'OpenStackTenant', 'Rijkscloud']
    },
    {
      name: gettext('Private clouds'),
      type: 'provider',
      icon: 'cloud',
      key: 'private_clouds',
      services: ['OpenStack'],
    },
    {
      name: gettext('Storages'),
      type: 'provider',
      key: 'storages',
      services: ['OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Volumes'),
      type: 'provider',
      key: 'volumes',
      services: ['OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Batch processing'),
      type: 'provider',
      key: 'slurm',
      services: ['SLURM'],
    },
    {
      name: gettext('Service desk'),
      type: 'provider',
      key: 'jiraProject',
      services: ['JIRA'],
    },
  ],
  serviceCategories: [
    {
      name: gettext('Virtual machines'),
      services: ['Amazon', 'Azure', 'DigitalOcean', 'OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Service desk'),
      services: ['JIRA'],
    },
    {
      name: gettext('Batch processing'),
      services: ['SLURM'],
    }
  ],

  // optional list of disabled services, for example, ['Amazon', 'Azure']
  disabledServices: [],

  resourceCategory: {
    'Amazon.Instance': 'vms',
    'Azure.VirtualMachine': 'vms',
    'DigitalOcean.Droplet': 'vms',
    'OpenStack.Tenant': 'private_clouds',
    'OpenStackTenant.Instance': 'vms',
    'OpenStackTenant.Volume': 'storages',
    'OpenStackTenant.Snapshot': 'storages',
    'Zabbix.Host': 'apps',
    'Zabbix.ITService': 'apps',
    'SLURM.Allocation': 'slurm',
    'JIRA.Project': 'jiraProject',
    'JIRA.Issue': 'jiraProject',
    'Rijkscloud.Instance': 'vms',
    'Rijkscloud.Volume': 'storages',
  },
  defaultListCacheTime: 60 * 10,
  optionsCacheTime: 10 * 1000,
  disabledFeatures: [],
  enabledFeatures: [
    'resources.legacy',
    'marketplace.my-offerings',
    'user.ssh-keys',
  ],
  featuresVisible: false,

  requestTimeout: 1000 * 20,
  countsCacheTime: 60, // seconds
  enablePurchaseCostDisplay: true,

  resourceDetailInterval: 5, // seconds
  resourcesTimerInterval: 30, // seconds
  countersTimerInterval: 30, // seconds

  // an interval in milliseconds to check invitation if server returns 500 or there is a network error.
  invitationCheckInterval: 5000,

  // refresh timeout for a single resource polling.
  resourcePollingEnabled: true,
  singleResourcePollingTimeout: 1000 * 2,

  // delay in milliseconds before starting intro js hints. It is recommended to set it bigger than 500.
  introJsDelay: 1000,

  roles: {
    owner: gettext('Organization owner'),
    manager: gettext('Project manager'),
    admin: gettext('System administrator')
  },
  invitationRedirectTime: 5000,
  userMandatoryFields: [
    'full_name',
    'email'
  ],

  userRegistrationHiddenFields: [
    'registration_method',
    'job_title',
    'phone_number',
    'organization'
  ],

  languageChoices: [
    {
      code: 'az',
      label: gettext('Azerbaijani')
    },
    {
      code: 'en',
      label: gettext('English')
    },
    {
      code: 'et',
      label: gettext('Estonian')
    },
    {
      code: 'lv',
      label: gettext('Latvian')
    },
    {
      code: 'lt',
      label: gettext('Lithuanian')
    },
    {
      code: 'ru',
      label: gettext('Russian')
    }
  ],
  defaultLanguage: 'en',
  organizationSubnetsVisible: false,

  FREEIPA_USERNAME_PREFIX: 'waldur_',

  // Support email and phone is rendered at the footer
  // supportEmail: 'support@example.com',
  // supportPhone: '+1234567890'

  // Support portal URL is rendered as a shortcut on dashboard
  // supportPortalURL: 'http://example.com/support/',

  // Renders label and logo at the login page
  // poweredByLogo: 'images/waldur/logo-120x120.png'

  // Renders link to docs in header
  // docsLink: 'http://example.com/docs/'

  // Conceal "Change request" from a selection of issue types for non-staff/non-support users
  // concealChangeRequest: false

  // Start intro.js implicitly. If false, intro.js is started
  // only when user clicks on "Guide Me" button
  introJsAutostart: false,

  // Provide exclude file types for issue attachments uploading
  // Based on https://github.com/okonet/attr-accept
  // Reffered to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#Attributes
  // Available value types: string or string array
  // Available value format:
  // A file extension starting with the STOP character (U+002E). (e.g. .jpg, .png, .doc).
  // A valid MIME type with no extensions.
  // audio/* representing sound files.
  // video/* representing video files.
  // image/* representing image files.
  excludedAttachmentTypes : [],

  // Ensure that customer, project and resource name contains only ASCII chars.
  enforceLatinName: true,

  // It can be either 'localStorage' or 'sessionStorage'.
  authStorage: 'localStorage',

  // Allows to toggle visibility of empty marketplace categories.
  showEmptyMarketplaceCategories: false,

  // Allows to hide billing step in organization creation wizard
  hideOrganizationBillingStep: false,

  // Allows to hide domain field in organization detail
  organizationDomainVisible: false,

  // Default font for rendering exported table PDF
  defaultFont: 'OpenSans',

  // Font families should match default font.
  // Both normal and bold types are required.
  fontFamilies: {
    OpenSans: {
      normal: 'OpenSans-Regular.ttf',
      bold: 'OpenSans-Bold.ttf',
    }
  },
};

export default ENV;
<commit_msg>Add features that should be enabled for majority of deployment to base<commit_after>const ENV = {
  // general config
  name: '',
  apiEndpoint: 'http://localhost:8080/',
  modePageTitle: 'Waldur | Cloud Service Management',
  shortPageTitle: 'Waldur',

  pageSizes: [5, 10, 20, 50],
  pageSize: 10,
  dashboardEventsCacheTime: 60, // seconds
  showImport: false,
  defaultErrorMessage: gettext('Reason unknown, please contact support.'),

  // build version
  buildId: 'develop',

  currency: '€',
  // Either 'accounting' or 'billing'
  accountingMode: 'accounting',

  defaultCategories: [
    {
      label: gettext('Virtual machines'),
      icon: 'fa-desktop',
      feature: 'vms',
      key: 'vms',
      state: 'appstore.vms',
      description: gettext('Provision virtual machines (VMs) in available Providers.')
    },
    {
      label: gettext('Private clouds'),
      icon: 'fa-cloud',
      feature: 'private_clouds',
      key: 'private_clouds',
      state: 'appstore.private_clouds',
      description: gettext('Purchase bulk resource as Virtual Private Clouds (VPC).'),
    },
    {
      label: gettext('Block storage'),
      icon: 'fa-hdd-o',
      feature: 'storage',
      key: 'storages',
      state: 'appstore.storages',
      description: gettext('Provision persistent storage volumes in available Providers.')
    },
    {
      label: gettext('Batch processing'),
      icon: 'fa-tasks',
      key: 'slurm',
      feature: 'slurm',
      state: 'appstore.slurm',
      description: gettext('Create an allocation for computations in batch resources.')
    },
  ],

  defaultGroup: gettext('Infrastructure'),

  resourcesTypes: {
    vms: 'vms',
    storages: 'storages',
    volumes: 'volumes',
    private_clouds: 'private_clouds',
    slurm: 'slurm',
    jiraProject: 'jiraProject',
  },

  // Index of category inside of appStoreCategories
  AllResources: -1,
  VirtualMachines: 0,
  PrivateClouds: 1,
  Storages: 3,
  Volumes: 4,

  appStoreCategories: [
    {
      name: gettext('Virtual machines'),
      type: 'provider',
      icon: 'desktop',
      key: 'vms',
      services: ['DigitalOcean', 'Azure', 'Amazon', 'OpenStackTenant', 'Rijkscloud']
    },
    {
      name: gettext('Private clouds'),
      type: 'provider',
      icon: 'cloud',
      key: 'private_clouds',
      services: ['OpenStack'],
    },
    {
      name: gettext('Storages'),
      type: 'provider',
      key: 'storages',
      services: ['OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Volumes'),
      type: 'provider',
      key: 'volumes',
      services: ['OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Batch processing'),
      type: 'provider',
      key: 'slurm',
      services: ['SLURM'],
    },
    {
      name: gettext('Service desk'),
      type: 'provider',
      key: 'jiraProject',
      services: ['JIRA'],
    },
  ],
  serviceCategories: [
    {
      name: gettext('Virtual machines'),
      services: ['Amazon', 'Azure', 'DigitalOcean', 'OpenStackTenant', 'Rijkscloud'],
    },
    {
      name: gettext('Service desk'),
      services: ['JIRA'],
    },
    {
      name: gettext('Batch processing'),
      services: ['SLURM'],
    }
  ],

  // optional list of disabled services, for example, ['Amazon', 'Azure']
  disabledServices: [],

  resourceCategory: {
    'Amazon.Instance': 'vms',
    'Azure.VirtualMachine': 'vms',
    'DigitalOcean.Droplet': 'vms',
    'OpenStack.Tenant': 'private_clouds',
    'OpenStackTenant.Instance': 'vms',
    'OpenStackTenant.Volume': 'storages',
    'OpenStackTenant.Snapshot': 'storages',
    'Zabbix.Host': 'apps',
    'Zabbix.ITService': 'apps',
    'SLURM.Allocation': 'slurm',
    'JIRA.Project': 'jiraProject',
    'JIRA.Issue': 'jiraProject',
    'Rijkscloud.Instance': 'vms',
    'Rijkscloud.Volume': 'storages',
  },
  defaultListCacheTime: 60 * 10,
  optionsCacheTime: 10 * 1000,
  disabledFeatures: [],
  enabledFeatures: [
    'billing',
    'customers',
    'eventlog',
    'import',
    'marketplace.my-offerings',
    'notifications',
    'private_clouds',
    'projects',
    'projectCostDetails',
    'resources',
    'resources.legacy',
    'storage',
    'support.users',
    'support.organizations',
    'support.resources-treemap',
    'support.shared-providers',
    'team',
    'user.ssh-keys',
    'vms'
  ],
  featuresVisible: false,

  requestTimeout: 1000 * 20,
  countsCacheTime: 60, // seconds
  enablePurchaseCostDisplay: true,

  resourceDetailInterval: 5, // seconds
  resourcesTimerInterval: 30, // seconds
  countersTimerInterval: 30, // seconds

  // an interval in milliseconds to check invitation if server returns 500 or there is a network error.
  invitationCheckInterval: 5000,

  // refresh timeout for a single resource polling.
  resourcePollingEnabled: true,
  singleResourcePollingTimeout: 1000 * 2,

  // delay in milliseconds before starting intro js hints. It is recommended to set it bigger than 500.
  introJsDelay: 1000,

  roles: {
    owner: gettext('Organization owner'),
    manager: gettext('Project manager'),
    admin: gettext('System administrator')
  },
  invitationRedirectTime: 5000,
  userMandatoryFields: [
    'full_name',
    'email'
  ],

  userRegistrationHiddenFields: [
    'registration_method',
    'job_title',
    'phone_number',
    'organization'
  ],

  languageChoices: [
    {
      code: 'az',
      label: gettext('Azerbaijani')
    },
    {
      code: 'en',
      label: gettext('English')
    },
    {
      code: 'et',
      label: gettext('Estonian')
    },
    {
      code: 'lv',
      label: gettext('Latvian')
    },
    {
      code: 'lt',
      label: gettext('Lithuanian')
    },
    {
      code: 'ru',
      label: gettext('Russian')
    }
  ],
  defaultLanguage: 'en',
  organizationSubnetsVisible: false,

  FREEIPA_USERNAME_PREFIX: 'waldur_',

  // Support email and phone is rendered at the footer
  // supportEmail: 'support@example.com',
  // supportPhone: '+1234567890'

  // Support portal URL is rendered as a shortcut on dashboard
  // supportPortalURL: 'http://example.com/support/',

  // Renders label and logo at the login page
  // poweredByLogo: 'images/waldur/logo-120x120.png'

  // Renders link to docs in header
  // docsLink: 'http://example.com/docs/'

  // Conceal "Change request" from a selection of issue types for non-staff/non-support users
  // concealChangeRequest: false

  // Start intro.js implicitly. If false, intro.js is started
  // only when user clicks on "Guide Me" button
  introJsAutostart: false,

  // Provide exclude file types for issue attachments uploading
  // Based on https://github.com/okonet/attr-accept
  // Reffered to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#Attributes
  // Available value types: string or string array
  // Available value format:
  // A file extension starting with the STOP character (U+002E). (e.g. .jpg, .png, .doc).
  // A valid MIME type with no extensions.
  // audio/* representing sound files.
  // video/* representing video files.
  // image/* representing image files.
  excludedAttachmentTypes : [],

  // Ensure that customer, project and resource name contains only ASCII chars.
  enforceLatinName: true,

  // It can be either 'localStorage' or 'sessionStorage'.
  authStorage: 'localStorage',

  // Allows to toggle visibility of empty marketplace categories.
  showEmptyMarketplaceCategories: false,

  // Allows to hide billing step in organization creation wizard
  hideOrganizationBillingStep: false,

  // Allows to hide domain field in organization detail
  organizationDomainVisible: false,

  // Default font for rendering exported table PDF
  defaultFont: 'OpenSans',

  // Font families should match default font.
  // Both normal and bold types are required.
  fontFamilies: {
    OpenSans: {
      normal: 'OpenSans-Regular.ttf',
      bold: 'OpenSans-Bold.ttf',
    }
  },
};

export default ENV;
<|endoftext|>


<commit_before>(function(){
  'use strict';

  var utils = require('./_utils'),
      CONSTANTS = require('../protractor.constants'),
      modelsRecipe = require('./_modelsRecipe');

  describe('operatorApp', function() {
    beforeEach(utils.setUp);

    describe('Case List', function () {
      var randomName = Math.random().toString(36).substring(7);

      function searchAndExpect(personQ, numResults) {
        element(by.css('#s2id_searchPerson a')).click();

        element(by.css('.select2-search input')).sendKeys(personQ);
        browser.driver.wait(function() {
          return element(by.css('.select2-no-results, .select2-result')).isPresent();
        }).then(function() {
          expect(element.all(by.css('.select2-results-dept-0')).count()).toBe(numResults);
        });
      }

      it('should filter by person', function() {

        modelsRecipe.Case.createRecipe({}, {
            full_name: randomName
          }
        ).then(function() {
          // go to list => assert num of rows > 1
          browser.get(CONSTANTS.callcentreBaseUrl);

          // findelement by random name and click on the name
          element(by.cssContainingText('a', randomName)).click();

          // assert that url changed and num of rows == 1
          element.all(by.css('.CaseList tbody tr')).then(function(els) {
            expect(els.length).toBe(1);
          });
          expect(element(by.css('.search-person')).getText()).toBe(randomName);
        });
      });

      it('should allow creating a Case for selected person', function() {
        // click on create new case for that person
        element(by.buttonText('Create a case for '+randomName)).click();

        // assert that personal details is filled in properly
        var caseRef = element(by.binding('case.reference'));
        expect(caseRef.isPresent()).toBe(true);
        expect(browser.getLocationAbsUrl()).toContain(caseRef.getText());
        expect(element(by.css('#personal_details h2.Icon--user')).getText()).toBe(randomName);
      });

      it('should allow going back to case list for that person', function() {
        // click go back to case list
        element(by.cssContainingText('a','Back to cases')).click();

        // assert that we are still in multi cases per user list
        element.all(by.css('.CaseList tbody tr')).then(function(els) {
          expect(els.length).toBe(2);
        });
        expect(element(by.css('.search-person')).getText()).toBe(randomName);
        expect(browser.getLocationAbsUrl()).toContain('person_ref');
      });

      it('should allow going back to full case list', function() {
        // reset search => assert that it goes back to full case list
        element(by.cssContainingText('.search-person', randomName)).click();

        expect(browser.getLocationAbsUrl()).not.toContain('person_ref');
      });

      it('should allow searching for a person when creating a new case', function() {
        element(by.buttonText('Create a case')).click();

        browser.driver.wait(function() {
          return element(by.css('#s2id_searchPerson a'));
        }).then(function(select2Triggerer) {
          searchAndExpect('__invalid', 0);
          element(by.id('select2-drop-mask')).click();  // focus away to close the select
          searchAndExpect(randomName, 1);
        });
      });

      it('should allow cancelling a linking request', function() {
        element(by.css('.select2-results-dept-0')).click();

        browser.switchTo().alert().dismiss();
      });

      it('should allow linking a Person to a new case', function() {
        searchAndExpect(randomName, 1);

        element(by.css('.select2-results-dept-0')).click();

        browser.switchTo().alert().accept();

        expect(element(by.css('#personal_details h2.Icon--user')).getText()).toBe(randomName);
      });
    });
  });
})();
<commit_msg>cleanup<commit_after>(function(){
  'use strict';

  var utils = require('./_utils'),
      CONSTANTS = require('../protractor.constants'),
      modelsRecipe = require('./_modelsRecipe');

  describe('operatorApp', function() {
    beforeEach(utils.setUp);

    describe('Case List', function () {
      var randomName = Math.random().toString(36).substring(7);

      function searchAndExpect(personQ, numResults) {
        element(by.css('#s2id_searchPerson a')).click();

        element(by.css('.select2-search input')).sendKeys(personQ);
        browser.driver.wait(function() {
          return element(by.css('.select2-no-results, .select2-result')).isPresent();
        }).then(function() {
          expect(element.all(by.css('.select2-results-dept-0')).count()).toBe(numResults);
        });
      }

      it('should filter by person', function() {

        modelsRecipe.Case.createRecipe({}, {
            full_name: randomName
          }
        ).then(function() {
          // go to list => assert num of rows > 1
          browser.get(CONSTANTS.callcentreBaseUrl);

          // findelement by random name and click on the name
          element(by.cssContainingText('a', randomName)).click();

          // assert that url changed and num of rows == 1
          element.all(by.css('.CaseList tbody tr')).then(function(els) {
            expect(els.length).toBe(1);
          });
          expect(element(by.css('.search-person')).getText()).toBe(randomName);
        });
      });

      it('should allow creating a Case for selected person', function() {
        // click on create new case for that person
        element(by.buttonText('Create a case for '+randomName)).click();

        // assert that personal details is filled in properly
        var caseRef = element(by.binding('case.reference'));
        expect(caseRef.isPresent()).toBe(true);
        expect(browser.getLocationAbsUrl()).toContain(caseRef.getText());
        expect(element(by.css('#personal_details h2.Icon--user')).getText()).toBe(randomName);
      });

      it('should allow going back to case list for that person', function() {
        // click go back to case list
        element(by.cssContainingText('a','Back to cases')).click();

        // assert that we are still in multi cases per user list
        element.all(by.css('.CaseList tbody tr')).then(function(els) {
          expect(els.length).toBe(2);
        });
        expect(element(by.css('.search-person')).getText()).toBe(randomName);
        expect(browser.getLocationAbsUrl()).toContain('person_ref');
      });

      it('should allow going back to full case list', function() {
        // reset search => assert that it goes back to full case list
        element(by.cssContainingText('.search-person', randomName)).click();

        expect(browser.getLocationAbsUrl()).not.toContain('person_ref');
      });

      it('should allow searching for a person when creating a new case', function() {
        element(by.buttonText('Create a case')).click();

        browser.driver.wait(function() {
          return element(by.css('#s2id_searchPerson a'));
        }).then(function() {
          searchAndExpect('__invalid', 0);
          element(by.id('select2-drop-mask')).click();  // focus away to close the select
          searchAndExpect(randomName, 1);
        });
      });

      it('should allow cancelling a linking request', function() {
        element(by.css('.select2-results-dept-0')).click();

        browser.switchTo().alert().dismiss();
      });

      it('should allow linking a Person to a new case', function() {
        searchAndExpect(randomName, 1);

        element(by.css('.select2-results-dept-0')).click();

        browser.switchTo().alert().accept();

        expect(element(by.css('#personal_details h2.Icon--user')).getText()).toBe(randomName);
      });
    });
  });
})();
<|endoftext|>