<commit_before>iD.Map = function(context) {
    var dimensions = [1, 1],
        dispatch = d3.dispatch('move', 'drawn'),
        projection = d3.geo.mercator().scale(512 / Math.PI),
        roundedProjection = iD.svg.RoundProjection(projection),
        zoom = d3.behavior.zoom()
            .translate(projection.translate())
            .scale(projection.scale() * 2 * Math.PI)
            .scaleExtent([1024, 256 * Math.pow(2, 24)])
            .on('zoom', zoomPan),
        dblclickEnabled = true,
        transformStart,
        transformed = false,
        minzoom = 0,
        layers = [
            iD.Background().projection(projection),
            iD.LocalGpx(context).projection(projection),
            iD.Background('overlay').projection(projection)
        ],
        transformProp = iD.util.prefixCSSProperty('Transform'),
        points = iD.svg.Points(roundedProjection, context),
        vertices = iD.svg.Vertices(roundedProjection, context),
        lines = iD.svg.Lines(projection),
        areas = iD.svg.Areas(roundedProjection),
        midpoints = iD.svg.Midpoints(roundedProjection, context),
        labels = iD.svg.Labels(roundedProjection, context),
        tail = iD.ui.Tail(),
        supersurface, surface,
        mouse;

    function map(selection) {
        context.history()
            .on('change.map', redraw);

        context.on('select.map', function() {
            redraw();
        });

        selection.call(zoom);

        supersurface = selection.append('div')
            .attr('id', 'supersurface');

        layers.forEach(function(layer) {
            supersurface.call(layer);
        });

        // Need a wrapper div because Opera can't cope with an absolutely positioned
        // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
        var dataLayer = supersurface.append('div')
            .attr('class', 'layer-layer layer-data');

        surface = dataLayer.append('svg')
            .on('mousedown.zoom', function() {
                if (d3.event.button == 2) {
                    d3.event.stopPropagation();
                }
            }, true)
            .on('mouseup.zoom', function() {
                if (resetTransform()) redraw();
            })
            .attr('id', 'surface')
            .call(iD.svg.Surface(context));

        surface.on('mouseover.vertices', function() {
            if (map.editable() && !transformed) {
                var hover = d3.event.target.__data__;
                surface.call(vertices.drawHover, context.graph(), hover, map.zoom());
                dispatch.drawn(map);
            }
        });

        surface.on('mouseout.vertices', function() {
            if (map.editable() && !transformed) {
                var hover = d3.event.relatedTarget && d3.event.relatedTarget.__data__;
                surface.call(vertices.drawHover, context.graph(), hover, map.zoom());
                dispatch.drawn(map);
            }
        });

        map.size(selection.size());
        map.surface = surface;

        labels.supersurface(supersurface);
        mouse = iD.util.fastMouse(supersurface.node());

        supersurface
            .call(tail);
    }

    function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }

    function drawVector(difference) {
        var filter, all,
            extent = map.extent(),
            graph = context.graph();

        if (!difference) {
            all = context.intersects(extent);
            filter = d3.functor(true);
        } else {
            var complete = difference.complete(extent);
            all = _.compact(_.values(complete));
            filter = function(d) {
                if (d.type === 'midpoint') {

                    var a = d.edge[0],
                        b = d.edge[1];

                    // redraw a midpoint if it needs to be
                    // - moved (either edge node moved)
                    // - deleted (edge nodes not consecutive in any parent way)
                    if (a in complete || b in complete) return true;

                    var parentsWays = graph.parentWays({ id: a });
                    for (var i = 0; i < parentsWays.length; i++) {
                        var nodes = parentsWays[i].nodes;
                        for (var n = 0; n < nodes.length; n++) {
                            if (nodes[n] === a && (nodes[n - 1] === b || nodes[n + 1] === b)) return false;
                        }
                    }
                    return true;

                } else {
                    return d.id in complete;
                }
            };
        }

        if (all.length > 100000) {
            editOff();
        } else {
            surface
                .call(points, graph, all, filter)
                .call(vertices, graph, all, filter, map.zoom())
                .call(lines, graph, all, filter)
                .call(areas, graph, all, filter)
                .call(midpoints, graph, all, filter, extent)
                .call(labels, graph, all, filter, dimensions, !difference);
        }
        dispatch.drawn(map);
    }

    function editOff() {
        surface.selectAll('.layer *').remove();
    }

    var translate3d = !iD.detect().opera &&
        iD.util.stringQs(location.search.substring(1)).translate3d !== '0';

    function zoomPan() {
        if (d3.event && d3.event.sourceEvent.type === 'dblclick') {
            if (!dblclickEnabled) {
                zoom.scale(projection.scale() * 2 * Math.PI)
                    .translate(projection.translate());
                return d3.event.sourceEvent.preventDefault();
            }
        }

        if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) {
            iD.ui.flash(context.container())
                .select('.content')
                .text(t('cannot_zoom'));
            return setZoom(16, true);
        }

        projection
            .translate(d3.event.translate)
            .scale(d3.event.scale / (2 * Math.PI));

        var ascale = d3.event.scale;
        var bscale = transformStart[0];
        var scale = (ascale / bscale);

        var tX = Math.round((d3.event.translate[0] / scale) - (transformStart[1][0]));
        var tY = Math.round((d3.event.translate[1] / scale) - (transformStart[1][1]));

        var transform =
            'scale(' + scale + ')' +
            (translate3d ?
                'translate3d(' + tX + 'px,' + tY + 'px, 0)' :
                'translate(' + tX + 'px,' + tY + 'px)');

        transformed = true;
        supersurface.style(transformProp, transform);

        if (tX || tY) {
            context.container().selectAll('#map')
                .classed('panning', true);
        }

        queueRedraw();

        dispatch.move(map);
    }

    function resetTransform() {
        if (!transformed) return false;
        supersurface.style(transformProp, '');
        context.container().selectAll('#map')
            .classed('panning', false);
        transformed = false;
        return true;
    }

    function redraw(difference) {

        if (!surface) return;

        clearTimeout(timeoutId);

        // If we are in the middle of a zoom/pan, we can't do differenced redraws.
        // It would result in artifacts where differenced entities are redrawn with
        // one transform and unchanged entities with another.
        if (resetTransform()) {
            difference = undefined;
        }

        var zoom = String(~~map.zoom());
        if (surface.attr('data-zoom') !== zoom) {
            surface.attr('data-zoom', zoom);
        }

        if (!difference) {
            layers.forEach(function(layer) {
                supersurface.call(layer);
            });
        }

        if (map.editable()) {
            context.connection().loadTiles(projection, dimensions);
            drawVector(difference);
        } else {
            editOff();
        }

        transformStart = [
            projection.scale() * 2 * Math.PI,
            projection.translate().slice()];

        return map;
    }

    var timeoutId;
    function queueRedraw() {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() { redraw(); }, 300);
    }

    function pointLocation(p) {
        var translate = projection.translate(),
            scale = projection.scale() * 2 * Math.PI;
        return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
    }

    function locationPoint(l) {
        var translate = projection.translate(),
            scale = projection.scale() * 2 * Math.PI;
        return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
    }

    map.mouse = function() {
        var e = d3.event, s;
        while (s = e.sourceEvent) e = s;
        return mouse(e);
    };

    map.mouseCoordinates = function() {
        return projection.invert(map.mouse());
    };

    map.dblclickEnable = function(_) {
        if (!arguments.length) return dblclickEnabled;
        dblclickEnabled = _;
        return map;
    };

    function setZoom(z, force) {
        if (z === map.zoom() && !force)
            return false;
        var scale = 256 * Math.pow(2, z),
            center = pxCenter(),
            l = pointLocation(center);
        scale = Math.max(1024, Math.min(256 * Math.pow(2, 24), scale));
        projection.scale(scale / (2 * Math.PI));
        zoom.scale(scale);
        var t = projection.translate();
        l = locationPoint(l);
        t[0] += center[0] - l[0];
        t[1] += center[1] - l[1];
        projection.translate(t);
        zoom.translate(projection.translate());
        return true;
    }

    function setCenter(loc) {
        var t = projection.translate(),
            c = pxCenter(),
            ll = projection(loc);
        if (ll[0] === c[0] && ll[1] === c[1])
            return false;
        projection.translate([
            t[0] - ll[0] + c[0],
            t[1] - ll[1] + c[1]]);
        zoom.translate(projection.translate());
        return true;
    }

    map.pan = function(d) {
        var t = projection.translate();
        t[0] += d[0];
        t[1] += d[1];
        projection.translate(t);
        zoom.translate(projection.translate());
        dispatch.move(map);
        return redraw();
    };

    map.size = function(_) {
        if (!arguments.length) return dimensions;
        var center = map.center();
        dimensions = _;
        surface.size(dimensions);
        layers.forEach(function(layer) {
            layer.size(dimensions);
        });
        projection.clipExtent([[0, 0], dimensions]);
        setCenter(center);
        return redraw();
    };

    map.zoomIn = function() { return map.zoom(Math.ceil(map.zoom() + 1)); };
    map.zoomOut = function() { return map.zoom(Math.floor(map.zoom() - 1)); };

    map.center = function(loc) {
        if (!arguments.length) {
            return projection.invert(pxCenter());
        }

        if (setCenter(loc)) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.zoom = function(z) {
        if (!arguments.length) {
            return Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.LN2 - 8, 0);
        }

        if (setZoom(z)) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.zoomTo = function(entity) {
        var extent = entity.extent(context.graph()),
            zoom = map.extentZoom(extent);
        map.centerZoom(extent.center(), zoom);
    };

    map.centerZoom = function(loc, z) {
        var centered = setCenter(loc),
            zoomed   = setZoom(z);

        if (centered || zoomed) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.centerEase = function(loc) {
        var from = map.center().slice(),
            t = 0,
            stop;

        surface.one('mousedown.ease', function() {
            stop = true;
        });

        d3.timer(function() {
            if (stop) return true;
            map.center(iD.geo.interp(from, loc, (t += 1) / 10));
            return t == 10;
        }, 20);
        return map;
    };

    map.extent = function(_) {
        if (!arguments.length) {
            return new iD.geo.Extent(projection.invert([0, dimensions[1]]),
                                 projection.invert([dimensions[0], 0]));
        } else {
            var extent = iD.geo.Extent(_);
            map.centerZoom(extent.center(), map.extentZoom(extent));
        }
    };

    map.extentZoom = function(_) {
        var extent = iD.geo.Extent(_),
            tl = projection([extent[0][0], extent[1][1]]),
            br = projection([extent[1][0], extent[0][1]]);

        // Calculate maximum zoom that fits extent
        var hFactor = (br[0] - tl[0]) / dimensions[0],
            vFactor = (br[1] - tl[1]) / dimensions[1],
            hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
            vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
            newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);

        return newZoom;
    };

    map.flush = function() {
        context.connection().flush();
        context.history().reset();
        return map;
    };

    var usedTails = {};
    map.tail = function(_) {
        if (!_ || usedTails[_] === undefined) {
            tail.text(_);
            usedTails[_] = true;
        }
        return map;
    };

    map.editable = function() {
        return map.zoom() >= 16;
    };

    map.minzoom = function(_) {
        if (!arguments.length) return minzoom;
        minzoom = _;
        return map;
    };

    map.layers = layers;
    map.projection = projection;
    map.redraw = redraw;

    return d3.rebind(map, dispatch, 'on');
};
<commit_msg>Only redraw vertices when selection changes<commit_after>iD.Map = function(context) {
    var dimensions = [1, 1],
        dispatch = d3.dispatch('move', 'drawn'),
        projection = d3.geo.mercator().scale(512 / Math.PI),
        roundedProjection = iD.svg.RoundProjection(projection),
        zoom = d3.behavior.zoom()
            .translate(projection.translate())
            .scale(projection.scale() * 2 * Math.PI)
            .scaleExtent([1024, 256 * Math.pow(2, 24)])
            .on('zoom', zoomPan),
        dblclickEnabled = true,
        transformStart,
        transformed = false,
        minzoom = 0,
        layers = [
            iD.Background().projection(projection),
            iD.LocalGpx(context).projection(projection),
            iD.Background('overlay').projection(projection)
        ],
        transformProp = iD.util.prefixCSSProperty('Transform'),
        points = iD.svg.Points(roundedProjection, context),
        vertices = iD.svg.Vertices(roundedProjection, context),
        lines = iD.svg.Lines(projection),
        areas = iD.svg.Areas(roundedProjection),
        midpoints = iD.svg.Midpoints(roundedProjection, context),
        labels = iD.svg.Labels(roundedProjection, context),
        tail = iD.ui.Tail(),
        supersurface, surface,
        mouse;

    function map(selection) {
        context.history()
            .on('change.map', redraw);

        selection.call(zoom);

        supersurface = selection.append('div')
            .attr('id', 'supersurface');

        layers.forEach(function(layer) {
            supersurface.call(layer);
        });

        // Need a wrapper div because Opera can't cope with an absolutely positioned
        // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
        var dataLayer = supersurface.append('div')
            .attr('class', 'layer-layer layer-data');

        surface = dataLayer.append('svg')
            .on('mousedown.zoom', function() {
                if (d3.event.button == 2) {
                    d3.event.stopPropagation();
                }
            }, true)
            .on('mouseup.zoom', function() {
                if (resetTransform()) redraw();
            })
            .attr('id', 'surface')
            .call(iD.svg.Surface(context));

        surface.on('mouseover.vertices', function() {
            if (map.editable() && !transformed) {
                var hover = d3.event.target.__data__;
                surface.call(vertices.drawHover, context.graph(), hover, map.zoom());
                dispatch.drawn(map);
            }
        });

        surface.on('mouseout.vertices', function() {
            if (map.editable() && !transformed) {
                var hover = d3.event.relatedTarget && d3.event.relatedTarget.__data__;
                surface.call(vertices.drawHover, context.graph(), hover, map.zoom());
                dispatch.drawn(map);
            }
        });

        context.on('select.map', function() {
            if (map.editable() && !transformed) {
                var all = context.intersects(map.extent()),
                    filter = d3.functor(true),
                    extent = map.extent(),
                    graph = context.graph();
                surface.call(vertices, graph, all, filter, map.zoom());
                surface.call(midpoints, graph, all, filter, extent);
                dispatch.drawn(map);
            }
        });

        map.size(selection.size());
        map.surface = surface;

        labels.supersurface(supersurface);
        mouse = iD.util.fastMouse(supersurface.node());

        supersurface
            .call(tail);
    }

    function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }

    function drawVector(difference) {
        var filter, all,
            extent = map.extent(),
            graph = context.graph();

        if (!difference) {
            all = context.intersects(extent);
            filter = d3.functor(true);
        } else {
            var complete = difference.complete(extent);
            all = _.compact(_.values(complete));
            filter = function(d) {
                if (d.type === 'midpoint') {

                    var a = d.edge[0],
                        b = d.edge[1];

                    // redraw a midpoint if it needs to be
                    // - moved (either edge node moved)
                    // - deleted (edge nodes not consecutive in any parent way)
                    if (a in complete || b in complete) return true;

                    var parentsWays = graph.parentWays({ id: a });
                    for (var i = 0; i < parentsWays.length; i++) {
                        var nodes = parentsWays[i].nodes;
                        for (var n = 0; n < nodes.length; n++) {
                            if (nodes[n] === a && (nodes[n - 1] === b || nodes[n + 1] === b)) return false;
                        }
                    }
                    return true;

                } else {
                    return d.id in complete;
                }
            };
        }

        if (all.length > 100000) {
            editOff();
        } else {
            surface
                .call(points, graph, all, filter)
                .call(vertices, graph, all, filter, map.zoom())
                .call(lines, graph, all, filter)
                .call(areas, graph, all, filter)
                .call(midpoints, graph, all, filter, extent)
                .call(labels, graph, all, filter, dimensions, !difference);
        }
        dispatch.drawn(map);
    }

    function editOff() {
        surface.selectAll('.layer *').remove();
    }

    var translate3d = !iD.detect().opera &&
        iD.util.stringQs(location.search.substring(1)).translate3d !== '0';

    function zoomPan() {
        if (d3.event && d3.event.sourceEvent.type === 'dblclick') {
            if (!dblclickEnabled) {
                zoom.scale(projection.scale() * 2 * Math.PI)
                    .translate(projection.translate());
                return d3.event.sourceEvent.preventDefault();
            }
        }

        if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) {
            iD.ui.flash(context.container())
                .select('.content')
                .text(t('cannot_zoom'));
            return setZoom(16, true);
        }

        projection
            .translate(d3.event.translate)
            .scale(d3.event.scale / (2 * Math.PI));

        var ascale = d3.event.scale;
        var bscale = transformStart[0];
        var scale = (ascale / bscale);

        var tX = Math.round((d3.event.translate[0] / scale) - (transformStart[1][0]));
        var tY = Math.round((d3.event.translate[1] / scale) - (transformStart[1][1]));

        var transform =
            'scale(' + scale + ')' +
            (translate3d ?
                'translate3d(' + tX + 'px,' + tY + 'px, 0)' :
                'translate(' + tX + 'px,' + tY + 'px)');

        transformed = true;
        supersurface.style(transformProp, transform);

        if (tX || tY) {
            context.container().selectAll('#map')
                .classed('panning', true);
        }

        queueRedraw();

        dispatch.move(map);
    }

    function resetTransform() {
        if (!transformed) return false;
        supersurface.style(transformProp, '');
        context.container().selectAll('#map')
            .classed('panning', false);
        transformed = false;
        return true;
    }

    function redraw(difference) {

        if (!surface) return;

        clearTimeout(timeoutId);

        // If we are in the middle of a zoom/pan, we can't do differenced redraws.
        // It would result in artifacts where differenced entities are redrawn with
        // one transform and unchanged entities with another.
        if (resetTransform()) {
            difference = undefined;
        }

        var zoom = String(~~map.zoom());
        if (surface.attr('data-zoom') !== zoom) {
            surface.attr('data-zoom', zoom);
        }

        if (!difference) {
            layers.forEach(function(layer) {
                supersurface.call(layer);
            });
        }

        if (map.editable()) {
            context.connection().loadTiles(projection, dimensions);
            drawVector(difference);
        } else {
            editOff();
        }

        transformStart = [
            projection.scale() * 2 * Math.PI,
            projection.translate().slice()];

        return map;
    }

    var timeoutId;
    function queueRedraw() {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() { redraw(); }, 300);
    }

    function pointLocation(p) {
        var translate = projection.translate(),
            scale = projection.scale() * 2 * Math.PI;
        return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
    }

    function locationPoint(l) {
        var translate = projection.translate(),
            scale = projection.scale() * 2 * Math.PI;
        return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
    }

    map.mouse = function() {
        var e = d3.event, s;
        while (s = e.sourceEvent) e = s;
        return mouse(e);
    };

    map.mouseCoordinates = function() {
        return projection.invert(map.mouse());
    };

    map.dblclickEnable = function(_) {
        if (!arguments.length) return dblclickEnabled;
        dblclickEnabled = _;
        return map;
    };

    function setZoom(z, force) {
        if (z === map.zoom() && !force)
            return false;
        var scale = 256 * Math.pow(2, z),
            center = pxCenter(),
            l = pointLocation(center);
        scale = Math.max(1024, Math.min(256 * Math.pow(2, 24), scale));
        projection.scale(scale / (2 * Math.PI));
        zoom.scale(scale);
        var t = projection.translate();
        l = locationPoint(l);
        t[0] += center[0] - l[0];
        t[1] += center[1] - l[1];
        projection.translate(t);
        zoom.translate(projection.translate());
        return true;
    }

    function setCenter(loc) {
        var t = projection.translate(),
            c = pxCenter(),
            ll = projection(loc);
        if (ll[0] === c[0] && ll[1] === c[1])
            return false;
        projection.translate([
            t[0] - ll[0] + c[0],
            t[1] - ll[1] + c[1]]);
        zoom.translate(projection.translate());
        return true;
    }

    map.pan = function(d) {
        var t = projection.translate();
        t[0] += d[0];
        t[1] += d[1];
        projection.translate(t);
        zoom.translate(projection.translate());
        dispatch.move(map);
        return redraw();
    };

    map.size = function(_) {
        if (!arguments.length) return dimensions;
        var center = map.center();
        dimensions = _;
        surface.size(dimensions);
        layers.forEach(function(layer) {
            layer.size(dimensions);
        });
        projection.clipExtent([[0, 0], dimensions]);
        setCenter(center);
        return redraw();
    };

    map.zoomIn = function() { return map.zoom(Math.ceil(map.zoom() + 1)); };
    map.zoomOut = function() { return map.zoom(Math.floor(map.zoom() - 1)); };

    map.center = function(loc) {
        if (!arguments.length) {
            return projection.invert(pxCenter());
        }

        if (setCenter(loc)) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.zoom = function(z) {
        if (!arguments.length) {
            return Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.LN2 - 8, 0);
        }

        if (setZoom(z)) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.zoomTo = function(entity) {
        var extent = entity.extent(context.graph()),
            zoom = map.extentZoom(extent);
        map.centerZoom(extent.center(), zoom);
    };

    map.centerZoom = function(loc, z) {
        var centered = setCenter(loc),
            zoomed   = setZoom(z);

        if (centered || zoomed) {
            dispatch.move(map);
        }

        return redraw();
    };

    map.centerEase = function(loc) {
        var from = map.center().slice(),
            t = 0,
            stop;

        surface.one('mousedown.ease', function() {
            stop = true;
        });

        d3.timer(function() {
            if (stop) return true;
            map.center(iD.geo.interp(from, loc, (t += 1) / 10));
            return t == 10;
        }, 20);
        return map;
    };

    map.extent = function(_) {
        if (!arguments.length) {
            return new iD.geo.Extent(projection.invert([0, dimensions[1]]),
                                 projection.invert([dimensions[0], 0]));
        } else {
            var extent = iD.geo.Extent(_);
            map.centerZoom(extent.center(), map.extentZoom(extent));
        }
    };

    map.extentZoom = function(_) {
        var extent = iD.geo.Extent(_),
            tl = projection([extent[0][0], extent[1][1]]),
            br = projection([extent[1][0], extent[0][1]]);

        // Calculate maximum zoom that fits extent
        var hFactor = (br[0] - tl[0]) / dimensions[0],
            vFactor = (br[1] - tl[1]) / dimensions[1],
            hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
            vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
            newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);

        return newZoom;
    };

    map.flush = function() {
        context.connection().flush();
        context.history().reset();
        return map;
    };

    var usedTails = {};
    map.tail = function(_) {
        if (!_ || usedTails[_] === undefined) {
            tail.text(_);
            usedTails[_] = true;
        }
        return map;
    };

    map.editable = function() {
        return map.zoom() >= 16;
    };

    map.minzoom = function(_) {
        if (!arguments.length) return minzoom;
        minzoom = _;
        return map;
    };

    map.layers = layers;
    map.projection = projection;
    map.redraw = redraw;

    return d3.rebind(map, dispatch, 'on');
};
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route } from 'react-router-dom'

