﻿<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>data8 duplicare™ Global Search Configuration</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <style type="text/css">
        html, body {
            font-family: Segoe UI, Tahoma, Arial;
            font-size: 12px;
            cursor: default;
            color: #444;
        }

        input, select {
            font-family: Segoe UI, Tahoma, Arial;
            font-size: 12px;
            color: #444;
        }

        h2 {
            color: black;
            font-size: 21px;
            font-weight: bold;
        }

        h3 {
            color: #1160b7;
            font-size: 15px;
            font-weight: normal;
        }

        .mappingRow {
            padding-top: 10px; 
            border-top: 1px solid; 
            border-color: #ccc;
        }

        .resultsRow {
            padding-top: 10px;
            border-top: 1px solid;
            border-color: #ccc;
        }

        .row-odd {

        }

        .row-even {
            background-color: #eee;
        }

        .row-new {
            background-color: #FFB5B5;
        }

    </style>
</head>
<body>    
    <div id="form" class="container-fluid">
        <h2>data<span style="color: #FF7C22">8</span> duplicare&trade; Global Search Configuration</h2>
        <div id="loading" align="center">
            <img src="/_imgs/AdvFind/progress.gif" /><br />
            Loading...
        </div>
        <div id="navRow" class="row waitForLoad" style="display: none;">
            <div class="btn-group"><a href="data8_DuplicateDetectionPlusConfiguration" class="btn btn-primary" style="margin-left: 15px;"> << Back to home</a></div>
            <button id="save" type="button" class="btn btn-primary save-row" style="margin-left: 15px;" onclick="SaveForm()">Save Changes</button>
        </div>
        <h2 class="waitForLoad" style="display: none;">Search Mappings</h2>
        <div id="titleRow" class="row waitForLoad" style="display: none;">           
            <div class="col-sm-3">
                <h3>Display Name</h3>
            </div>
            <div class="col-sm-3">
                <h3>Display Type</h3>
            </div>
            <div class="col-sm-6">
                <h3>Maps To</h3>
            </div>
        </div>
    </div>

    <div id="form_results" class="container-fluid waitForLoad" style="display: none;">
        <h2>Result Columns</h2>
        <div id="titleRow" class="row">
            <div class="col-sm-3">
                <h3>Display Name</h3>
            </div>
            <div class="col-sm-3">
                <h3>Entity Name</h3>
            </div>
            <div class="col-sm-6">
                <h3>Attribute Name</h3>
            </div>
        </div>        
    </div>

    <script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
    <script src="https://use.fontawesome.com/f00756e2fe.js"></script>
    <script type="text/javascript">

        var orgUrl = Xrm.Page.context.getClientUrl();
        var oDataEndpoint = orgUrl + "/api/data/v8.0/";

        var formFormat;
        var possibleFieldMappings;
        var resultsColumns;
        var globalId;

        $(document).ready(function () {
            var actionData = {};
            actionData.ConfigForm = true;

            $.ajax(oDataEndpoint + "data8_InitializeGlobalSearch",
                {
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    data: JSON.stringify(actionData),
                    success: function (result) {
                        var formattedJson = JSON.parse(result.JsonResponse);
                        globalId = formattedJson.GlobalId;
                        formFormat = formattedJson.GlobalSearchMappings;
                        possibleFieldMappings = formattedJson.UnmappedFields;
                        resultsColumns = formattedJson.ResultsColumns;

                        $(".waitForLoad").show();
                        $("#loading").hide();
                        RenderConfig(formFormat);

                        RenderResultColumns(resultsColumns);
                    }
                });
        });

        function RemoveThisMapping(e) {
            var mappingDiv = $(e).parent().parent();
            var entityMapSelect = mappingDiv.find('.field-mapping-entity');
            var mappedEntity = entityMapSelect.children("option:selected").val();

            var attrMapSelect = mappingDiv.find('.field-mapping-attr');
            var mappedAttr = attrMapSelect.children("option:selected").val();

            var fieldDiv = mappingDiv.parent().parent().parent();
            var fieldMapSelect = fieldDiv.find('.field-mapping-label');
            var fieldMapped = fieldMapSelect.val();

            RemoveFieldMapping(fieldMapped, mappedEntity, mappedAttr);
        }

        function AddMapping(e) {
            if (possibleFieldMappings.length === 0) {
                alert("All fields used in Dedupe+ rules are currently mapped");
            } else {
                var mappingListDiv = $(e).parent().parent();

                var htmlRow = '<div class="row" style="margin-bottom: 10px;">';
                htmlRow = htmlRow + '<div class="form-group">';
                htmlRow = htmlRow + '<div class="col-sm-4">';
                htmlRow = htmlRow +
                    '<select class="form-control field-mapping-entity" onchange="UpdateFieldMappings(this)">';
                var i;
                for (i = 0; i < possibleFieldMappings.length; i++) {
                    htmlRow = htmlRow + '<option>' + possibleFieldMappings[i].EntityName + '</option>';
                }
                htmlRow = htmlRow + '</select>';
                htmlRow = htmlRow + '</div>';
                htmlRow = htmlRow + '<div class="col-sm-4">';
                htmlRow = htmlRow + '<select class="form-control field-mapping-attr">';
                var topRow = possibleFieldMappings[0];
                for (i = 0; i < topRow.AttributeNames.length; i++) {
                    htmlRow = htmlRow + '<option>' + topRow.AttributeNames[i] + '</option>';
                }
                htmlRow = htmlRow + '</select>';
                htmlRow = htmlRow + '</div>';
                htmlRow = htmlRow + '<div class="col-sm-4">';
                htmlRow = htmlRow + '<button type="button" class="btn btn-primary" onclick="SaveNewMapping(this)">Save</button>';
                htmlRow = htmlRow + '<button type="button" class="btn btn-primary" onclick="CancelNewMapping(this)" style="margin-left:15px;">Cancel</button>';
                htmlRow = htmlRow + '</div>';
                htmlRow = htmlRow + '</div>';
                htmlRow = htmlRow + '</div>';

                mappingListDiv.append(htmlRow);
                $(e).parent().hide();
            }
        }

        function UpdateFieldMappings(e) {
            var possibleFields = [];
            var i;
            for (i = 0; i < possibleFieldMappings.length; i++) {
                if (possibleFieldMappings[i].EntityName === $(e).val()) {
                    possibleFields = possibleFieldMappings[i].AttributeNames;
                }
            }

            var parentDiv = $(e).parent().parent();
            var attrMapSelect = parentDiv.find('.field-mapping-attr');
            attrMapSelect.empty();

            for (i = 0; i < possibleFields.length; i++) {
                attrMapSelect.append('<option>' + possibleFields[i] + '</option>');
            }
        }

        function RemoveFieldMapping(mappingVal, entityVal, attrVal) {
            var i;
            for (i = 0; i < formFormat.length; i++) {
                var formField = formFormat[i];
                if (formField.Label === mappingVal) {
                    for (var mapping in formField.MapsTo) {
                        if (formField.MapsTo.hasOwnProperty(mapping)) {
                            var data = formField.MapsTo[mapping];
                            if (data.length === 1 && Object.keys(formField.MapsTo).length === 1) {
                                formFormat.splice(i, 1);
                            } else {
                                if (data.length === 1) {
                                    delete formField.MapsTo[entityVal];
                                } else {
                                    var j;
                                    for (j = 0; j < data.length; j++) {
                                        if (mapping === entityVal && data[j] === attrVal) {
                                            data.splice(j, 1);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            var matchFound = false;
            for (i = 0; i < possibleFieldMappings.length; i++) {
                if (possibleFieldMappings[i].EntityName === entityVal) {
                    matchFound = true;
                    possibleFieldMappings[i].AttributeNames.push(attrVal);
                }
            }

            if (!matchFound) {
                var newMapping = {
                    "EntityName": entityVal,
                    "AttributeNames": [attrVal]
                }
                possibleFieldMappings.push(newMapping);
            }

            RenderConfig(formFormat);
        }

        function SaveNewMapping(e) {
            var parentDiv = $(e).parent().parent();
            var entityMapSelect = parentDiv.find('.field-mapping-entity');
            var mappedEntity = entityMapSelect.children("option:selected").val();

            var attrMapSelect = parentDiv.find('.field-mapping-attr');
            var mappedAttr = attrMapSelect.children("option:selected").val();

            var fieldDiv = parentDiv.parent().parent().parent();
            var fieldMapSelect = fieldDiv.find('.field-mapping-label');

            SaveMapping(fieldMapSelect.val(), mappedEntity, mappedAttr);
        }

        function CancelNewMapping(e) {
            RenderConfig(formFormat);
        }

        function SaveMapping(mappingVal, entityVal, attrVal) {
            if (mappingVal === "") {
                alert("Please enter a valid field name");
                return;
            }

            var i;
            var existingField = false;
            if (formFormat === null) {
                formFormat = [];
            };

            for (i = 0; i < formFormat.length; i++) {
                var formField = formFormat[i];
                if (formField.Label === mappingVal) {
                    existingField = true;
                    var matchFound = false;
                    for (var mapping in formField.MapsTo) {
                        if (formField.MapsTo.hasOwnProperty(mapping) && mapping === entityVal) {
                            matchFound = true;
                            formField.MapsTo[mapping].push(attrVal);
                        }
                    }
                    if (!matchFound) {
                        formField.MapsTo[entityVal] = [attrVal];

                    }
                }
            }

            if (!existingField) {
                var newFormat = {};
                newFormat.Name = guidGenerator();
                newFormat.Label = mappingVal;
                newFormat.Type = "text";
                newFormat.MapsTo = {};
                newFormat.MapsTo[entityVal] = [attrVal];

                formFormat.push(newFormat);
            }

            var availableMappings = [];
            for (i = 0; i < possibleFieldMappings.length; i++) {
                if (possibleFieldMappings[i].EntityName === entityVal) {
                    var j;
                    var availableAttrs = [];
                    for (j = 0; j < possibleFieldMappings[i].AttributeNames.length; j++) {
                        if (possibleFieldMappings[i].AttributeNames[j] !== attrVal) {
                            availableAttrs.push(possibleFieldMappings[i].AttributeNames[j]);
                        }
                    }

                    if (availableAttrs.length > 0) {
                        possibleFieldMappings[i].AttributeNames = availableAttrs;
                        availableMappings.push(possibleFieldMappings[i]);
                    }
                } else {
                    availableMappings.push(possibleFieldMappings[i]);
                }
            }
            possibleFieldMappings = availableMappings;

            RenderConfig();
        }

        function AddFinalRow() {
            $('#form').append('<div id="saveRow" class="row mappingRow" style="margin-bottom: 10px;">' +
                '<button type="button" class="btn btn-primary save-row" style="margin-left: 15px;" onclick="AddField(this)">+ Add New Search Mapping</button>' +
                '<button type="button" class="btn btn-danger cancel-row" style="margin-left: 15px; display:none;" onclick="RenderConfig()">- Cancel New Search Mapping</button>' +
                '<span id="ValidationStatus" style="padding-left:10px;"></span><div style="margin-top: 1em" id="ValidationDetails"></div>' +
                '</div>');
        }

        function AddField(e) {
            $(".cancel-row").show();

            var htmlRow = '<div class="row mappingRow row-new">';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<div class="form-group">';
            htmlRow = htmlRow + '<input class="form-control field-mapping-label" type="text" placeholder="Field Name" value="">';
            htmlRow = htmlRow + ' </div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<div class="form-group">';
            htmlRow = htmlRow + '<select class="form-control">';
            htmlRow = htmlRow + '<option>Text</option>';
            htmlRow = htmlRow + '<option>Email</option>';
            htmlRow = htmlRow + '<option>Telephone</option>';
            htmlRow = htmlRow + '</select>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '<div class="col-sm-6 mapping-list">';
            htmlRow = htmlRow + '<div class="row manage-mapping" style="margin-bottom: 10px;">';
            htmlRow = htmlRow + '<button type="button" class="btn btn-primary" style="margin-left: 15px;" onclick="AddMapping(this)">+ Add New Mapping</button>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';

            $('#saveRow').before(htmlRow);
        };

        function RenderConfig() {
            $('.mappingRow').remove();

            if (formFormat !== null) {
                var i;
                for (i = 0; i < formFormat.length; i++) {
                    var formField = formFormat[i];
                    var rowType = "row-odd";
                    if (i % 2 === 0) {
                        rowType = "row-even";
                    }

                    var htmlRow = '<div class="row mappingRow ' + rowType + '">';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow +
                        '<input name = "' +
                        formField.Name +
                        '" class="form-control field-mapping-label" type="text" placeholder="' +
                        formField.Label +
                        '" value="' +
                        formField.Label +
                        '">';
                    htmlRow = htmlRow + ' </div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow +
                        '<select class="form-control" data-fieldname="' +
                        formField.Name +
                        '" onchange="UpdateFieldType(this)">';
                    htmlRow = htmlRow + '<option' + (formField.Type === "Text" ? " selected" : "") + '>Text</option>';
                    htmlRow = htmlRow + '<option' + (formField.Type === "Email" ? " selected" : "") + '>Email</option>';
                    htmlRow = htmlRow +
                        '<option' +
                        (formField.Type === "Telephone" ? " selected" : "") +
                        '>Telephone</option>';
                    htmlRow = htmlRow + '</select>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '<div class="col-sm-6 mapping-list">';
                    for (var mapping in formField.MapsTo) {
                        if (formField.MapsTo.hasOwnProperty(mapping)) {
                            var data = formField.MapsTo[mapping];
                            var j;
                            for (j = 0; j < data.length; j++) {
                                var dataMapping = data[j];

                                htmlRow = htmlRow + '<div class="row existing-mapping" style="margin-bottom: 10px;">';
                                htmlRow = htmlRow + '<div class="form-group">';
                                htmlRow = htmlRow + '<div class="col-sm-4">';
                                htmlRow = htmlRow +
                                    '<select class="form-control field-mapping-entity" disabled="disabled">';
                                htmlRow = htmlRow + '<option>' + mapping + '</option>';
                                htmlRow = htmlRow + '</select>';
                                htmlRow = htmlRow + '</div>';
                                htmlRow = htmlRow + '<div class="col-sm-4">';
                                htmlRow = htmlRow +
                                    '<select class="form-control field-mapping-attr" disabled="disabled">';
                                htmlRow = htmlRow + '<option>' + dataMapping + '</option>';
                                htmlRow = htmlRow + '</select>';
                                htmlRow = htmlRow + '</div>';
                                htmlRow = htmlRow + '<div class="col-sm-4">';
                                htmlRow = htmlRow +
                                    '<button type="button" class="btn btn-danger removemapping" onclick="RemoveThisMapping(this)">Remove</button>';
                                htmlRow = htmlRow + '</div>';
                                htmlRow = htmlRow + '</div>';
                                htmlRow = htmlRow + '</div>';
                            }
                        }
                    }
                    htmlRow = htmlRow + '<div class="row manage-mapping" style="margin-bottom: 10px;">';
                    htmlRow = htmlRow +
                        '<button type="button" class="btn btn-primary" style="margin-left: 15px;" onclick="AddMapping(this)">+ Add New Mapping</button>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';

                    $('#form').append(htmlRow);
                }
            }
            AddFinalRow();
        }

        function RenderResultColumns() {
            $('.resultsRow').remove();

            if (resultsColumns !== null) {
                var i;
                for (i = 0; i < resultsColumns.length; i++) {
                    var resultColumn = resultsColumns[i];
                    var rowType = "row-odd";
                    if (i % 2 === 0) {
                        rowType = "row-even";
                    }

                    var htmlRow = '<div class="row resultsRow ' + rowType + '">';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow + '<input class="form-control result-display" type="text" placeholder="Display Name" value="' + resultColumn.DisplayName + '">';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow + '<input class="form-control result-entity" type="text" placeholder="Entity Logical Name" value="' + (resultColumn.EntityName ?? "All") + '">';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow + '<input class="form-control result-attribute" type="text" placeholder="Attribute Logical Name" value="' + resultColumn.AttributeName + '">';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '<div class="col-sm-3">';
                    htmlRow = htmlRow + '<div class="form-group">';
                    htmlRow = htmlRow + '<button type="button" class="btn btn-danger removemapping" onclick="AlterThisResultsColumn(this, false)">Remove</button>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';
                    htmlRow = htmlRow + '</div>';

                    $('#form_results').append(htmlRow);
                }
            }

            AddFinalResultsColumnRow();
        }

        function AddFinalResultsColumnRow() {
            $('#form_results').append('<div id="saveRow" class="row resultsRow" style="margin-bottom: 10px;">' +
                '<button type="button" class="btn btn-primary save-row" style="margin-left: 15px;" onclick="AddResultsColumnField(this)"> + Add New Results Column</button>' +
                '<span id="ValidationStatus" style="padding-left:10px;"></span><div style="margin-top: 1em" id="ValidationDetails"></div>' +
            '</div>');
        }

        function AddResultsColumnField(e) {
            debugger;
            var mappingListDiv = $(e).parent().parent();
            var htmlRow = '<div class="row resultsRow">';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<div class="form-group">';
            htmlRow = htmlRow + '<input class="form-control result-display" type="text" placeholder="Display Name">';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<div class="form-group">';
            htmlRow = htmlRow + '<input class="form-control result-entity" type="text" placeholder="Entity Logical Name">';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<div class="form-group">';
            htmlRow = htmlRow + '<input class="form-control result-attribute" type="text" placeholder="Attribute Logical Name">';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '<div class="col-sm-3">';
            htmlRow = htmlRow + '<button type="button" class="btn btn-primary" onclick="AlterThisResultsColumn(this, true)">Save</button>';
            htmlRow = htmlRow + '<button type="button" class="btn btn-primary" onclick="CancelNewResultColumn(this)" style="margin-left:15px;">Cancel</button>';
            htmlRow = htmlRow + '</div>';
            htmlRow = htmlRow + '</div>';


            mappingListDiv.append(htmlRow);
            $(e).parent().hide();
            
        }

        function CancelNewResultColumn(e) {
            RenderResultColumns();
        }

        function AlterThisResultsColumn(e, add) {
            var mappingDiv;
            if (add) {
                mappingDiv = $(e).parent().parent();
            } else {
                mappingDiv = $(e).parent().parent().parent();
            }

            var entitySelect = mappingDiv.find('.result-entity');
            var mappedEntity = entitySelect.val();
            if (mappedEntity == "All") {
                mappedEntity = null;
            }

            var attrSelect = mappingDiv.find('.result-attribute');
            var mappedAttr = attrSelect.val();

            var displaySelect = mappingDiv.find('.result-display');
            var displayVal = displaySelect.val();

            if (add) {
                AddResultColumn(mappedEntity, mappedAttr, displayVal);
            } else {
                RemoveResultColumn(mappedEntity, mappedAttr);
            }
        }

        function RemoveResultColumn(mappedEntity, mappedAttr) {
            var i;
            for (i = 0; i < resultsColumns.length; i++) {
                var resultColumn = resultsColumns[i];
                if (resultColumn.EntityName === mappedEntity && resultColumn.AttributeName == mappedAttr) {
                    resultsColumns.splice(i, 1);
                }
            }

            RenderResultColumns();
        }

        function AddResultColumn(mappedEntity, mappedAttr, displayVal) {
            var newColumn = {
                "EntityName": mappedEntity,
                "AttributeName": mappedAttr,
                "DisplayName": displayVal
            };
            if (resultsColumns == null) {
                resultsColumns = [];
            }

            resultsColumns.push(newColumn);
            RenderResultColumns();
        }

        function UpdateFieldType(e) {
            var fieldName = $(e).attr("data-fieldname");
            var i;
            for (i = 0; i < formFormat.length; i++) {
                var formField = formFormat[i];
                if (formField.Name === fieldName) {
                    formFormat[i].Type = e[e.selectedIndex].text;
                }
            }
        }

        function guidGenerator() {
            var S4 = function () {
                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
            };
            return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
        }

        function SaveForm() {
            var format = {
                "Mappings": formFormat,
                "AdditionalFields": resultsColumns
            };

            var data = {
                data8_globalsearchformat: JSON.stringify(format)
            };

            var onSuccess = function () {
                $("#ValidationStatus").text("Details saved successfully");
                $('#save').prop("disabled", false);
            };

            var onError = function (jqXHR) {
                // Extract and show error
                var response = JSON.parse(jqXHR.responseText);
                var msg = response.error.message;
                var detailsIndex = msg.indexOf("Details: ");
                var details = "";
                if (detailsIndex !== -1) {
                    details = msg.substring(detailsIndex);
                    msg = msg.substring(0, detailsIndex);
                }
                $("#ValidationStatus").text(msg);
                $("#ValidationDetails").text(details);

                $('#save').prop("disabled", false);
            };

            $('#save').prop("disabled", true);
            $.ajax(oDataEndpoint + "data8_globaldedupeconfigurations(" + globalId + ")",
                {
                    method: "PATCH",
                    contentType: "application/json",
                    data: JSON.stringify(data),
                    dataType: "json",
                    success: onSuccess,
                    error: onError
                });
        }

    </script>
</body>
</html>