<commit_before>
/*
All required uci packages are stored variable uci.
The GUI code displayes and manipulated this variable.
*/
var uci = {};
var gid = 0;

function init()
{
	send("/cgi-bin/settings", { func : "get_settings" }, function(data) {
		uci = fromUCI(data);
		rebuild_general();
	});
}

function updateFrom(src)
{
	var obj = {};
	collect_inputs(src, obj);
	for(var name in obj)
	{
		var value = obj[name];
		var path = name.split('#');

		var pkg = path[0];
		var sec = path[1];
		var opt = path[2];

		uci[pkg].pchanged = true;
		uci[pkg][sec][opt] = value
	}
}

function getChangeModeAction(ifname)
{
	return function(e) {
		var src = (e.target || e.srcElement);
		var mode = src.value;
		delNetSection(ifname);
		addNetSection(ifname, mode);
	};
}

function appendSetting(p, path, value, mode)
{
	var id = path.join('#');
	var b;
	var cfg = path[0]
	var name = path[path.length-1];
	switch(name)
	{
	case "geo":
		b = append_input(p, "GPS-Koordinaten", id, value);
		b.lastChild.placeholder = "52.02713078 8.52829987";
		addInputCheck(b.lastChild, /^\d{1,3}\.\d{1,8} +\d{1,3}\.\d{1,8}$/, "Koordinaten sind ung\xfcltig. Bitte nur maximal 8 Nachkommastellen und keine Kommas verwenden.");
		addHelpText(b, "Die Koordinaten dieses Knotens auf der Freifunk-Karte (z.B. \"52.02713078 8.52829987\").");
		break;
	case "name":
		b = append_input(p, "Knotenname", id, value);
		b.lastChild.placeholder = "MeinRouter";
		addInputCheck(b.lastChild, /^[\-\^'\w\.\:\[\]\(\)\/ \u0080-\u00FF]{0,32}$/, name + " ist ung\xfcltig.");
		addHelpText(b, "Der Name dieses Knotens auf der Freifunk-Karte.");
		break;
	case "enabled":
		if(cfg == "autoupdater") {
			b = append_radio(p, "Autoupdater", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Der Autoupdater aktualisiert die Firmware automatisch auf die neuste Version. Dabei werden allerdings alle Einstellungen zur\xfcckgesetzt.");
		}
		if(cfg == "simple-tc") {
			b = append_radio(p, "Bandweitenkontrolle", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Bandweitenkontrolle f\xfcr den Upload-/Download \xfcber das Freifunknetz \xfcber den eigenen Internetanschluss.");
		}
		break;
	case "map_publish":
		b = append_radio(p, "Zur Karte beitragen", id, value, [["Ja", "1"], ["Nein", "0"]]);
		addHelpText(b, "Soll dieser Knoten auf der Knotenkarte angezeigt werden?");
		break;
	case "limit_egress":
		b = append_input(p, "Public Upload", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Upload ist ung\xfcltig.");
		addHelpText(b, "Maximaler Upload in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "limit_ingress":
		b = append_input(p, "Public Download", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Download ist ung\xfcltig.");
		addHelpText(b, "Maximaler Download in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "access_from":
		b = append_check(p, "SSH/HTTPS Zugriff", id, split(value), [["WAN","wan"], ["Private","private"], ["Public","public"]]);
		addHelpText(b, "Zugang zur Konfiguration \xfcber verschiedene Anschl\xfcsse/Netzwerke erm\xf6glichen.")
		break;
	case "service_link":
		b = append_input(p, "Service Link", id, value);
		b.lastChild.placeholder = "http://[fdef:17a0::1]/seite.html";
		addInputCheck(b.lastChild, /^[#\[\] \w\/.:]{0,128}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Verweis auf eine Netzwerkresource. Z.B. \"http://1.2.3.4\".");
		break;
	case "service_label":
		b = append_input(p, "Service Name", id, value);
		b.lastChild.placeholder = "MeineWebseite";
		addInputCheck(b.lastChild, /^[\[\]\(\) \w\/.:]{0,32}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Name der angegebenen Netzwerkresource. Z.B. \"Meine Webseite\".");
		break;
	case "service_display_max":
		b = append_input(p, "Max. Angezeigte-Eintr\xe4ge", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Ung\xfcltige Zahl.");
		addHelpText(b, "Maximale Anzahl der auf der eigenen Statusseite angezeigten Eintr\xe4ge.");
		break;
	default:
		return;
	}

	b.id = id; //needed for updateFrom
	b.onchange = function() {
		updateFrom(b);
	};

	return b;
}

function rebuild_general()
{
	var gfs = $("general");
	var rfs = $("resource");
	var tfs = $("traffic");

	removeChilds(gfs);
	removeChilds(rfs);
	removeChilds(tfs);

	if('freifunk' in uci) {
		var f = uci.freifunk;
		var i = firstSectionID(f, "settings");
		appendSetting(gfs, ['freifunk', i, "name"], f[i]["name"]);
		appendSetting(gfs, ['freifunk', i, "geo"], f[i]["geo"]);
		appendSetting(gfs, ['freifunk', i, "map_publish"], f[i]["map_publish"]);
		appendSetting(gfs, ['freifunk', i, "access_from"], f[i]["access_from"]);
		appendSetting(rfs, ['freifunk', i, "service_label"], f[i]["service_label"]);
		appendSetting(rfs, ['freifunk', i, "service_link"], f[i]["service_link"]);
		appendSetting(rfs, ['freifunk', i, "service_display_max"], f[i]["service_display_max"]);
	}

	if('autoupdater' in uci) {
		var a = uci.autoupdater;
		var i = firstSectionID(a, "autoupdater");
		appendSetting(gfs, ['autoupdater', i, "enabled"], a[i]["enabled"]);
	}

	if('simple-tc' in uci) {
		var t = uci['simple-tc'];
		var i = firstSectionID(t, "interface");
		appendSetting(tfs, ['simple-tc', i, "enabled"], t[i]["enabled"]);
		appendSetting(tfs, ['simple-tc', i, "limit_ingress"], t[i]["limit_ingress"]);
		appendSetting(tfs, ['simple-tc', i, "limit_egress"], t[i]["limit_egress"]);
	}
}

function save_data()
{
	for(var name in uci)
	{
		var obj = uci[name];
		if(!obj.pchanged)
			continue;
		var data = toUCI(obj);
		send("/cgi-bin/misc", { func : "set_config_file", name : name, data : data },
			function(data) {
				$('msg').innerHTML = data;
				$('msg').focus();
				init();
			}
		);
	}
}
<commit_msg>allow latin-1 for service labels<commit_after>
/*
All required uci packages are stored variable uci.
The GUI code displayes and manipulated this variable.
*/
var uci = {};
var gid = 0;

function init()
{
	send("/cgi-bin/settings", { func : "get_settings" }, function(data) {
		uci = fromUCI(data);
		rebuild_general();
	});
}

function updateFrom(src)
{
	var obj = {};
	collect_inputs(src, obj);
	for(var name in obj)
	{
		var value = obj[name];
		var path = name.split('#');

		var pkg = path[0];
		var sec = path[1];
		var opt = path[2];

		uci[pkg].pchanged = true;
		uci[pkg][sec][opt] = value
	}
}

function getChangeModeAction(ifname)
{
	return function(e) {
		var src = (e.target || e.srcElement);
		var mode = src.value;
		delNetSection(ifname);
		addNetSection(ifname, mode);
	};
}

function appendSetting(p, path, value, mode)
{
	var id = path.join('#');
	var b;
	var cfg = path[0]
	var name = path[path.length-1];
	switch(name)
	{
	case "geo":
		b = append_input(p, "GPS-Koordinaten", id, value);
		b.lastChild.placeholder = "52.02713078 8.52829987";
		addInputCheck(b.lastChild, /^\d{1,3}\.\d{1,8} +\d{1,3}\.\d{1,8}$/, "Koordinaten sind ung\xfcltig. Bitte nur maximal 8 Nachkommastellen und keine Kommas verwenden.");
		addHelpText(b, "Die Koordinaten dieses Knotens auf der Freifunk-Karte (z.B. \"52.02713078 8.52829987\").");
		break;
	case "name":
		b = append_input(p, "Knotenname", id, value);
		b.lastChild.placeholder = "MeinRouter";
		addInputCheck(b.lastChild, /^[\-\^'\w\.\:\[\]\(\)\/ \u0080-\u00FF]{0,32}$/, name + " ist ung\xfcltig.");
		addHelpText(b, "Der Name dieses Knotens auf der Freifunk-Karte.");
		break;
	case "enabled":
		if(cfg == "autoupdater") {
			b = append_radio(p, "Autoupdater", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Der Autoupdater aktualisiert die Firmware automatisch auf die neuste Version. Dabei werden allerdings alle Einstellungen zur\xfcckgesetzt.");
		}
		if(cfg == "simple-tc") {
			b = append_radio(p, "Bandweitenkontrolle", id, value, [["An", "1"], ["Aus", "0"]]);
			addHelpText(b, "Bandweitenkontrolle f\xfcr den Upload-/Download \xfcber das Freifunknetz \xfcber den eigenen Internetanschluss.");
		}
		break;
	case "map_publish":
		b = append_radio(p, "Zur Karte beitragen", id, value, [["Ja", "1"], ["Nein", "0"]]);
		addHelpText(b, "Soll dieser Knoten auf der Knotenkarte angezeigt werden?");
		break;
	case "limit_egress":
		b = append_input(p, "Public Upload", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Upload ist ung\xfcltig.");
		addHelpText(b, "Maximaler Upload in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "limit_ingress":
		b = append_input(p, "Public Download", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Download ist ung\xfcltig.");
		addHelpText(b, "Maximaler Download in KBit/s f\xfcr die Bandweitenkontrolle.");
		break;
	case "access_from":
		b = append_check(p, "SSH/HTTPS Zugriff", id, split(value), [["WAN","wan"], ["Private","private"], ["Public","public"]]);
		addHelpText(b, "Zugang zur Konfiguration \xfcber verschiedene Anschl\xfcsse/Netzwerke erm\xf6glichen.")
		break;
	case "service_link":
		b = append_input(p, "Service Link", id, value);
		b.lastChild.placeholder = "http://[fdef:17a0::1]/seite.html";
		addInputCheck(b.lastChild, /^[#\[\] \w\/.:]{0,128}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Verweis auf eine Netzwerkresource. Z.B. \"http://1.2.3.4\".");
		break;
	case "service_label":
		b = append_input(p, "Service Name", id, value);
		b.lastChild.placeholder = "MeineWebseite";
		addInputCheck(b.lastChild, /^[\[\]\(\) \w\/.:\u0080-\u00FF]{0,32}$/, "Ung\xfcltige Eingabe.");
		addHelpText(b, "Ein Name der angegebenen Netzwerkresource. Z.B. \"Meine Webseite\".");
		break;
	case "service_display_max":
		b = append_input(p, "Max. Angezeigte-Eintr\xe4ge", id, value);
		addInputCheck(b.lastChild, /^\d+$/, "Ung\xfcltige Zahl.");
		addHelpText(b, "Maximale Anzahl der auf der eigenen Statusseite angezeigten Eintr\xe4ge.");
		break;
	default:
		return;
	}

	b.id = id; //needed for updateFrom
	b.onchange = function() {
		updateFrom(b);
	};

	return b;
}

function rebuild_general()
{
	var gfs = $("general");
	var rfs = $("resource");
	var tfs = $("traffic");

	removeChilds(gfs);
	removeChilds(rfs);
	removeChilds(tfs);

	if('freifunk' in uci) {
		var f = uci.freifunk;
		var i = firstSectionID(f, "settings");
		appendSetting(gfs, ['freifunk', i, "name"], f[i]["name"]);
		appendSetting(gfs, ['freifunk', i, "geo"], f[i]["geo"]);
		appendSetting(gfs, ['freifunk', i, "map_publish"], f[i]["map_publish"]);
		appendSetting(gfs, ['freifunk', i, "access_from"], f[i]["access_from"]);
		appendSetting(rfs, ['freifunk', i, "service_label"], f[i]["service_label"]);
		appendSetting(rfs, ['freifunk', i, "service_link"], f[i]["service_link"]);
		appendSetting(rfs, ['freifunk', i, "service_display_max"], f[i]["service_display_max"]);
	}

	if('autoupdater' in uci) {
		var a = uci.autoupdater;
		var i = firstSectionID(a, "autoupdater");
		appendSetting(gfs, ['autoupdater', i, "enabled"], a[i]["enabled"]);
	}

	if('simple-tc' in uci) {
		var t = uci['simple-tc'];
		var i = firstSectionID(t, "interface");
		appendSetting(tfs, ['simple-tc', i, "enabled"], t[i]["enabled"]);
		appendSetting(tfs, ['simple-tc', i, "limit_ingress"], t[i]["limit_ingress"]);
		appendSetting(tfs, ['simple-tc', i, "limit_egress"], t[i]["limit_egress"]);
	}
}

function save_data()
{
	for(var name in uci)
	{
		var obj = uci[name];
		if(!obj.pchanged)
			continue;
		var data = toUCI(obj);
		send("/cgi-bin/misc", { func : "set_config_file", name : name, data : data },
			function(data) {
				$('msg').innerHTML = data;
				$('msg').focus();
				init();
			}
		);
	}
}
<|endoftext|>


<commit_before>import Collection from 'ol/Collection';
import Vector from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import {Circle, Fill, Stroke, Style} from 'ol/style';
import {Draw, Modify} from 'ol/interaction';

/**
 * @param HsConfig
 * @param HsMapService
 * @param HsQueryBaseService
 * @param $rootScope
 * @param HsLayerUtilsService
 * @param gettext
 * @param $log
 * @param $document
 * @param HsLayoutService
 * @param $compile
 */
export default function (
  HsConfig,
  HsMapService,
  HsQueryBaseService,
  $rootScope,
  HsLayerUtilsService,
  gettext,
  $log,
  $document,
  HsLayoutService,
  $compile,
) {
  'ngInject';
  const me = this;
  angular.extend(me, {
    draw: null,
    modify: null,
    type: null,
    selectedFeatures: new Collection(),
    selectedLayer: null,
    drawActive: false,
    highlighted_style(feature, resolution) {
      return [
        new Style({
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.4)',
          }),
          stroke: new Stroke({
            color: '#d00504',
            width: 2,
          }),
          image: new Circle({
            radius: 5,
            fill: new Fill({
              color: '#d11514',
            }),
            stroke: new Stroke({
              color: '#d00504',
              width: 2,
            }),
          }),
        }),
      ];
    },

    saveDrawingLayer($scope,addNewLayer = false) {
      let tmpTitle = gettext('Draw layer');
      let tmpLayer = addNewLayer === true ? null : HsMapService.findLayerByTitle('tmpDrawLayer');
      let tmpSource = addNewLayer === true ? new Vector() : tmpLayer.getSource();

      let i = 1;
      while (HsMapService.findLayerByTitle(tmpTitle)) {
        tmpTitle = `${gettext('Draw layer')} ${i++}`;
      }
      const drawLayer = new VectorLayer({
        title: tmpTitle,
        source: tmpSource,
        show_in_manager: true,
        visible: true,
        removable: true,
        editable: true,
        synchronize: true,
        path: HsConfig.defaultDrawLayerPath || gettext('User generated'),
      });
      me.selectedLayer = drawLayer;
      const el = angular.element(
        '<hs.draw-layer-metadata layer="service.selectedLayer"></draw-layer-metadata>'
      );
      HsLayoutService.contentWrapper
        .querySelector('.hs-dialog-area')
        .appendChild(el[0]);
      $compile(el)($scope);
    },

    addDrawLayer(layer) {
      HsMapService.map.addLayer(layer);
      me.fillDrawableLayers();
    },

    drawableLayers: [],
    /**
     * @function updateStyle
     * @memberOf HsDrawService
     * @param {Function} changeStyle controller callback function
     * @description Update draw style without neccessity to reactivate drawing interaction
     */
    updateStyle(changeStyle) {
      if (me.draw) {
        me.draw.getOverlay().setStyle(changeStyle());
      }
    },
    /**
     * @function activateDrawing
     * @memberOf HsDrawService
     * @param {Function} onDrawStart Callback function called when drawing is started
     * @param {Function} onDrawEnd Callback function called when drawing is finished
     * @param {Function} onSelected Callback function called when feature is selected for modification
     * @param {Function} onDeselected Callback function called when feature is deselected
     * @param {Function} changeStyle controller callback function which set style
     * dynamically according to selected parameters
     * @param {boolean} drawState Should drawing be set active when
     * creating the interactions
     * @description Add drawing interaction to map. Partial interactions are Draw, Modify and Select. Add Event listeners for drawstart, drawend and (de)selection of feature.
     */
    activateDrawing(
      onDrawStart,
      onDrawEnd,
      onSelected,
      onDeselected,
      changeStyle,
      drawState
    ) {
      me.onDeselected = onDeselected;
      me.onSelected = onSelected;
      me.deactivateDrawing().then(() => {
        HsQueryBaseService.deactivateQueries();
        me.draw = new Draw({
          source: me.source,
          type: /** @type {ol.geom.GeometryType} */ (me.type),
          style: changeStyle ? changeStyle() : undefined,
        });

        me.draw.setActive(drawState);

        HsMapService.loaded().then((map) => {
          map.addInteraction(me.draw);
        });

        /**
         * @param event
         */
        function keyUp(event) {
          if (event.keyCode === 27) {
            me.removeLastPoint();
          }
        }

        me.draw.on(
          'drawstart',
          (e) => {
            me.drawActive = true;
            me.modify.setActive(false);
            if (onDrawStart) {
              onDrawStart(e);
            }
            $document[0].addEventListener('keyup', keyUp);
          },
          this
        );

        me.draw.on(
          'drawend',
          (e) => {
            if (changeStyle) {
              e.feature.setStyle(changeStyle());
            }
            if (onDrawEnd) {
              onDrawEnd(e);
            }
            $document[0].removeEventListener('keyup', keyUp);
          },
          this
        );
      });
    },

    /**
     * Re-enables getFeatureInfo info and cleans up after drawing
     */
    afterDrawEnd() {
      if (me.draw) {
        me.draw.setActive(false);
      }
      me.drawActive = false;
      HsQueryBaseService.activateQueries();
    },

    removeLastPoint() {
      me.draw.removeLastPoint();
    },

    changeDrawSource(){
      me.source = me.selectedLayer.getSource()
      if (me.draw){
        me.activateDrawing(
          null, null, null, null, null, true, true
        );
      }
    },

    /**
     * @function deactivateDrawing
     * @memberOf HsDrawService
     * @returns {Promise}
     * Deactivate all hs.draw interaction in map (Draw, Modify, Select)
     */
    deactivateDrawing() {
      return new Promise((resolve, reject) => {
        HsMapService.loaded().then((map) => {
          me.afterDrawEnd();
          if (me.draw) {
            map.removeInteraction(me.draw);
            me.draw = null;
          }
          resolve();
        });
      });
    },

    stopDrawing() {
      if (angular.isUndefined(me.draw) || me.draw === null) {
        return;
      }
      try {
        if (me.draw.getActive()) {
          me.draw.finishDrawing();
        }
      } catch (ex) {
        $log.warn(ex);
      }
      me.draw.setActive(false);
      me.modify.setActive(false);
    },

    startDrawing() {
      try {
        if (me.draw.getActive()) {
          me.draw.finishDrawing();
        }
      } catch (ex) {
        $log.warn(ex);
      }
      me.draw.setActive(true);
    },

    fillDrawableLayers() {
      const tmp = HsMapService.map
        .getLayers()
        .getArray()
        .filter(HsLayerUtilsService.isLayerDrawable);
      if (tmp.length > 0 && me.selectedLayer === null) {
        me.selectedLayer = tmp[0];
      }
      if (tmp.length == 0 && me.selectedLayer === null){
        me.type = null;
        me.deactivateDrawing();
      }
      me.drawableLayers = tmp;
    },
  });

  HsMapService.loaded().then((map) => {
    me.modify = new Modify({
      features: me.selectedFeatures,
    });
    map.addInteraction(me.modify);
    me.fillDrawableLayers();
  });

  me.selectedFeatures.on('add', (e) => {
    if (me.onSelected) {
      me.onSelected(e);
    }
    me.modify.setActive(true);
  });

  me.selectedFeatures.on('remove', (e) => {
    if (me.onDeselected) {
      me.onDeselected(e);
    }
  });

  const unregisterFeatureSelected = $rootScope.$on(
    'vectorQuery.featureSelected',
    (e, feature) => {
      me.selectedFeatures.push(feature);
    }
  );

  const unregisterFeatureDeselected = $rootScope.$on(
    'vectorQuery.featureDelected',
    (e, feature) => {
      me.selectedFeatures.remove(feature);
    }
  );
  return me;
}
<commit_msg>Fix styling of features in new layers/after draw layer change<commit_after>import Collection from 'ol/Collection';
import Vector from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import {Circle, Fill, Stroke, Style} from 'ol/style';
import {Draw, Modify} from 'ol/interaction';

/**
 * @param HsConfig
 * @param HsMapService
 * @param HsQueryBaseService
 * @param $rootScope
 * @param HsLayerUtilsService
 * @param gettext
 * @param $log
 * @param $document
 * @param HsLayoutService
 * @param $compile
 */
export default function (
  HsConfig,
  HsMapService,
  HsQueryBaseService,
  $rootScope,
  HsLayerUtilsService,
  gettext,
  $log,
  $document,
  HsLayoutService,
  $compile,
) {
  'ngInject';
  const me = this;
  angular.extend(me, {
    draw: null,
    modify: null,
    type: null,
    selectedFeatures: new Collection(),
    selectedLayer: null,
    drawActive: false,
    highlighted_style(feature, resolution) {
      return [
        new Style({
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.4)',
          }),
          stroke: new Stroke({
            color: '#d00504',
            width: 2,
          }),
          image: new Circle({
            radius: 5,
            fill: new Fill({
              color: '#d11514',
            }),
            stroke: new Stroke({
              color: '#d00504',
              width: 2,
            }),
          }),
        }),
      ];
    },

    saveDrawingLayer($scope,addNewLayer = false) {
      let tmpTitle = gettext('Draw layer');
      let tmpLayer = addNewLayer === true ? null : HsMapService.findLayerByTitle('tmpDrawLayer');
      let tmpSource = addNewLayer === true ? new Vector() : tmpLayer.getSource();

      let i = 1;
      while (HsMapService.findLayerByTitle(tmpTitle)) {
        tmpTitle = `${gettext('Draw layer')} ${i++}`;
      }
      const drawLayer = new VectorLayer({
        title: tmpTitle,
        source: tmpSource,
        show_in_manager: true,
        visible: true,
        removable: true,
        editable: true,
        synchronize: true,
        path: HsConfig.defaultDrawLayerPath || gettext('User generated'),
      });
      me.selectedLayer = drawLayer;
      const el = angular.element(
        '<hs.draw-layer-metadata layer="service.selectedLayer"></draw-layer-metadata>'
      );
      HsLayoutService.contentWrapper
        .querySelector('.hs-dialog-area')
        .appendChild(el[0]);
      $compile(el)($scope);
    },

    addDrawLayer(layer) {
      HsMapService.map.addLayer(layer);
      me.fillDrawableLayers();
    },

    drawableLayers: [],
    /**
     * @function updateStyle
     * @memberOf HsDrawService
     * @param {Function} changeStyle controller callback function
     * @description Update draw style without neccessity to reactivate drawing interaction
     */
    updateStyle(changeStyle) {
      if (me.draw) {
        me.currentStyle = changeStyle();
        me.draw.getOverlay().setStyle(me.currentStyle);
      }
    },
    /**
     * (PRIVATE) Helper function which returns currently selected style. Used with
     * @function useCurrentStyle
     * @memberOf HsDrawService
     */
    useCurrentStyle(){
      return me.currentStyle;
    },
    /**
     * @function activateDrawing
     * @memberOf HsDrawService
     * @param {Function} onDrawStart Callback function called when drawing is started
     * @param {Function} onDrawEnd Callback function called when drawing is finished
     * @param {Function} onSelected Callback function called when feature is selected for modification
     * @param {Function} onDeselected Callback function called when feature is deselected
     * @param {Function} changeStyle controller callback function which set style
     * dynamically according to selected parameters
     * @param {boolean} drawState Should drawing be set active when
     * creating the interactions
     * @description Add drawing interaction to map. Partial interactions are Draw, Modify and Select. Add Event listeners for drawstart, drawend and (de)selection of feature.
     */
    activateDrawing(
      onDrawStart,
      onDrawEnd,
      onSelected,
      onDeselected,
      changeStyle,
      drawState
    ) {
      me.onDeselected = onDeselected;
      me.onSelected = onSelected;
      me.deactivateDrawing().then(() => {
        HsQueryBaseService.deactivateQueries();
        me.draw = new Draw({
          source: me.source,
          type: /** @type {ol.geom.GeometryType} */ (me.type),
          style: changeStyle ? changeStyle() : undefined,
        });

        me.draw.setActive(drawState);

        HsMapService.loaded().then((map) => {
          map.addInteraction(me.draw);
        });

        /**
         * @param event
         */
        function keyUp(event) {
          if (event.keyCode === 27) {
            me.removeLastPoint();
          }
        }

        me.draw.on(
          'drawstart',
          (e) => {
            me.drawActive = true;
            me.modify.setActive(false);
            if (onDrawStart) {
              onDrawStart(e);
            }
            $document[0].addEventListener('keyup', keyUp);
          },
          this
        );

        me.draw.on(
          'drawend',
          (e) => {
            if (changeStyle) {
              e.feature.setStyle(changeStyle());
            }
            if (onDrawEnd) {
              onDrawEnd(e);
            }
            $document[0].removeEventListener('keyup', keyUp);
          },
          this
        );
      });
    },

    /**
     * Re-enables getFeatureInfo info and cleans up after drawing
     */
    afterDrawEnd() {
      if (me.draw) {
        me.draw.setActive(false);
      }
      me.drawActive = false;
      HsQueryBaseService.activateQueries();
    },

    removeLastPoint() {
      me.draw.removeLastPoint();
    },

    changeDrawSource(){
      me.source = me.selectedLayer.getSource()
      if (me.draw){
        me.activateDrawing(
          null, null, null, null, me.useCurrentStyle, true
        );
      };
    },

    /**
     * @function deactivateDrawing
     * @memberOf HsDrawService
     * @returns {Promise}
     * Deactivate all hs.draw interaction in map (Draw, Modify, Select)
     */
    deactivateDrawing() {
      return new Promise((resolve, reject) => {
        HsMapService.loaded().then((map) => {
          me.afterDrawEnd();
          if (me.draw) {
            map.removeInteraction(me.draw);
            me.draw = null;
          }
          resolve();
        });
      });
    },

    stopDrawing() {
      if (angular.isUndefined(me.draw) || me.draw === null) {
        return;
      }
      try {
        if (me.draw.getActive()) {
          me.draw.finishDrawing();
        }
      } catch (ex) {
        $log.warn(ex);
      }
      me.draw.setActive(false);
      me.modify.setActive(false);
    },

    startDrawing() {
      try {
        if (me.draw.getActive()) {
          me.draw.finishDrawing();
        }
      } catch (ex) {
        $log.warn(ex);
      }
      me.draw.setActive(true);
    },

    fillDrawableLayers() {
      const tmp = HsMapService.map
        .getLayers()
        .getArray()
        .filter(HsLayerUtilsService.isLayerDrawable);
      if (tmp.length > 0 && me.selectedLayer === null) {
        me.selectedLayer = tmp[0];
      }
      if (tmp.length == 0 && me.selectedLayer === null){
        me.type = null;
        me.deactivateDrawing();
      }
      me.drawableLayers = tmp;
    },
  });

  HsMapService.loaded().then((map) => {
    me.modify = new Modify({
      features: me.selectedFeatures,
    });
    map.addInteraction(me.modify);
    me.fillDrawableLayers();
  });

  me.selectedFeatures.on('add', (e) => {
    if (me.onSelected) {
      me.onSelected(e);
    }
    me.modify.setActive(true);
  });

  me.selectedFeatures.on('remove', (e) => {
    if (me.onDeselected) {
      me.onDeselected(e);
    }
  });

  const unregisterFeatureSelected = $rootScope.$on(
    'vectorQuery.featureSelected',
    (e, feature) => {
      me.selectedFeatures.push(feature);
    }
  );

  const unregisterFeatureDeselected = $rootScope.$on(
    'vectorQuery.featureDelected',
    (e, feature) => {
      me.selectedFeatures.remove(feature);
    }
  );
  return me;
}
<|endoftext|>


<commit_before>define(['js/services/targets/TargetsService'], function () {

    var hmssModule = angular.module('hmssModule');
    hmssModule.controller('TargetsController', function ($scope, $location, TargetsService) {

        var _targetData = TargetsService.getTargets();

        $scope.getTargetData = function() {
            return _targetData;
        };

        $scope.setTargetData = function(val) {
            _targetData = val;

            $scope.buildTargetMarkers();
        };

        $scope.center = {
            latitude: 32.7502, // initial map center latitude
            longitude: 6.1916, // initial map center longitude
        };

        $scope.targetMarkers = []; // an array of markers,

        $scope.zoom = 2; // the zoom level

        $scope.mapTypeId = google.maps.MapTypeId.SATELLITE;

        $scope.checkForData = function() {
            if ($scope.getTargetData() == null || $scope.getTargetData().length <= 0) {
                var promise = TargetsService.loadTargets();
                promise.success($scope.targetsSuccessHandler);
                promise.error($scope.targetsErrorHandler);
            }
        };

        $scope.buildTargetMarkers = function() {
            var updatedMarkers = [];
            for (var index in _targetData) {
                var target = _targetData[index];
                var marker = new Object();
                marker.title = target.name;
                marker.latitude = target.latitude;
                marker.longitude = target.longitude;
                updatedMarkers.push(marker);
            }

            $scope.targetMarkers = updatedMarkers;
        };

        $scope.targetRowClicked = function(target) {
            $location.path('/targetDetail/' + target.id);
        };

        $scope.$on('targetsChangedEvent', function (event, data) {
            $scope.setTargetData(data);
        });

        $scope.checkForData();
    });
});<commit_msg>Removed old listeners<commit_after>define(['js/services/targets/TargetsService'], function () {

    var hmssModule = angular.module('hmssModule');
    hmssModule.controller('TargetsController', function ($scope, $location, TargetsService) {

        var _targetData = TargetsService.getTargets();

        $scope.getTargetData = function() {
            return _targetData;
        };

        $scope.setTargetData = function(val) {
            _targetData = val;

            $scope.buildTargetMarkers();
        };

        $scope.center = {
            latitude: 32.7502, // initial map center latitude
            longitude: 6.1916, // initial map center longitude
        };

        $scope.targetMarkers = []; // an array of markers,

        $scope.zoom = 2; // the zoom level

        $scope.mapTypeId = google.maps.MapTypeId.SATELLITE;

        $scope.checkForData = function() {
            if ($scope.getTargetData() == null || $scope.getTargetData().length <= 0) {
                TargetsService.loadTargets();
            }
        };

        $scope.buildTargetMarkers = function() {
            var updatedMarkers = [];
            for (var index in _targetData) {
                var target = _targetData[index];
                var marker = new Object();
                marker.title = target.name;
                marker.latitude = target.latitude;
                marker.longitude = target.longitude;
                updatedMarkers.push(marker);
            }

            $scope.targetMarkers = updatedMarkers;
        };

        $scope.targetRowClicked = function(target) {
            $location.path('/targetDetail/' + target.id);
        };

        $scope.$on('targetsChangedEvent', function (event, data) {
            $scope.setTargetData(data);
        });

        $scope.checkForData();
    });
});<|endoftext|>


<commit_before>"use strict";

// handle post request for new link post without page reload
const submitLinkButton = document.querySelector(".postLink");
submitLinkButton.addEventListener("click", function(event) {
	event.preventDefault();
	handleNewPost();
});

function handleNewPost() {
	let subject = document.querySelector(".newPostFields input[name=subject]").value;
	let url = document.querySelector(".newPostFields input[name=url]").value;
	let description = document.querySelector(".newPostFields input[name=description]").value;
	let errorMessage = document.querySelector(".jsMessage");
	// check if all fields has content
	if (subject == "" || url == "" || description == "") {
		errorMessage.innerHTML = "Please fill out all fields.";
		errorMessage.classList.add("showError");
	} else {
		// put form input in object
		let postData = new FormData();
		postData.append("subject", subject);
		postData.append("url", url);
		postData.append("description", description);
		postData.append("postLink", "share");
		// post to php script handling post requests for new posts
		fetch("/app/posts/newpost.php",
		{
			method: "POST",
			body: postData,
			credentials: "same-origin",
		})
		// response after php script have been executed
		.then(function(response) {
			// if error
			if (!response.ok) {
				return response.text().then(function (error) {
					errorMessage.innerHTML = error;
					errorMessage.classList.add("showError");
				});
			} else {
				return response.text().then(function(result) {
					// if success remove error and reset form
					errorMessage.classList.remove("showError");
					document.querySelector(".newPostForm").reset();
					// display new post
					let newPost = document.createElement("div");
					newPost.innerHTML = result;
					newPost.classList.add("post");
					let allPosts = document.querySelector(".displayPosts");
					allPosts.insertBefore(newPost, allPosts.firstChild);
					// add event listeners to new post
					let commentButton = newPost.querySelector(".commentPost");
					commentButton.addEventListener("click", function(event) {
						event.preventDefault();
						handleCommentPost(commentButton);
					});
					let deleteButton = newPost.querySelector(".deleteButton");
					deleteButton.addEventListener("click", function(event) {
						event.preventDefault();
						if (window.confirm("Are you sure you want to delete this post?")) {
							handlePostDelete(deleteButton);
						}
					});
					let newEditButton = newPost.querySelector(".saveEdit");
					newEditButton.addEventListener("click", function(event) {
						event.preventDefault();
						handleEditPost(newEditButton);
					});
					let showSettingsButton = newPost.querySelector(".showPostSettings");
					showSettingsButton.addEventListener("click", function(event) {
						event.preventDefault();
						showSettings(showSettingsButton);
					});
					let editButton = newPost.querySelector(".editButton");
					editButton.addEventListener("click", function(event) {
						event.preventDefault();
						replacePostWithForm(editButton);
					});
					let upVoteNewPost = newPost.querySelector(".up");
					upVoteNewPost.addEventListener("click", function(event) {
						event.preventDefault();
						handleVote(upVoteNewPost, "up", 1);
					});
					let downVoteNewPost = newPost.querySelector(".down");
					downVoteNewPost.addEventListener("click", function(event) {
						event.preventDefault();
						handleVote(downVoteNewPost, "down", -1);
					});
				});
			}
		});
	}
}
<commit_msg>hide new link form on successfull post<commit_after>"use strict";

// handle post request for new link post without page reload
const submitLinkButton = document.querySelector(".postLink");
submitLinkButton.addEventListener("click", function(event) {
	event.preventDefault();
	handleNewPost();
});

function handleNewPost() {
	let subject = document.querySelector(".newPostFields input[name=subject]").value;
	let url = document.querySelector(".newPostFields input[name=url]").value;
	let description = document.querySelector(".newPostFields input[name=description]").value;
	let errorMessage = document.querySelector(".jsMessage");
	// check if all fields has content
	if (subject == "" || url == "" || description == "") {
		errorMessage.innerHTML = "Please fill out all fields.";
		errorMessage.classList.add("showError");
	} else {
		// put form input in object
		let postData = new FormData();
		postData.append("subject", subject);
		postData.append("url", url);
		postData.append("description", description);
		postData.append("postLink", "share");
		// post to php script handling post requests for new posts
		fetch("/app/posts/newpost.php",
		{
			method: "POST",
			body: postData,
			credentials: "same-origin",
		})
		// response after php script have been executed
		.then(function(response) {
			// if error
			if (!response.ok) {
				return response.text().then(function (error) {
					errorMessage.innerHTML = error;
					errorMessage.classList.add("showError");
				});
			} else {
				return response.text().then(function(result) {
					// if success remove error and reset form
					errorMessage.classList.remove("showError");
					document.querySelector(".newPostForm").reset();
					document.querySelector(".newPost").classList.remove("showNewPostForm");
					// display new post
					let newPost = document.createElement("div");
					newPost.innerHTML = result;
					newPost.classList.add("post");
					let allPosts = document.querySelector(".displayPosts");
					allPosts.insertBefore(newPost, allPosts.firstChild);
					// add event listeners to new post
					let commentButton = newPost.querySelector(".commentPost");
					commentButton.addEventListener("click", function(event) {
						event.preventDefault();
						handleCommentPost(commentButton);
					});
					let deleteButton = newPost.querySelector(".deleteButton");
					deleteButton.addEventListener("click", function(event) {
						event.preventDefault();
						if (window.confirm("Are you sure you want to delete this post?")) {
							handlePostDelete(deleteButton);
						}
					});
					let newEditButton = newPost.querySelector(".saveEdit");
					newEditButton.addEventListener("click", function(event) {
						event.preventDefault();
						handleEditPost(newEditButton);
					});
					let showSettingsButton = newPost.querySelector(".showPostSettings");
					showSettingsButton.addEventListener("click", function(event) {
						event.preventDefault();
						showSettings(showSettingsButton);
					});
					let editButton = newPost.querySelector(".editButton");
					editButton.addEventListener("click", function(event) {
						event.preventDefault();
						replacePostWithForm(editButton);
					});
					let upVoteNewPost = newPost.querySelector(".up");
					upVoteNewPost.addEventListener("click", function(event) {
						event.preventDefault();
						handleVote(upVoteNewPost, "up", 1);
					});
					let downVoteNewPost = newPost.querySelector(".down");
					downVoteNewPost.addEventListener("click", function(event) {
						event.preventDefault();
						handleVote(downVoteNewPost, "down", -1);
					});
				});
			}
		});
	}
}
<|endoftext|>


<commit_before>

(function() {
  'use strict';

  var pymChild;

  function render() {

    var data = [];
    var amounts = [];
    //Load JSON data from Google Spreadsheet
    $.getJSON('//membership.texastribune.org.s3.amazonaws.com/donors.json', function(json) {
    // $.getJSON('/scripts/donors.json', function(json) {
      data = json;
    }).done( function() {
      sortData(data);
      getAmounts(data);
      build(data);
    });

    function sortData(data) {
      data.sort(function (a, b) {
        if (a.amount > b.amount) {
          return 1;
        }
        if (a.amount < b.amount) {
          return -1;
        }
        // a must be equal to b
        return 0;
      });
      return data.reverse();
      console.log(data);
    }

    function numberWithCommas(x) {
      return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }

    function getAmounts(data) {
      for (var i = 0; i < data.length; i++) {
        var amount = data[i].amount;
        amounts.push(amount);
      }

      // var maxDonation = Math.max.apply(null, amounts);
      // console.log(maxDonation);
      amounts = $.unique(amounts);

      $.each(amounts, function( index, value ) {

        if ( value >= 1000 ) {
          $('

$' + numberWithCommas(value) + '

').appendTo('.large-donors');
        }
      });
    }

    function build(data) {
      for (var i = 0; i < data.length; i++) {
        var name = '' + data[i].attribution + '';
        var amount = data[i].amount;

        if (amount <= 10) {
          $(name).appendTo('.student');
        } else if (amount <= 35) {
          $(name).appendTo('.enthusiast');
        } else if (amount <= 60 ) {
          $(name).appendTo('.activist');
        } else if (amount <= 150 ) {
          $(name).appendTo('.advocate');
        } else if (amount <= 250 ) {
          $(name).appendTo('.diplomat');
        } else if (amount <= 500 ) {
          $(name).appendTo('.benefactor');
        } else if (amount < 1000 ) {
          $(name).appendTo('.large');
        } else {
          var className = amount.toString();
          $('.' + className).append(name);
        }
      }
    }

    if (pymChild) {
      pymChild.sendHeight();
    }
  }

  function load() {
    pymChild = new pym.Child({
      renderCallback: render
    });
  }

  window.onload = load;
})();
<commit_msg>delete unnecessary code<commit_after>

(function() {
  'use strict';

  var pymChild;

  function render() {

    var data = [];
    var amounts = [];
    //Load JSON data from Google Spreadsheet
    $.getJSON('//membership.texastribune.org.s3.amazonaws.com/donors.json', function(json) {
      data = json;
    }).done( function() {
      sortData(data);
      getAmounts(data);
      build(data);
    });

    function sortData(data) {
      data.sort(function (a, b) {
        if (a.amount > b.amount) {
          return 1;
        }
        if (a.amount < b.amount) {
          return -1;
        }
        // a must be equal to b
        return 0;
      });
      return data.reverse();
      console.log(data);
    }

    function numberWithCommas(x) {
      return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }

    function getAmounts(data) {
      for (var i = 0; i < data.length; i++) {
        var amount = data[i].amount;
        amounts.push(amount);
      }

      // var maxDonation = Math.max.apply(null, amounts);
      // console.log(maxDonation);
      amounts = $.unique(amounts);

      $.each(amounts, function( index, value ) {

        if ( value >= 1000 ) {
          $('

$' + numberWithCommas(value) + '

').appendTo('.large-donors');
        }
      });
    }

    function build(data) {
      for (var i = 0; i < data.length; i++) {
        var name = '' + data[i].attribution + '';
        var amount = data[i].amount;

        if (amount <= 10) {
          $(name).appendTo('.student');
        } else if (amount <= 35) {
          $(name).appendTo('.enthusiast');
        } else if (amount <= 60 ) {
          $(name).appendTo('.activist');
        } else if (amount <= 150 ) {
          $(name).appendTo('.advocate');
        } else if (amount <= 250 ) {
          $(name).appendTo('.diplomat');
        } else if (amount <= 500 ) {
          $(name).appendTo('.benefactor');
        } else if (amount < 1000 ) {
          $(name).appendTo('.large');
        } else {
          var className = amount.toString();
          $('.' + className).append(name);
        }
      }
    }

    if (pymChild) {
      pymChild.sendHeight();
    }
  }

  function load() {
    pymChild = new pym.Child({
      renderCallback: render
    });
  }

  window.onload = load;
})();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.core',
  name: 'Int',
  extends: 'Property',

  properties: [
    'units',
    [ 'value', 0 ],
    'min',
    'max',
    [ 'type', 'Integer' ],
    [ 'adapt', function adaptInt(_, v) {
        return typeof v === 'number' ? Math.trunc(v) :
          v ? parseInt(v) :
          0 ;
      }
    ],
    [ 'fromString', function intFromString(str) {
        return str ? parseInt(str) : 0;
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'String',
  extends: 'Property',

  documentation: 'StringProperties coerce their arguments into Strings.',

  properties: [
    { class: 'Int', name: 'width', value: 30 },
    [ 'adapt', function(_, a) {
        return typeof a === 'function' ? foam.String.multiline(a) :
               typeof a === 'number'   ? String(a)                :
               a && a.toString         ? a.toString()             :
                                         ''                       ;
      }
    ],
    [ 'type', 'String' ],
    [ 'value', '' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'ModelDocumentationRefinement',
  refines: 'foam.core.Model',

  documentation: 'Upgrade Mode.documentation to a proper String property.',

  properties: [
    { class: 'String', name: 'documentation' }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Date',
  extends: 'Property',

  // documentation: 'Describes properties of type Date.',
  label: 'Date',

  properties: [
    {
      name: 'adapt',
      value: function (_, d) {
        if ( typeof d === 'number' ) return new Date(d);
        if ( typeof d === 'string' ) {
          var ret = new Date(d);

          if ( isNaN(ret.getTime()) ) throw 'Invalid Date: ' + d;

          return ret;
        }
        return d;
      }
    },
    [ 'type', 'Date' ],
    {
      name: 'comparePropertyValues',
      value: function(o1, o2) {
        if ( ! o1 ) return o2 ? -1 : 0;
        if ( ! o2 ) return 1;

        return foam.Date.compare(o1, o2);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'DateTime',
  extends: 'Date',

  documentation: 'Describes properties of type DateTime.',
  label: 'Date and time',

  properties: [
    [ 'type', 'DateTime' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Time',
  extends: 'String',

  documentation: 'Describes properties of type Time.',
  label: 'Time',

  properties: [
    [ 'type', 'Time' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Byte',
  extends: 'Int',

  documentation: 'Describes properties of type Byte.',
  label: 'Round byte numbers',

  properties: [
    [ 'type', 'Byte' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Short',
  extends: 'Int',

  documentation: 'Describes properties of type Short.',
  label: 'Round short numbers',

  properties: [
    [ 'type', 'Short' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name:  'Long',
  extends: 'Int',

  documentation:  'Describes properties of type Long.',
  label: 'Round long numbers',

  properties: [
    [ 'type', 'Long' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Float',
  extends: 'Int',

  // documentation:  'Describes properties of type Float.',
  label: 'Decimal numbers',

  properties: [
    'precision',
    [
      'adapt',
      function (_, v) {
        return typeof v === 'number' ? v : v ? parseFloat(v) : 0.0 ;
      }
    ],
    [ 'type', 'Double' ]
  ]
});

/**
 No different than Float for JS, but useful when targeting with other languages.
 **/
foam.CLASS({
  package: 'foam.core',
  name: 'Double',
  extends: 'Float',
  properties: [
    [ 'type', 'Double' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Function',
  extends: 'Property',

  documentation: 'Describes properties of type Function.',
  label: 'Code that can be run',

  properties: [
    [
      'value',
      function() {}
    ],
    [
      'assertValue',
      function(value, prop) {
        foam.assert(typeof value === 'function', prop.name, 'Cannot set to non function type.');
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Object',
  extends: 'Property',
  documentation: '',
  properties: [
    [ 'type', 'Any' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Array',
  extends: 'Property',

  properties: [
    [
      'factory',
      function() { return []; }
    ],
    [
      'isDefaultValue',
      function(v) { return ! v || ! v.length; }
    ],
    [ 'type', 'AnyArray' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'List',
  extends: 'foam.core.Object',
  properties: [
    [ 'type', 'List' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'StringArray',
  extends: 'Property',

  documentation: 'An array of String values.',
  label: 'List of text strings',

  properties: [
    {
      name: 'of',
      value: 'String',
      documentation: 'The FOAM sub-type of this property.'
    },
    [ 'type', 'StringArray' ],
    [
      'factory',
      function() { return []; }
    ],
    [
      'adapt',
      function(_, v, prop) {
        if ( ! Array.isArray(v) ) return v;

        var copy;
        for ( var i = 0 ; i < v.length ; i++ ) {
          if ( typeof v[i] !== 'string' ) {
            if ( ! copy ) copy = v.slice();
            copy[i] = '' + v[i];
          }
        }

        return copy || v;
      }
    ],
    [
      'assertValue',
      function(v, prop) {
        if ( v === null ) return;

        foam.assert(Array.isArray(v),
            prop.name, 'Tried to set StringArray to non-array type.');
        for ( var i = 0 ; i < v.length ; i++ ) {
          foam.assert(typeof v[i] === 'string',
              prop.name, 'Element', i, 'is not a string', v[i]);
        }
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Class',
  extends: 'Property',

  properties: [
    [
      'adapt',
      function(_, v) {
        if ( v && v.class == '__Class__' )
          return v.forClass_;
        return v;
      }
    ],
    [ 'type', 'Class' ]
  ],
  methods: [
    function installInProto(proto) {
      this.SUPER(proto);

      // Wrap the getter that was installed with an adapter that will perform the lookup.
      // We don't adapt at set time because the class were referring to might not be loaded
      // at that point.
      var name = this.name;
      var desc = Object.getOwnPropertyDescriptor(proto, name);

      var adapt = function(value) {
        if ( foam.String.isInstance(value) ) {
          var cls = this.__context__.lookup(value, true);
          if ( ! cls ) {
            console.error(`Property '${name}' of type '${this.model_.name}' was set to '${value}', which isn't a valid class.`);
            return null;
          }
          return cls;
        }
        return value;
      };

      var get = desc.get;
      desc.get = function() {
        return adapt.call(this, get.call(this));
      };

      Object.defineProperty(proto, name, desc);

      Object.defineProperty(proto, name + '$cls', {
        get: function classGetter() {
          console.warn("Deprecated use of 'cls.$cls'. Just use 'cls' instead.");
          return typeof this[name] !== 'string' ? this[name] :
            this.__context__.lookup(this[name], true);
        },
        configurable: true
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'EMail',
  extends: 'String',
  // FUTURE: verify
  label: 'Email address'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Image',
  extends: 'String',
  // FUTURE: verify
  label: 'Image data or link',
  properties: [ [ 'displayWidth', 80 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'URL',
  extends: 'String',
  // FUTURE: verify
  label: 'Web link (URL or internet address)',
  properties: [ [ 'displayWidth', 80 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Color',
  extends: 'String',
  label: 'Color',
  properties: [ [ 'displayWidth', 20 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Password',
  extends: 'String',
  label: 'Password that displays protected or hidden text'
});

foam.CLASS({
  package: 'foam.core',
  name: 'PhoneNumber',
  extends: 'String',
  label: 'Phone number'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Currency',
  extends: 'Long'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Map',
  extends: 'Property',

  // TODO: Remove need for sorting
  properties: [
    [ 'factory', function() { return {} } ],
    [
      'comparePropertyValues',
      function(o1, o2) {
        if ( foam.typeOf(o1) != foam.typeOf(o2) ) return -1;

        var keys1 = Object.keys(o1).sort();
        var keys2 = Object.keys(o2).sort();
        if ( keys1.length < keys2.length ) return -1;
        if ( keys1.length > keys2.length ) return 1;
        for ( var i = 0 ; i < keys1.length ; i++ ) {
          var c = foam.String.compare(keys1[i], keys2[i]);
          if ( c != 0 ) return c;
          c = foam.util.compare(o1[keys1[i]], o2[keys2[i]]);
          if ( c != 0 ) return c;
        }

        return 0;
      }
    ],
    [
      'cloneProperty',
      function(value, cloneMap) {
        if ( value ) {
          var tmp = cloneMap[this.name] = {};
          for ( var key in value ) {
            tmp[key] = value[key];
          }
        }
      }
    ],
    [
      'diffPropertyValues',
      function(o1, o2) {
        // TODO
      }
    ],
    [ 'type', 'Map' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'FObjectProperty',
  extends: 'Property',

  properties: [
    {
      class: 'Class',
      name: 'of',
      value: 'foam.core.FObject'
    },
    {
      name: 'type',
      factory: function() { return this.of.id; }
    },
    {
      name: 'fromJSON',
      value: function(json, ctx, prop) {
        return foam.json.parse(json, foam.lookup(prop.type), ctx);
      }
    },
    {
      name: 'adapt',
      value: function(_, v, prop) {
        // All FObjects may be null.
        if (v === null) return v;

        var type = foam.lookup(prop.type);

        return type.isInstance(v) ?
            v :
            ( v.class ?
                this.__context__.lookup(v.class) :
                type ).create(v, this.__subContext__);
      }
    }
  ],
  methods: [
    function xinitObject(obj) {
      var s1, s2;

      obj.onDetach(function() {
        s1 && s1.detach();
        s2 && s2.detach();
      });

      var name = this.name;
      var slot = this.toSlot(obj);

      function proxyListener(sub) {
        var args = [
          'nestedPropertyChange', name, slot
        ].concat(Array.from(arguments).slice(1));

        obj.pub.apply(obj, args);
      }

      function attach(inner) {
        s1 && s1.detach();
        s1 = inner && inner.sub && inner.sub('propertyChange', proxyListener);

        s2 && s2.detach();
        s2 = inner && inner.sub && inner.sub('nestedPropertyChange', proxyListener);
      }

      function listener(s, pc, name, slot) {
        attach(slot.get());
      }

      obj.sub('propertyChange', name, listener);

      // TODO: Only hook up the subscription when somebody listens to us.
      if ( obj[name] ) attach(obj[name]);
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Reference',
  extends: 'Property',

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    [ 'type', 'Any' ],
    {
      class: 'String',
      name: 'targetDAOKey',
      expression: function(of) {
        if ( ! of ) {
          console.error("invalid 'of' for property with targetDAOKey", this.name);
        }
        return foam.String.daoize(of.name);
      }
    },
    {
      name: 'adapt',
      value: function(oldValue, newValue, prop) {
        return prop.of.isInstance(newValue) ?
          newValue.id :
          newValue ;
      }
    }
  ],

  methods: [
    function installInProto(proto) {
      this.SUPER(proto);
      var key  = this.targetDAOKey;
      var name = this.name;

      Object.defineProperty(proto, name + '$find', {
        get: function classGetter() {
          return this.__context__[key].find(this[name]);
        },
        configurable: true
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'ModelUpgradeTypesRefinement',
  refines: 'foam.core.Model',

  documentation: 'Update Model Property types.',

  properties: [
    { class: 'String',  name: 'name' },
    { class: 'Boolean', name: 'abstract' }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'FacetedPropertyRefinement',
  refines: 'foam.core.Property',

  axioms: [
    foam.pattern.Faceted.create()
  ],

  properties: [
    {
      name: 'of'
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'PropertyShortNameRefinement',
  refines: 'Property',

  properties: [
    /**
      A short-name is an optional shorter name for a property.
      It is used by JSON and XML support when 'useShortNames'
      is enabled. Short-names enable output to be smaller,
      which can save disk space and/or network bandwidth.
      Ex.
    <pre>
      properties: [
        { name: 'firstName', shortName: 'fn' },
        { name: 'lastName',  shortName: 'ln' }
      ]
    </pre>
    */
    { class: 'String', name: 'shortName' }
  ]
});

// Upgrade async property to a real boolean property.
foam.CLASS({
  package: 'foam.core',
  name: 'AbstractMethodUpgradeTypesRefinement',
  refines: 'foam.core.AbstractMethod',
  properties: [
    {
      class: 'Boolean',
      name: 'async',
      value: false
    }
  ]
});
<commit_msg>Delay touching targetDAOKey in Reference until it's actually needed to prevent triggering an expression before we need to.<commit_after>/**
 * @license
 * Copyright 2016 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.core',
  name: 'Int',
  extends: 'Property',

  properties: [
    'units',
    [ 'value', 0 ],
    'min',
    'max',
    [ 'type', 'Integer' ],
    [ 'adapt', function adaptInt(_, v) {
        return typeof v === 'number' ? Math.trunc(v) :
          v ? parseInt(v) :
          0 ;
      }
    ],
    [ 'fromString', function intFromString(str) {
        return str ? parseInt(str) : 0;
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'String',
  extends: 'Property',

  documentation: 'StringProperties coerce their arguments into Strings.',

  properties: [
    { class: 'Int', name: 'width', value: 30 },
    [ 'adapt', function(_, a) {
        return typeof a === 'function' ? foam.String.multiline(a) :
               typeof a === 'number'   ? String(a)                :
               a && a.toString         ? a.toString()             :
                                         ''                       ;
      }
    ],
    [ 'type', 'String' ],
    [ 'value', '' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'ModelDocumentationRefinement',
  refines: 'foam.core.Model',

  documentation: 'Upgrade Mode.documentation to a proper String property.',

  properties: [
    { class: 'String', name: 'documentation' }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Date',
  extends: 'Property',

  // documentation: 'Describes properties of type Date.',
  label: 'Date',

  properties: [
    {
      name: 'adapt',
      value: function (_, d) {
        if ( typeof d === 'number' ) return new Date(d);
        if ( typeof d === 'string' ) {
          var ret = new Date(d);

          if ( isNaN(ret.getTime()) ) throw 'Invalid Date: ' + d;

          return ret;
        }
        return d;
      }
    },
    [ 'type', 'Date' ],
    {
      name: 'comparePropertyValues',
      value: function(o1, o2) {
        if ( ! o1 ) return o2 ? -1 : 0;
        if ( ! o2 ) return 1;

        return foam.Date.compare(o1, o2);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'DateTime',
  extends: 'Date',

  documentation: 'Describes properties of type DateTime.',
  label: 'Date and time',

  properties: [
    [ 'type', 'DateTime' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Time',
  extends: 'String',

  documentation: 'Describes properties of type Time.',
  label: 'Time',

  properties: [
    [ 'type', 'Time' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Byte',
  extends: 'Int',

  documentation: 'Describes properties of type Byte.',
  label: 'Round byte numbers',

  properties: [
    [ 'type', 'Byte' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Short',
  extends: 'Int',

  documentation: 'Describes properties of type Short.',
  label: 'Round short numbers',

  properties: [
    [ 'type', 'Short' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name:  'Long',
  extends: 'Int',

  documentation:  'Describes properties of type Long.',
  label: 'Round long numbers',

  properties: [
    [ 'type', 'Long' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Float',
  extends: 'Int',

  // documentation:  'Describes properties of type Float.',
  label: 'Decimal numbers',

  properties: [
    'precision',
    [
      'adapt',
      function (_, v) {
        return typeof v === 'number' ? v : v ? parseFloat(v) : 0.0 ;
      }
    ],
    [ 'type', 'Double' ]
  ]
});

/**
 No different than Float for JS, but useful when targeting with other languages.
 **/
foam.CLASS({
  package: 'foam.core',
  name: 'Double',
  extends: 'Float',
  properties: [
    [ 'type', 'Double' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Function',
  extends: 'Property',

  documentation: 'Describes properties of type Function.',
  label: 'Code that can be run',

  properties: [
    [
      'value',
      function() {}
    ],
    [
      'assertValue',
      function(value, prop) {
        foam.assert(typeof value === 'function', prop.name, 'Cannot set to non function type.');
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Object',
  extends: 'Property',
  documentation: '',
  properties: [
    [ 'type', 'Any' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Array',
  extends: 'Property',

  properties: [
    [
      'factory',
      function() { return []; }
    ],
    [
      'isDefaultValue',
      function(v) { return ! v || ! v.length; }
    ],
    [ 'type', 'AnyArray' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'List',
  extends: 'foam.core.Object',
  properties: [
    [ 'type', 'List' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'StringArray',
  extends: 'Property',

  documentation: 'An array of String values.',
  label: 'List of text strings',

  properties: [
    {
      name: 'of',
      value: 'String',
      documentation: 'The FOAM sub-type of this property.'
    },
    [ 'type', 'StringArray' ],
    [
      'factory',
      function() { return []; }
    ],
    [
      'adapt',
      function(_, v, prop) {
        if ( ! Array.isArray(v) ) return v;

        var copy;
        for ( var i = 0 ; i < v.length ; i++ ) {
          if ( typeof v[i] !== 'string' ) {
            if ( ! copy ) copy = v.slice();
            copy[i] = '' + v[i];
          }
        }

        return copy || v;
      }
    ],
    [
      'assertValue',
      function(v, prop) {
        if ( v === null ) return;

        foam.assert(Array.isArray(v),
            prop.name, 'Tried to set StringArray to non-array type.');
        for ( var i = 0 ; i < v.length ; i++ ) {
          foam.assert(typeof v[i] === 'string',
              prop.name, 'Element', i, 'is not a string', v[i]);
        }
      }
    ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Class',
  extends: 'Property',

  properties: [
    [
      'adapt',
      function(_, v) {
        if ( v && v.class == '__Class__' )
          return v.forClass_;
        return v;
      }
    ],
    [ 'type', 'Class' ]
  ],
  methods: [
    function installInProto(proto) {
      this.SUPER(proto);

      // Wrap the getter that was installed with an adapter that will perform the lookup.
      // We don't adapt at set time because the class were referring to might not be loaded
      // at that point.
      var name = this.name;
      var desc = Object.getOwnPropertyDescriptor(proto, name);

      var adapt = function(value) {
        if ( foam.String.isInstance(value) ) {
          var cls = this.__context__.lookup(value, true);
          if ( ! cls ) {
            console.error(`Property '${name}' of type '${this.model_.name}' was set to '${value}', which isn't a valid class.`);
            return null;
          }
          return cls;
        }
        return value;
      };

      var get = desc.get;
      desc.get = function() {
        return adapt.call(this, get.call(this));
      };

      Object.defineProperty(proto, name, desc);

      Object.defineProperty(proto, name + '$cls', {
        get: function classGetter() {
          console.warn("Deprecated use of 'cls.$cls'. Just use 'cls' instead.");
          return typeof this[name] !== 'string' ? this[name] :
            this.__context__.lookup(this[name], true);
        },
        configurable: true
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'EMail',
  extends: 'String',
  // FUTURE: verify
  label: 'Email address'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Image',
  extends: 'String',
  // FUTURE: verify
  label: 'Image data or link',
  properties: [ [ 'displayWidth', 80 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'URL',
  extends: 'String',
  // FUTURE: verify
  label: 'Web link (URL or internet address)',
  properties: [ [ 'displayWidth', 80 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Color',
  extends: 'String',
  label: 'Color',
  properties: [ [ 'displayWidth', 20 ] ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Password',
  extends: 'String',
  label: 'Password that displays protected or hidden text'
});

foam.CLASS({
  package: 'foam.core',
  name: 'PhoneNumber',
  extends: 'String',
  label: 'Phone number'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Currency',
  extends: 'Long'
});

foam.CLASS({
  package: 'foam.core',
  name: 'Map',
  extends: 'Property',

  // TODO: Remove need for sorting
  properties: [
    [ 'factory', function() { return {} } ],
    [
      'comparePropertyValues',
      function(o1, o2) {
        if ( foam.typeOf(o1) != foam.typeOf(o2) ) return -1;

        var keys1 = Object.keys(o1).sort();
        var keys2 = Object.keys(o2).sort();
        if ( keys1.length < keys2.length ) return -1;
        if ( keys1.length > keys2.length ) return 1;
        for ( var i = 0 ; i < keys1.length ; i++ ) {
          var c = foam.String.compare(keys1[i], keys2[i]);
          if ( c != 0 ) return c;
          c = foam.util.compare(o1[keys1[i]], o2[keys2[i]]);
          if ( c != 0 ) return c;
        }

        return 0;
      }
    ],
    [
      'cloneProperty',
      function(value, cloneMap) {
        if ( value ) {
          var tmp = cloneMap[this.name] = {};
          for ( var key in value ) {
            tmp[key] = value[key];
          }
        }
      }
    ],
    [
      'diffPropertyValues',
      function(o1, o2) {
        // TODO
      }
    ],
    [ 'type', 'Map' ]
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'FObjectProperty',
  extends: 'Property',

  properties: [
    {
      class: 'Class',
      name: 'of',
      value: 'foam.core.FObject'
    },
    {
      name: 'type',
      factory: function() { return this.of.id; }
    },
    {
      name: 'fromJSON',
      value: function(json, ctx, prop) {
        return foam.json.parse(json, foam.lookup(prop.type), ctx);
      }
    },
    {
      name: 'adapt',
      value: function(_, v, prop) {
        // All FObjects may be null.
        if (v === null) return v;

        var type = foam.lookup(prop.type);

        return type.isInstance(v) ?
            v :
            ( v.class ?
                this.__context__.lookup(v.class) :
                type ).create(v, this.__subContext__);
      }
    }
  ],
  methods: [
    function xinitObject(obj) {
      var s1, s2;

      obj.onDetach(function() {
        s1 && s1.detach();
        s2 && s2.detach();
      });

      var name = this.name;
      var slot = this.toSlot(obj);

      function proxyListener(sub) {
        var args = [
          'nestedPropertyChange', name, slot
        ].concat(Array.from(arguments).slice(1));

        obj.pub.apply(obj, args);
      }

      function attach(inner) {
        s1 && s1.detach();
        s1 = inner && inner.sub && inner.sub('propertyChange', proxyListener);

        s2 && s2.detach();
        s2 = inner && inner.sub && inner.sub('nestedPropertyChange', proxyListener);
      }

      function listener(s, pc, name, slot) {
        attach(slot.get());
      }

      obj.sub('propertyChange', name, listener);

      // TODO: Only hook up the subscription when somebody listens to us.
      if ( obj[name] ) attach(obj[name]);
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'Reference',
  extends: 'Property',

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    [ 'type', 'Any' ],
    {
      class: 'String',
      name: 'targetDAOKey',
      expression: function(of) {
        if ( ! of ) {
          console.error("invalid 'of' for property with targetDAOKey", this.name);
        }
        return foam.String.daoize(of.name);
      }
    },
    {
      name: 'adapt',
      value: function(oldValue, newValue, prop) {
        return prop.of.isInstance(newValue) ?
          newValue.id :
          newValue ;
      }
    }
  ],

  methods: [
    function installInProto(proto) {
      this.SUPER(proto);
      var self = this;
      Object.defineProperty(proto, self.name + '$find', {
        get: function classGetter() {
          return this.__context__[self.targetDAOKey].find(this[self.name]);
        },
        configurable: true
      });
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'ModelUpgradeTypesRefinement',
  refines: 'foam.core.Model',

  documentation: 'Update Model Property types.',

  properties: [
    { class: 'String',  name: 'name' },
    { class: 'Boolean', name: 'abstract' }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'FacetedPropertyRefinement',
  refines: 'foam.core.Property',

  axioms: [
    foam.pattern.Faceted.create()
  ],

  properties: [
    {
      name: 'of'
    }
  ]
});

foam.CLASS({
  package: 'foam.core',
  name: 'PropertyShortNameRefinement',
  refines: 'Property',

  properties: [
    /**
      A short-name is an optional shorter name for a property.
      It is used by JSON and XML support when 'useShortNames'
      is enabled. Short-names enable output to be smaller,
      which can save disk space and/or network bandwidth.
      Ex.
    <pre>
      properties: [
        { name: 'firstName', shortName: 'fn' },
        { name: 'lastName',  shortName: 'ln' }
      ]
    </pre>
    */
    { class: 'String', name: 'shortName' }
  ]
});

// Upgrade async property to a real boolean property.
foam.CLASS({
  package: 'foam.core',
  name: 'AbstractMethodUpgradeTypesRefinement',
  refines: 'foam.core.AbstractMethod',
  properties: [
    {
      class: 'Boolean',
      name: 'async',
      value: false
    }
  ]
});
<|endoftext|>


<commit_before>import React from 'react';
import './App.css';

// Components
import Main from './Components/Main';

class App extends React.Component {
  render() {
    return (
      <Main />
    );
  }
}

export default App;
<commit_msg>Using stateless function for App<commit_after>import React from 'react';
import './App.css';

// Components
import Main from './Components/Main';

const App = () => (
  <Main />
);

export default App;
<|endoftext|>


<commit_before>'use strict';
const BasePluginGenerator = require('../../utils').Base;
const chalk = require('chalk');
class PluginGenerator extends BasePluginGenerator {

  initializing() {
    return super.initializing();
  }

  default() {
    return super.default();
  }

  writing() {
    return super.writing();
  }

  end() {
    this.log('\n\nnext steps: ');
    this.log(chalk.yellow(' npm install'));
    this.log(chalk.yellow(` npm build`));
  }
}

module.exports = PluginGenerator;
<commit_msg>remove end part with next steps from init-lib<commit_after>'use strict';
const BasePluginGenerator = require('../../utils').Base;
const chalk = require('chalk');
class PluginGenerator extends BasePluginGenerator {

  initializing() {
    return super.initializing();
  }

  default() {
    return super.default();
  }

  writing() {
    return super.writing();
  }
}

module.exports = PluginGenerator;
<|endoftext|>