import '!file-loader?name=[name].[ext]!./favicon.ico';
import '!file-loader?name=[name].[ext]!./manifest.json';

import Home from 'containers/Home';
import NotFound from 'containers/NotFound';

ReactDOM.render((
  <BrowserRouter>
    <Switch>
      <Route exact path='/' component={Home}/>

      <Route path='*' component={NotFound}/>
    </Switch>
  </BrowserRouter>
), document.getElementById('app'));

if (process.env.NODE_ENV === 'production') {
  require('offline-plugin/runtime').install(); // eslint-disable-line global-require
}
<commit_msg>Created container routes<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Switch, Route } from 'react-router-dom'

import '!file-loader?name=[name].[ext]!./favicon.ico';
import '!file-loader?name=[name].[ext]!./manifest.json';

import Home from 'containers/Home';
import NotFound from 'containers/NotFound';
import AddJob from 'containers/AddJob';
import JobDetails from 'containers/JobDetails';
import Jobs from 'containers/Jobs';
import Profile from 'containers/Profile';
import SignUp from 'containers/SignUp';
import Admin from 'container/Admin';

ReactDOM.render((
  <BrowserRouter>
    <Switch>
      <Route exact path='/' component={Home}/>
      <Route path='/AddJob' component={AddJob}/>
      <Route path='/JobDetails' component={JobDetails}/>
      <Route path='/Jobs' component={Jobs}/>
      <Route path='/Profile' component={Profile}/>
      <Route path='/SignUp' component={SignUp}/>
      <Route path='/Admin' component={Admin}/>
      <Route path='*' component={NotFound}/>
    </Switch>
  </BrowserRouter>
), document.getElementById('app'));

if (process.env.NODE_ENV === 'production') {
  require('offline-plugin/runtime').install(); // eslint-disable-line global-require
}
<|endoftext|>


<commit_before>const path = require("path");
const webpackRxjsExternals = require("webpack-rxjs-externals");

module.exports = {
  entry: "./src/index.ts",
  resolve: {
    extensions: [".ts", ".js"],
  },
  output: {
    path: path.join(__dirname, "/dist"),
    filename: "angular-idle-service.js",
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: "awesome-typescript-loader",
      },
    ],
  },

  devtool: "source-map",

  externals: [
    webpackRxjsExternals(),
    "angular"
  ],
};
<commit_msg>Adjust webpack<commit_after>const path = require("path");
const webpackRxjsExternals = require("webpack-rxjs-externals");

module.exports = {
  entry: "./src/index.ts",
  resolve: {
    extensions: [".ts", ".js"],
  },
  output: {
    path: path.join(__dirname, "/dist"),
    filename: "angular-idle-service.js",
    library: "angularIdleService",
    libraryTarget: "umd"
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: "awesome-typescript-loader",
      },
    ],
  },

  devtool: "source-map",

  externals: [
    webpackRxjsExternals(),
    "angular"
  ],
};
<|endoftext|>


<commit_before>var LiveReloadPlugin = require('webpack-livereload-plugin');
var webpack = require('webpack');

module.exports = {
  resolve: {
    extensions: ['', '.scss', '.ts', '.js']
  },

  plugins: [
    new LiveReloadPlugin({
      appendScriptTag: true
    })
  ],

  entry: './src/main.ts',
  output: {
    path: "./dist",
    publicPath: 'dist/',
    filename: "bundle.js"
  },

  devtool: 'source-map',

  module: {
    loaders: [
		{
        test: /\.ts$/,
        loader: 'ts-loader'
      },
	  {
        test: /\.css$/,
        loader: 'style-loader'
      }
    ]
  },

  devServer: {
    historyApiFallback: true
  }
};
<commit_msg>update webpack config to fix the resolution of @angular/upgrade/static<commit_after>var LiveReloadPlugin = require('webpack-livereload-plugin');
var webpack = require('webpack');

module.exports = {
  resolve: {
    extensions: ['', '.scss', '.ts', '.js'],
    alias: {
      "@angular/upgrade/static": "@angular/upgrade/bundles/upgrade-static.umd.js"
    }
  },

  plugins: [
    new LiveReloadPlugin({
      appendScriptTag: true
    })
  ],

  entry: './src/main.ts',
  output: {
    path: "./dist",
    publicPath: 'dist/',
    filename: "bundle.js"
  },

  devtool: 'source-map',

  module: {
    loaders: [
		{
        test: /\.ts$/,
        loader: 'ts-loader'
      },
	  {
        test: /\.css$/,
        loader: 'style-loader'
      }
    ]
  },

  devServer: {
    historyApiFallback: true
  }
};
<|endoftext|>


<commit_before>function ddg_spice_lastfm(lastfm) {
	console.log(lastfm);
	//Search for artists
	if(lastfm.results) {
		var query = DDG.get_query();
		query = query.replace(/\s*(albums?)\s*/, "");
		display(lastfm.results.artistmatches.artist, query, "Artists");
	//Get their top albums
	} else if(lastfm.topalbums && lastfm.topalbums.album.length > 0) {
		display(lastfm.topalbums.album, lastfm.topalbums.album[0].artist.name, "Albums");
	}
}

function display(result, query, thing) {
	var tmp, div, div2, link, img, item, limit, out = '', ddg;

	if(thing === 'Albums') {
		ddg = '/?q=albums+album-';
	} else {
		ddg = '/?q=albums+';
	}
	//Get only the ones with the property mbid
	var tmp = new Array();
	for(var i = 0;i < result.length;i++) {
		if(result[i].mbid) {
			tmp.push(result[i]);
		}
	}
	result = tmp;

	//Get only 5 results.
	if(result.length > 5) {
		limit = 5;
	} else {
		limit = result.length;
	}

	for (var i = 0;i < limit;i++) {
		item = result[i];

	    div = d.createElement("div");
	    div2 = d.createElement("div");

	    link = d.createElement("a");
	    link.href = ddg + item.mbid;

	    if (item.name.length >= 10) {
			item.name = item.name.substring(0,8) + "...";
		}

	    img = d.createElement('img');
	    img.src = item.image[1]['#text'];
	    YAHOO.util.Dom.setStyle(img, "margin", '0 auto 0 auto');
	    YAHOO.util.Dom.setStyle(div,'margin-bottom', '10px');
	    YAHOO.util.Dom.setStyle(div,'text-align', 'center');
	    link.appendChild(img);
	    div.appendChild(link);

	    link = d.createElement('a');
	    link.href = ddg + item.mbid;
	    link.innerHTML = item.name;
	    div.appendChild(link);
	    div.appendChild(d.createElement('br'));

	    YAHOO.util.Dom.addClass(div, 'inline highlight_zero_click1 highlight_zero_click_wrapper');
	    YAHOO.util.Dom.setStyle(div, "float", "left");
	    YAHOO.util.Dom.setStyle(div, "margin", "10px 20px 10px 0px");
	    YAHOO.util.Dom.setStyle(div, "padding", "5px");
	    YAHOO.util.Dom.setStyle(div, "max-width", "80px");

	    div2.appendChild(div);

	    out += div2.innerHTML;
	}

	var items = new Array();
	items[0] = new Array();
	items[0]['a'] = out += '

';
	items[0]['h'] = 'Last.fm ' + thing + ' (' + query + ')';
	items[0]['s'] = 'Last.fm';
	items[0]['f'] = 1;
	items[0]['u'] = 'http://www.last.fm/search?q=' + query + '&type=album';
	nra(items,1,1);
}<commit_msg>Can now show album info<commit_after>function ddg_spice_lastfm(lastfm) {
	console.log(lastfm);
	//Search for artists
	if(lastfm.results) {
		var query = DDG.get_query();
		query = query.replace(/\s*(albums?)\s*/, "");
		display(lastfm.results.artistmatches.artist, query, "Artists");
	//Get their top albums
	} else if(lastfm.topalbums && lastfm.topalbums.album.length > 0) {
		display(lastfm.topalbums.album, lastfm.topalbums.album[0].artist.name, "Albums");
	//Get album info
	} else if(lastfm.album) {
		var songs = '';
		var out = '';
		out += '
Release:' + lastfm.album.releasedate.substring(0,lastfm.album.releasedate.length-7)
			+ '
';
		if(lastfm.album.tracks.track.length > 0) {
			for(var i = 0;i < lastfm.album.tracks.track.length;i++) {
				songs += '' +
					lastfm.album.tracks.track[i].name + '
';
			}
		} else {
			songs += '' +
					lastfm.album.tracks.track.name + '
'
		}
		out += '
Songs:
' + songs + '
';
		var items = new Array();
		items[0] = new Array();
		items[0]['a'] = out;
		items[0]['h'] = lastfm.album.name + ' by ' + lastfm.album.artist;
		items[0]['s'] = 'Last.fm';
		items[0]['i'] = lastfm.album.image[2]['#text'];
		items[0]['f'] = 1;
		items[0]['u'] = lastfm.album.url;
		nra(items);
	}
}

function display(result, query, thing) {
	var tmp, div, div2, link, img, item, limit, out = '', ddg;

	if(thing === 'Albums') {
		ddg = '/?q=albums+album-';
	} else {
		ddg = '/?q=albums+';
	}
	//Get only the ones with the property mbid
	var tmp = new Array();
	for(var i = 0;i < result.length;i++) {
		if(result[i].mbid) {
			tmp.push(result[i]);
		}
	}
	result = tmp;

	//Get only 5 results.
	if(result.length > 5) {
		limit = 5;
	} else {
		limit = result.length;
	}

	for (var i = 0;i < limit;i++) {
		item = result[i];

	    div = d.createElement("div");
	    div2 = d.createElement("div");

	    link = d.createElement("a");
	    link.href = ddg + item.mbid;

	    if (item.name.length >= 10) {
			item.name = item.name.substring(0,8) + "...";
		}

	    img = d.createElement('img');
	    img.src = item.image[1]['#text'];
	    YAHOO.util.Dom.setStyle(img, "margin", '0 auto 0 auto');
	    YAHOO.util.Dom.setStyle(div,'margin-bottom', '10px');
	    YAHOO.util.Dom.setStyle(div,'text-align', 'center');
	    link.appendChild(img);
	    div.appendChild(link);

	    link = d.createElement('a');
	    link.href = ddg + item.mbid;
	    link.innerHTML = item.name;
	    div.appendChild(link);
	    div.appendChild(d.createElement('br'));

	    YAHOO.util.Dom.addClass(div, 'inline highlight_zero_click1 highlight_zero_click_wrapper');
	    YAHOO.util.Dom.setStyle(div, "float", "left");
	    YAHOO.util.Dom.setStyle(div, "margin", "10px 20px 10px 0px");
	    YAHOO.util.Dom.setStyle(div, "padding", "5px");
	    YAHOO.util.Dom.setStyle(div, "max-width", "80px");

	    div2.appendChild(div);

	    out += div2.innerHTML;
	}

	var items = new Array();
	items[0] = new Array();
	items[0]['a'] = out += '

';
	items[0]['h'] = 'Last.fm ' + thing + ' (' + query + ')';
	items[0]['s'] = 'Last.fm';
	items[0]['f'] = 1;
	items[0]['u'] = 'http://www.last.fm/search?q=' + query + '&type=album';
	nra(items,1,1);
}<|endoftext|>


<commit_before>jQuery(document).ready(function () {
    jQuery('.post').addClass("hidden").viewportChecker({
        classToAdd: 'visible animated slideInLeft',
        offset: 100
    });
});<commit_msg>Alteração do efeito de animação para FadeIn<commit_after>jQuery(document).ready(function () {
    jQuery('.post').addClass("hidden").viewportChecker({
        classToAdd: 'visible animated fadeIn',
        offset: 100
    });
});<|endoftext|>


<commit_before>// let fs = require('fs');
let path = require('path');
let poster = require('./poster');
let server = require('./server');
let metadata = require('./metadata');
let configLoader = require('./configLoader');

let config = configLoader.load(path.join(__dirname, '../config.json'));

metadata.getData(
    config.sourceFolder,
    config.api.metadata.url,
    (moviesData) => {
        poster.getPosters(
            moviesData,
            config.api.poster.url,
            config.posterFolder,
            (moviesDataWithPosters) => {
                server.startServer(moviesDataWithPosters, config.port);
            }
        );
    }
);
<commit_msg>basic approach for db cleanup and update<commit_after>let fs = require('fs');
let path = require('path');
let configLoader = require('./configloader');
let config = configLoader.load(path.join(__dirname, '../config.json'));
let TMDbClient = require('./tmdbclient');
let tmdb = new TMDbClient(config.TMDbAPIkey);
let Bottleneck = require('bottleneck');
let limiter = new Bottleneck(0, 500);
let Store = require('./store');
let db = new Store(config.database);

db.getAll()
    .then((records) => {
        extractDataFromFolderNames(config.sourceFolder)
            .then((movies) => {
                db.delete(
                    records.filter((record) => {
                        return !movies.find((movie) => {
                            return record._source.folder === movie.folder;
                        });
                    }).map((record) => {
                        return parseInt(record.id, 10);
                    })
                ).then((res) => {
                    console.log(res);
                    fetchMetadata(
                        movies.filter((movie) => {
                            return !records.find((record) => {
                                return record._source.folder === movie.folder;
                            });
                        })
                    );
                })
                .catch((err) => {
                    console.log(err);
                });
            })
            .catch((err) => {
                console.log(err);
            });
    })
    .catch((err) => {
        console.log(err);
    });

/**
 * @param {Array.<object>} movies Extracted data from folder names
 *
 * @return {Promise} Return a promise with the summary of changes
 */
function fetchMetadata(movies) {
    return new Promise((resolve, reject) => {
        movies.forEach((movie) => {
            limiter.schedule(function(url, params) {
                return tmdb.call(url, params)
                    .then((res) => {
                        if (res.total_results === 0) {
                            resolve('Missing: ', movie, '\n');
                        } else {
                            res.results[0]._source = movie;
                            console.log('Fetched: ' + res.results[0].title);
                            db.insert(res.results[0])
                                .then((res) => {
                                    resolve(res);
                                })
                                .catch((err) => {
                                    reject(err);
                                });
                        }
                    }).catch((err) => {
                        console.log(err);
                    });
            }, '/search/movie', {
                query: movie.title,
                year: movie.year
            });
        });
    });
}

/**
 * @param {string} sourceDir Where the movie folders can be found
 *
 * @return {Promise} Array contains objects of movie data (title/year)
 */
function extractDataFromFolderNames(sourceDir) {
    return new Promise((resolve, reject) => {
        fs.readdir(sourceDir, (err, items) => {
            if (err) {
                reject(new Error(err));
            }
            if (items && items.length) {
                resolve(
                    items
                        .filter((item) => {
                            return fs
                                .statSync(path.join(sourceDir, item))
                                .isDirectory();
                        })
                        .filter((item) => {
                            return item.match(/^(.+)\.(\d{4})\./i) !== null;
                        })
                        .map((item) => {
                            let matched = item.match(/^(.+)\.(\d{4})\./i);
                            return {
                                title: matched[1].replace(/\./g, ' '),
                                year: matched[2],
                                folder: item
                            };
                        })
                );
            } else {
                resolve([]);
            }
        });
    });
}
<|endoftext|>


<commit_before>"use strict";

const webpack = require('webpack');
const replace = require('replace-in-file');
const fs = require('fs');
const path = require('path');
const pkg = require('./package.json');
const Case = require('case');
const name = Case.kebab(pkg.name);
const date = new Date().toISOString().slice(0, 10);
const author = pkg.author.slice(0, pkg.author.indexOf(' <'));
const banner = `${name} ${pkg.version} by ${author} ${date}
${pkg.homepage}
License ${pkg.license}`;

var postBuildTasks = {
  apply: function(compiler) {
    compiler.plugin('after-emit', function(compiler, callback) {
      var matterToolsPath = path.dirname(require.resolve('matter-tools')) + '/build/matter-tools.demo.js';

      // replace constants
      replace.sync({
        files: ['index.js', 'docs/examples/*.js', 'docs/index.html'],
        replace: [
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_NAME)/g,
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_VERSION)/g,
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_REPO_URL)/g
        ],
        with: [
          "$1" + name + "$3",
          "$1" + pkg.version + "$3",
          "$1" + pkg.repository.url.replace('.git', '') + "$3"
        ]
      });

      // copy libs to demo
      copySync(require.resolve('matter-js'), 'docs/libs/matter.js');
      copySync(matterToolsPath, 'docs/libs/matter-tools.demo.js');
      copySync('build/' + name + '.js', 'docs/libs/bundle.js');

      // done
      callback();
    });
  }
};

var copySync = function(src, dest) {
  fs.writeFileSync(dest, fs.readFileSync(src));
  console.info('copied', path.basename(dest));
};

module.exports = {
  entry: {
    [name]: './index.js',
    [name + '.min']: './index.js'
  },
  output: {
    library: Case.pascal(name),
    path: './build',
    publicPath: '/libs',
    filename: '[name].js',
    libraryTarget: 'umd'
  },
  externals: {
    'matter-js': 'Matter'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true
    }),
    new webpack.BannerPlugin(banner),
    postBuildTasks
  ]
};<commit_msg>fix dev server<commit_after>"use strict";

const webpack = require('webpack');
const replace = require('replace-in-file');
const fs = require('fs');
const path = require('path');
const pkg = require('./package.json');
const Case = require('case');
const name = Case.kebab(pkg.name);
const date = new Date().toISOString().slice(0, 10);
const author = pkg.author.slice(0, pkg.author.indexOf(' <'));
const banner = `${name} ${pkg.version} by ${author} ${date}
${pkg.homepage}
License ${pkg.license}`;

var postBuildTasks = {
  apply: function(compiler) {
    compiler.plugin('after-emit', function(compiler, callback) {
      var matterToolsPath = path.dirname(require.resolve('matter-tools')) + '/build/matter-tools.demo.js';

      // replace constants
      replace.sync({
        files: ['index.js', 'docs/examples/*.js', 'docs/index.html'],
        replace: [
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_NAME)/g,
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_VERSION)/g,
          /(['"])(.*)(['"][;,\s]*\/\/\s*PLUGIN_REPO_URL)/g
        ],
        with: [
          "$1" + name + "$3",
          "$1" + pkg.version + "$3",
          "$1" + pkg.repository.url.replace('.git', '') + "$3"
        ]
      });

      // copy libs to demo
      copySync(require.resolve('matter-js'), 'docs/libs/matter.js');
      copySync(matterToolsPath, 'docs/libs/matter-tools.demo.js');
      copySync('build/' + name + '.js', 'docs/libs/bundle.js');

      // done
      callback();
    });
  }
};

var copySync = function(src, dest) {
  fs.writeFileSync(dest, fs.readFileSync(src));
  console.info('copied', path.basename(dest));
};

module.exports = {
  entry: {
    [name]: './index.js',
    [name + '.min']: './index.js'
  },
  output: {
    library: Case.pascal(name),
    path: './build',
    publicPath: '/libs',
    filename: '[name].js',
    libraryTarget: 'umd'
  },
  externals: {
    'matter-js': 'Matter'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      include: /\.min\.js$/,
      minimize: true
    }),
    new webpack.BannerPlugin(banner),
    postBuildTasks
  ],
  devServer: {
    proxy: {
      '/libs/bundle.js': {
        target: 'http://localhost:8080/',
        pathRewrite: { '^/libs/bundle\\.js' : '/libs/' + name + '.js' }
      }
    }
  }
};<|endoftext|>


<commit_before>(function() {
	var exports = app.namespace("app.views.boardControls");

	/**
	 * createInstance returns a new instance of class BoardControls.
	 * @returns object BoardControls
	 */
	exports.createInstance = function() {
		return new BoardControls();
	};

	/**
	 * Class BoardControls manages an anchor element that users click on to load
	 * more images.
	 */
	function BoardControls() {
		var self = this;

		/**
		 * @var HTMLElement
		 */
		var boardControls;

		var loadMoreAnchorTextDefault1 = "Load images";
		var loadMoreAnchorTextDefault2 = "Load more";
		var loadMoreAnchorTextActive = "Loading images…"

		/**
		 * Flag that indicates if at least one image has been loaded.
		 * @var boolean
		 */
		var hasLoadedAnImage = false;

		self.create = function() {
			boardControls = new Element("div", {
				html: loadMoreAnchorTextDefault1,
				id: "board-controls"
			});

			window.addEvent("app.views.board.didCompleteRequest", handleDidLoadMoreImage);

			boardControls.addEvent("click", handleClickEvent);
			return boardControls;
		};

		function handleClickEvent() {
			window.fireEvent("app.views.boardControls.userDidAskForImages");
		};

		function handleDidLoadMoreImage(event) {
			if (!event
					|| typeof(event.runningRequestsCount) !== "number"
					|| isNaN(event.runningRequestsCount)) {
				return;
			}

			if (event.hasLoadedAnImage) {
				hasLoadedAnImage = true;
			}

			if (event.runningRequestsCount > 0) {
				boardControls.set("html", loadMoreAnchorTextActive);
				return;
			}

			if (hasLoadedAnImage) {
				boardControls.set("html", loadMoreAnchorTextDefault2);
				return;
			}

			boardControls.set("html", loadMoreAnchorTextDefault1);
		}
	}
})();
<commit_msg>Changed HTML element for board controls from <div> to <a>.<commit_after>(function() {
	var exports = app.namespace("app.views.boardControls");

	/**
	 * createInstance returns a new instance of class BoardControls.
	 * @returns object BoardControls
	 */
	exports.createInstance = function() {
		return new BoardControls();
	};

	/**
	 * Class BoardControls manages an anchor element that users click on to load
	 * more images.
	 */
	function BoardControls() {
		var self = this;

		/**
		 * @var HTMLElement
		 */
		var boardControls;

		var loadMoreAnchorTextDefault1 = "Load images";
		var loadMoreAnchorTextDefault2 = "Load more";
		var loadMoreAnchorTextActive = "Loading images…"

		/**
		 * Flag that indicates if at least one image has been loaded.
		 * @var boolean
		 */
		var hasLoadedAnImage = false;

		self.create = function() {
			boardControls = new Element("a", {
				html: loadMoreAnchorTextDefault1,
				id: "board-controls"
			});

			window.addEvent("app.views.board.didCompleteRequest", handleDidLoadMoreImage);

			boardControls.addEvent("click", handleClickEvent);
			return boardControls;
		};

		function handleClickEvent() {
			window.fireEvent("app.views.boardControls.userDidAskForImages");
		};

		function handleDidLoadMoreImage(event) {
			if (!event
					|| typeof(event.runningRequestsCount) !== "number"
					|| isNaN(event.runningRequestsCount)) {
				return;
			}

			if (event.hasLoadedAnImage) {
				hasLoadedAnImage = true;
			}

			if (event.runningRequestsCount > 0) {
				boardControls.set("html", loadMoreAnchorTextActive);
				return;
			}

			if (hasLoadedAnImage) {
				boardControls.set("html", loadMoreAnchorTextDefault2);
				return;
			}

			boardControls.set("html", loadMoreAnchorTextDefault1);
		}
	}
})();
<|endoftext|>


<commit_before>DataTest = TestCase("DataTest");

DataTest.prototype.testCase = function(){
	data.set("test", "test")
	assert(data.get("test") === "test");
}
<commit_msg>Remove unused js-test folder<commit_after><|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');

const IS_DEV = process.env.NODE_ENV === 'dev';

let mode = IS_DEV ? 'development' : 'production';

console.log('Running Webpack in "' + mode + '" mode.');

const config = {
  mode: mode,
  devtool: IS_DEV ? 'eval' : 'source-map',
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[hash].js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.ejs$/,
        use: [
          {
            loader: 'ejs-webpack-loader',
            options: {
              htmlmin: true,
              emitFile: true
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          IS_DEV ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|woff|woff2|eot|ttf)$/,
        loader: 'url-loader?limit=100000'
      {
        test: /\.(gif|png|jpe?g|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'public/[name].[ext]?[hash:7]'
            }
          },
          {
            loader: 'image-webpack-loader',
            options: {
              bypassOnDebug: true,
              mozjpeg: {
                progressive: true,
                quality: 75
              }
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'windows.jQuery': 'jquery'
    }),
    new CopyWebpackPlugin([
      {
        from: './public',
        to: 'public'
      },
      {
        from: './sw.js',
        to: 'sw.js'
      }
    ]),
    new HtmlWebPackPlugin({
      hash: true,
      template: path.join(__dirname, 'src/work.ejs'),
      title: 'Commercials by Marc Flennert',
      filename: 'index.html',
      favicon: './public/icon.ico',
      minify: !IS_DEV && {
        collapseWhitespace: true,
        preserveLineBreaks: false,
        removeComments: true
      },
      meta: {
        description: 'Commercials by Marc Flennert',
        viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
      }
    }),
    new HtmlWebPackPlugin({
      hash: true,
      template: path.join(__dirname, 'src/about.ejs'),
      title: 'About Marc Flennert',
      filename: 'about.html',
      favicon: './public/icon.ico',
      minify: !IS_DEV && {
        collapseWhitespace: true,
        preserveLineBreaks: false,
        removeComments: true
      },
      meta: {
        description: 'About Marc Flennert',
        viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
      }
    }),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: IS_DEV ? 'css/[name].css' : 'css/[name].[contenthash].css',
      chunkFilename: IS_DEV ? 'css/[id].css' : 'css/[id].[hash].css'
    }),
    new ManifestPlugin(),
    new ServiceWorkerWebpackPlugin({
      entry: path.join(__dirname, 'sw.js')
    }),
    new webpack.HashedModuleIdsPlugin()
  ],
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /node_modules/,
          chunks: 'initial',
          name: 'vendor',
          priority: 10,
          enforce: true
        }
      }
    },
    minimizer: []
  }
};

if (!IS_DEV) {
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

  config.optimization.minimizer.push(
    new UglifyJsPlugin({
      sourceMap: false
    }),
    new OptimizeCSSAssetsPlugin({})
  );
}

module.exports = config;
<commit_msg>Add font handler plugin.<commit_after>const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');

const IS_DEV = process.env.NODE_ENV === 'dev';

let mode = IS_DEV ? 'development' : 'production';

console.log('Running Webpack in "' + mode + '" mode.');

const config = {
  mode: mode,
  devtool: IS_DEV ? 'eval' : 'source-map',
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[hash].js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.ejs$/,
        use: [
          {
            loader: 'ejs-webpack-loader',
            options: {
              htmlmin: true,
              emitFile: true
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          IS_DEV ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(gif|png|jpe?g|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'public/[name].[ext]?[hash:7]'
            }
          },
          {
            loader: 'image-webpack-loader',
            options: {
              bypassOnDebug: true,
              mozjpeg: {
                progressive: true,
                quality: 75
              }
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      'windows.jQuery': 'jquery'
    }),
    new CopyWebpackPlugin([
      {
        from: './public',
        to: 'public'
      },
      {
        from: './sw.js',
        to: 'sw.js'
      }
    ]),
    new HtmlWebPackPlugin({
      hash: true,
      template: path.join(__dirname, 'src/work.ejs'),
      title: 'Commercials by Marc Flennert',
      filename: 'index.html',
      favicon: './public/icon.ico',
      minify: !IS_DEV && {
        collapseWhitespace: true,
        preserveLineBreaks: false,
        removeComments: true
      },
      meta: {
        description: 'Commercials by Marc Flennert',
        viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
      }
    }),
    new HtmlWebPackPlugin({
      hash: true,
      template: path.join(__dirname, 'src/about.ejs'),
      title: 'About Marc Flennert',
      filename: 'about.html',
      favicon: './public/icon.ico',
      minify: !IS_DEV && {
        collapseWhitespace: true,
        preserveLineBreaks: false,
        removeComments: true
      },
      meta: {
        description: 'About Marc Flennert',
        viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
      }
    }),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: IS_DEV ? 'css/[name].css' : 'css/[name].[contenthash].css',
      chunkFilename: IS_DEV ? 'css/[id].css' : 'css/[id].[hash].css'
    }),
    new ManifestPlugin(),
    new ServiceWorkerWebpackPlugin({
      entry: path.join(__dirname, 'sw.js')
    }),
    new webpack.HashedModuleIdsPlugin()
  ],
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /node_modules/,
          chunks: 'initial',
          name: 'vendor',
          priority: 10,
          enforce: true
        }
      }
    },
    minimizer: []
  }
};

if (!IS_DEV) {
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

  config.optimization.minimizer.push(
    new UglifyJsPlugin({
      sourceMap: false
    }),
    new OptimizeCSSAssetsPlugin({})
  );
}

module.exports = config;
<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on views, and components
var app = angular.module('myApp', [
  'ngRoute',
  'ngCookies',
  'myApp.list',
  'myApp.new',
  'ui.select',
  'angucomplete-alt',
  'pascalprecht.translate',
  'myApp.change'
]);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/list'});
}]);

app.config(['$translateProvider', function ($translateProvider) {
  $translateProvider.translations('fi', {
    'TITLE': 'Ehdotusjärjestelmä',
    'NEWSUGGESTION': 'Ehdota uutta käsitettä',
    'NEWHEADING': 'Ehdota uutta käsitettä YSAan ja YSOon',
    'CHANGEHEADING': 'Ehdota muutosta olemassa olevaan käsitteeseen YSAssa ja YSOssa',
    'CHANGESUGGESTION': 'Ehdota muutosta olemassa olevaan käsitteeseen',
    'SUGGESTIONS': 'Ehdotukset',
    'LIST': 'Uusimmat ehdotukset',
    'NOTINYSA': 'Asiasanaa ei löytynyt YSAsta.',
    'INYSA': 'Ehdottamasi termi löytyy jo YSAsta.',
    'PREFLABEL': 'Päätermi/asiasana',
    'ALTLABEL': 'Vaihtoehtoiset termit ja ilmaisut',
    'NARROWER': 'Alakäsitteet (ST)',
    'BROADER': 'Yläkäsite YSOssa (LT)',
    'SEARCH': 'Hae käsitettä',
    'RELATED': 'Assosiatiiviset (RT)',
    'GROUP': 'YSA/YSO temaattinen ryhmä',
    'MATCHING': 'Vastaava käsite muussa sanastossa',
    'SCOPENOTE': 'Tarkoitusta täsmentävä selite',
    'EXPLANATION': 'Perustelut ehdotukselle',
    'NEEDEDFOR': 'Minkä aineiston kuvailussa tarvitsisit käsitettä? (esim. nimeke tai URL)',
    'NAME': 'Ehdottajan nimi',
    'ORG': 'Ehdottajan organisaatio',
    'EMAIL': 'Sähköpostiosoite',
    'EMAILINFO' : 'Saat sähköpostiisi tietoa käsittelyn etenemisestä',
    'QUALITY' : 'Ehdotuksen laatu',
    'REQUIRED' : 'merkityt kohdat ovat pakollisia',
    'SUBMIT': 'Lähetä ehdotus',
    'CHANGE': 'Ehdotettu muutos',
    'TYPE': 'Tyyppi',
    'CONCEPT': 'Käsite',
    'STATE': 'Tila',
    'DATE': 'Päivämäärä',
    'COMMENTS': 'Kommentit',
    'PREFFI': 'Päätermi/asiasana',
    'PREFSV': 'Termi ruotsiksi',
    'PREFEN': 'Termi englanniksi',
    'CHOOSEGROUP': 'Valitse ryhmä(t) listalta',
  });

  $translateProvider.translations('sv', {
    'TITLE': 'Förslagssystem',
    'NEWSUGGESTION': 'Ehdota uutta käsitettä',
    'NEWHEADING': 'Ehdota uutta käsitettä YSAan ja YSOon',
    'CHANGEHEADING': 'Ehdota muutosta olemassa olevaan käsitteeseen YSAssa ja YSOssa',
    'CHANGESUGGESTION': 'Ehdota muutosta olemassa olevaan käsitteeseen',
    'SUGGESTIONS': 'Förslag',
    'LIST': 'Nyaste förslag',
    'NOTINYSA': 'Asiasanaa ei löytynyt YSAsta.',
    'INYSA': 'Ehdottamasi termi löytyy jo YSAsta.',
    'PREFLABEL': 'Term/ämnesord',
    'ALTLABEL': 'Alternativa termer och uttryck',
    'NARROWER': 'Underordnade begrepp',
    'BROADER': 'Överordnat begrepp i ALLFO',
    'SEARCH': 'Sök begrepp',
    'RELATED': 'Associativa (RT)',
    'GROUP': 'Tematisk grupp i Allärs/ALLFO',
    'MATCHING': 'Motsvarande begrepp i annan terminologi',
    'SCOPENOTE': 'Förklaring som preciserar betydelsen',
    'EXPLANATION': 'Motiveringar för förslaget',
    'NEEDEDFOR': 'I beskrivningen av vilket material behöver du begreppet (t.ex. titel eller URL)',
    'NAME': 'Förslagsställarens namn',
    'ORG': 'Förslagsställarens organisation',
    'EMAIL': 'E-postadress',
    'EMAILINFO' : 'Du får information om hur behandlingen av förslaget framskrider till din e-post',
    'QUALITY' : 'Förslagets kvalitet',
    'REQUIRED' : 'obligatorisk information',
    'SUBMIT': 'Skicka förslaget',
    'CHANGE': 'Ehdotettu muutos',
    'TYPE': 'Typ',
    'CONCEPT': 'Begrepp',
    'STATE': 'Status',
    'DATE': 'Datum',
    'COMMENTS': 'Kommentarer',
    'PREFFI': 'Term/ämnesord på finska',
    'PREFSV': 'Term/ämnesord på svenska',
    'PREFEN': 'Term/ämnesord på engelska',
    'CHOOSEGROUP': 'Välj grupp(er) ur listan',
  });

  $translateProvider.preferredLanguage('fi');
  $translateProvider.useSanitizeValueStrategy('escape');
  $translateProvider.useCookieStorage();
}]);

app.controller('Ctrl', ['$translate', '$scope', function ($translate, $scope) {
  $scope.changeLanguage = function (langKey) {
    $translate.use(langKey);
    $scope.language = langKey;
  };

  $scope.language = $translate.use();
}]);

app.directive('existingConcept', function($http) {
  var toId;
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
      //when the scope changes, check the email.
      scope.$watch(attr.ngModel, function(value) {
        // if there was a previous attempt, stop it.
        if (!value)
          return false;
        if(toId) clearTimeout(toId);

        // start a new attempt with a delay to keep it from
        // getting too "chatty".
        toId = setTimeout(function(){
          var vocab = (attr.inVocab) ? attr.inVocab : 'ysa';
          $http.get('http://api.finto.fi/rest/v1/' + attr.inVocab + '/lookup?label=' + value).then(function(data) {
            //set the validity of the field
            ctrl.$setValidity('existingConcept', true);
          }, function() {
            ctrl.$setValidity('existingConcept', false);
          });
        }, 500);
      });
    }
  };
});

app.directive('newConcept', function($http) {
  var toId;
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
      //when the scope changes, check the email.
      scope.$watch(attr.ngModel, function(value) {
        // if there was a previous attempt, stop it.
        if (!value)
          return false;
        if(toId) clearTimeout(toId);

        // start a new attempt with a delay to keep it from
        // getting too "chatty".
        toId = setTimeout(function(){
          var vocab = (attr.inVocab) ? attr.inVocab : 'ysa';
          $http.get('http://api.finto.fi/rest/v1/' + vocab + '/lookup?label=' + value).then(function(data) {
            ctrl.$setValidity('newConcept', false); // set to false if the term can already be found
          }, function() {
            ctrl.$setValidity('newConcept', true);
          });
        }, 500);
      });
    }
  };
});

app.factory('FormFormatter', [function() {
  return {
    markdown: function(suggestion) {
      var msg_body = '';
      var labels = {'type': 'Ehdotuksen tyyppi', 'preflabelfi': 'Ehdotettu termi suomeksi', 'preflabelsv': 'Ehdotettu termi ruotsiksi', 'preflabelen': 'Ehdotettu termi englanniksi', 'state': 'Tila', 'change':'Ehdotettu muutos', 'scopenote': 'Tarkoitusta täsmentävä selite', 'explanation': 'Perustelut ehdotukselle', 'broader': 'Ehdotettu yläkäsite YSOssa (LT)', 'groups': 'Ehdotetut temaattiset ryhmät (YSA-ryhmät)','name': 'Ehdottajan nimi', 'email': 'Ehdottajan sähköpostiosoite', 'altlabel': 'Vaihtoehtoiset termit ja ilmaisut', 'narrower': 'Alakäsitteet (RT)', 'related': 'Assosiatiiviset (ST)'};

      for (var property in suggestion) {
        var proplabel = labels[property] ? labels[property] : property;
        var propval = suggestion[property];
        var groups = '';
        if (Object.prototype.toString.call(propval) === '[object Array]') {
          for (var i in propval) {
            groups += '[' + propval[i].prefLabel + '](' + propval[i].uri + ')  \n\n';
          }
          msg_body += '#### ' + proplabel + '   \n\n' + groups;
        } else if (propval.originalObject) // if there is an uri available from the autocomplete linking to that
  msg_body += '#### ' + proplabel + '   \n\n' + '[' + propval.originalObject.prefLabel + '](' + propval.originalObject.uri + ')  \n\n';
        else if (propval !== '')// the property value is only a string
  msg_body += '#### ' + proplabel + '   \n\n' + propval + '  \n\n';
      }
      return msg_body;
    }
  };
}]);
<commit_msg>adding pretty labels for markdown of the from fields<commit_after>'use strict';

// Declare app level module which depends on views, and components
var app = angular.module('myApp', [
  'ngRoute',
  'ngCookies',
  'myApp.list',
  'myApp.new',
  'ui.select',
  'angucomplete-alt',
  'pascalprecht.translate',
  'myApp.change'
]);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/list'});
}]);

app.config(['$translateProvider', function ($translateProvider) {
  $translateProvider.translations('fi', {
    'TITLE': 'Ehdotusjärjestelmä',
    'NEWSUGGESTION': 'Ehdota uutta käsitettä',
    'NEWHEADING': 'Ehdota uutta käsitettä YSAan ja YSOon',
    'CHANGEHEADING': 'Ehdota muutosta olemassa olevaan käsitteeseen YSAssa ja YSOssa',
    'CHANGESUGGESTION': 'Ehdota muutosta olemassa olevaan käsitteeseen',
    'SUGGESTIONS': 'Ehdotukset',
    'LIST': 'Uusimmat ehdotukset',
    'NOTINYSA': 'Asiasanaa ei löytynyt YSAsta.',
    'INYSA': 'Ehdottamasi termi löytyy jo YSAsta.',
    'PREFLABEL': 'Päätermi/asiasana',
    'ALTLABEL': 'Vaihtoehtoiset termit ja ilmaisut',
    'NARROWER': 'Alakäsitteet (ST)',
    'BROADER': 'Yläkäsite YSOssa (LT)',
    'SEARCH': 'Hae käsitettä',
    'RELATED': 'Assosiatiiviset (RT)',
    'GROUP': 'YSA/YSO temaattinen ryhmä',
    'MATCHING': 'Vastaava käsite muussa sanastossa',
    'SCOPENOTE': 'Tarkoitusta täsmentävä selite',
    'EXPLANATION': 'Perustelut ehdotukselle',
    'NEEDEDFOR': 'Minkä aineiston kuvailussa tarvitsisit käsitettä? (esim. nimeke tai URL)',
    'NAME': 'Ehdottajan nimi',
    'ORG': 'Ehdottajan organisaatio',
    'EMAIL': 'Sähköpostiosoite',
    'EMAILINFO' : 'Saat sähköpostiisi tietoa käsittelyn etenemisestä',
    'QUALITY' : 'Ehdotuksen laatu',
    'REQUIRED' : 'merkityt kohdat ovat pakollisia',
    'SUBMIT': 'Lähetä ehdotus',
    'CHANGE': 'Ehdotettu muutos',
    'TYPE': 'Tyyppi',
    'CONCEPT': 'Käsite',
    'STATE': 'Tila',
    'DATE': 'Päivämäärä',
    'COMMENTS': 'Kommentit',
    'PREFFI': 'Päätermi/asiasana',
    'PREFSV': 'Termi ruotsiksi',
    'PREFEN': 'Termi englanniksi',
    'CHOOSEGROUP': 'Valitse ryhmä(t) listalta',
  });

  $translateProvider.translations('sv', {
    'TITLE': 'Förslagssystem',
    'NEWSUGGESTION': 'Ehdota uutta käsitettä',
    'NEWHEADING': 'Ehdota uutta käsitettä YSAan ja YSOon',
    'CHANGEHEADING': 'Ehdota muutosta olemassa olevaan käsitteeseen YSAssa ja YSOssa',
    'CHANGESUGGESTION': 'Ehdota muutosta olemassa olevaan käsitteeseen',
    'SUGGESTIONS': 'Förslag',
    'LIST': 'Nyaste förslag',
    'NOTINYSA': 'Asiasanaa ei löytynyt YSAsta.',
    'INYSA': 'Ehdottamasi termi löytyy jo YSAsta.',
    'PREFLABEL': 'Term/ämnesord',
    'ALTLABEL': 'Alternativa termer och uttryck',
    'NARROWER': 'Underordnade begrepp',
    'BROADER': 'Överordnat begrepp i ALLFO',
    'SEARCH': 'Sök begrepp',
    'RELATED': 'Associativa (RT)',
    'GROUP': 'Tematisk grupp i Allärs/ALLFO',
    'MATCHING': 'Motsvarande begrepp i annan terminologi',
    'SCOPENOTE': 'Förklaring som preciserar betydelsen',
    'EXPLANATION': 'Motiveringar för förslaget',
    'NEEDEDFOR': 'I beskrivningen av vilket material behöver du begreppet (t.ex. titel eller URL)',
    'NAME': 'Förslagsställarens namn',
    'ORG': 'Förslagsställarens organisation',
    'EMAIL': 'E-postadress',
    'EMAILINFO' : 'Du får information om hur behandlingen av förslaget framskrider till din e-post',
    'QUALITY' : 'Förslagets kvalitet',
    'REQUIRED' : 'obligatorisk information',
    'SUBMIT': 'Skicka förslaget',
    'CHANGE': 'Ehdotettu muutos',
    'TYPE': 'Typ',
    'CONCEPT': 'Begrepp',
    'STATE': 'Status',
    'DATE': 'Datum',
    'COMMENTS': 'Kommentarer',
    'PREFFI': 'Term/ämnesord på finska',
    'PREFSV': 'Term/ämnesord på svenska',
    'PREFEN': 'Term/ämnesord på engelska',
    'CHOOSEGROUP': 'Välj grupp(er) ur listan',
  });

  $translateProvider.preferredLanguage('fi');
  $translateProvider.useSanitizeValueStrategy('escape');
  $translateProvider.useCookieStorage();
}]);

app.controller('Ctrl', ['$translate', '$scope', function ($translate, $scope) {
  $scope.changeLanguage = function (langKey) {
    $translate.use(langKey);
    $scope.language = langKey;
  };

  $scope.language = $translate.use();
}]);

app.directive('existingConcept', function($http) {
  var toId;
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
      //when the scope changes, check the email.
      scope.$watch(attr.ngModel, function(value) {
        // if there was a previous attempt, stop it.
        if (!value)
          return false;
        if(toId) clearTimeout(toId);

        // start a new attempt with a delay to keep it from
        // getting too "chatty".
        toId = setTimeout(function(){
          var vocab = (attr.inVocab) ? attr.inVocab : 'ysa';
          $http.get('http://api.finto.fi/rest/v1/' + attr.inVocab + '/lookup?label=' + value).then(function(data) {
            //set the validity of the field
            ctrl.$setValidity('existingConcept', true);
          }, function() {
            ctrl.$setValidity('existingConcept', false);
          });
        }, 500);
      });
    }
  };
});

app.directive('newConcept', function($http) {
  var toId;
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attr, ctrl) {
      //when the scope changes, check the email.
      scope.$watch(attr.ngModel, function(value) {
        // if there was a previous attempt, stop it.
        if (!value)
          return false;
        if(toId) clearTimeout(toId);

        // start a new attempt with a delay to keep it from
        // getting too "chatty".
        toId = setTimeout(function(){
          var vocab = (attr.inVocab) ? attr.inVocab : 'ysa';
          $http.get('http://api.finto.fi/rest/v1/' + vocab + '/lookup?label=' + value).then(function(data) {
            ctrl.$setValidity('newConcept', false); // set to false if the term can already be found
          }, function() {
            ctrl.$setValidity('newConcept', true);
          });
        }, 500);
      });
    }
  };
});

app.factory('FormFormatter', [function() {
  return {
    markdown: function(suggestion) {
      var msg_body = '';
      var labels = {'type': 'Ehdotuksen tyyppi', 'preflabelfi': 'Ehdotettu termi suomeksi', 'preflabelsv': 'Ehdotettu termi ruotsiksi', 'preflabelen': 'Ehdotettu termi englanniksi', 'state': 'Tila', 'change':'Ehdotettu muutos', 'scopenote': 'Tarkoitusta täsmentävä selite', 'explanation': 'Perustelut ehdotukselle', 'broader': 'Ehdotettu yläkäsite YSOssa (LT)', 'groups': 'Ehdotetut temaattiset ryhmät (YSA-ryhmät)','name': 'Ehdottajan nimi', 'email': 'Ehdottajan sähköpostiosoite', 'altlabel': 'Vaihtoehtoiset termit ja ilmaisut', 'narrower': 'Alakäsitteet (RT)', 'related': 'Assosiatiiviset (ST)', 'fromname': 'Ehdottajan nimi', 'fromorg': 'Ehdottajan organisaatio', 'fromemail': 'Ehdottajan sähköpostiosoite'};

      for (var property in suggestion) {
        var proplabel = labels[property] ? labels[property] : property;
        var propval = suggestion[property];
        var groups = '';
        if (Object.prototype.toString.call(propval) === '[object Array]') {
          for (var i in propval) {
            groups += '[' + propval[i].prefLabel + '](' + propval[i].uri + ')  \n\n';
          }
          msg_body += '#### ' + proplabel + '   \n\n' + groups;
        } else if (propval.originalObject) // if there is an uri available from the autocomplete linking to that
  msg_body += '#### ' + proplabel + '   \n\n' + '[' + propval.originalObject.prefLabel + '](' + propval.originalObject.uri + ')  \n\n';
        else if (propval !== '')// the property value is only a string
  msg_body += '#### ' + proplabel + '   \n\n' + propval + '  \n\n';
      }
      return msg_body;
    }
  };
}]);
<|endoftext|>