<commit_before>﻿@{
    Layout = null;
}

<!DOCTYPE html>

<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Configuring decision engine</title>
        <style type="text/css" media="screen">
            #editor { 
                position: relative;
                min-height: 100px;
            }
        </style>
        <link href="@Url.Content("~/Content/bootstrap-theme.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/tree.css")" rel="stylesheet" type="text/css" />
        <script type='text/javascript' src='@Url.Content("~/Scripts/knockout-3.0.0.debug.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/json2.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/jquery-2.0.0.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/bootstrap.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/ace/ace.js")' charset="utf-8"></script>
    </head>
    <body style="padding-top: 50px">
        <!--<strong data-bind="text: JSON.stringify({name : 1})"></strong>-->
     
      <div class="navbar navbar-default navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Decision engine configuration</a>
        </div>
        <div class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="active"><button type="button" class="btn btn-default navbar-btn">Add activity</button></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>

        <div class="container">
            <div class="panel panel-default" style="width: 300px; float: left">
                <div class="panel-heading">Activities tree</div>
                <div class="panel-body">
                    <div class="list-group" data-bind="foreach: rootGroups">
                        <!-- ko template: { name: 'activities-group-tree-node', data: { data: $data, indent: 0} } -->
                        <!-- /ko -->
                    </div>
                </div>
            </div>
            
            <!-- View for activity -->
            <div style="margin-left: 330px; margin-top: 30px" data-bind="with: chosenActivity">
                <div class="input-group">
                    <span class="input-group-addon">Name</span>
                    
                    <!-- ko if: $root.allowEdit -->
                    <input type="text" class="form-control" placeholder="Activity name" data-bind="value: name">
                    <!-- /ko -->
                    <!-- ko ifnot: $root.allowEdit -->
                    <span class="form-control" data-bind="text: name"></span>
                    <!-- /ko -->
                </div>
                
                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Activity condition</h3>
                    </div>
                    <div class="panel-body" style="height: 100px; padding: 0">
                        <div id="activityConditionEditor" style="height: 100px"></div>
                    </div>
                </div>
                
                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Activity rules</h3>
                    </div>
                    <div class="panel-body" style="height: 200px">
                        <span>Rules list.</span>
                    </div>
                </div>
            </div>
            
            <!-- View for Group -->
            <div style="margin-left: 330px; margin-top: 30px" data-bind="with: chosenGroup">
                <div class="input-group">
                    <span class="input-group-addon">Name</span>
                    
                    <!-- ko if: $root.allowEdit -->
                    <input type="text" class="form-control" placeholder="Group name" data-bind="value: name">
                    <!-- /ko -->
                    <!-- ko ifnot: $root.allowEdit -->
                    <span class="form-control" data-bind="text: name"></span>
                    <!-- /ko -->
                </div>
                
                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Group condition</h3>
                    </div>
                    <div class="panel-body" style="height: 100px; padding: 0">
                        <div id="groupConditionEditor" style="height: 100px"></div>
                    </div>
                </div>
            </div>
            
            
        </div>
    </body>
</html>

<script type="text/html" id="activities-group-tree-node">
    <a href="#" data-bind="css: (($data.data === $root.chosenGroup()) ? 'list-group-item active' : 'list-group-item'), style: { marginLeft: (indent * 20).toString() + 'px' }, click: $root.showGroupContent">
        <!-- ko if: CheckArrayNonEmpty($data.data.groups()) || CheckArrayNonEmpty($data.data.activities()) -->
        <span class="glyphicon glyphicon-minus"></span>
        <!-- /ko -->
        <span class="badge">...</span> <span data-bind="text: data.name"></span>
    </a>
    
    <!-- ko foreach: data.groups() -->
        <!-- ko template: { name: 'activities-group-tree-node', data: { data: $data, indent: $parent.indent + 1} } --><!-- /ko -->
    <!-- /ko -->
    <!-- ko foreach: data.activities() -->
        <!-- ko template: { name: 'activity-tree-node', data: { data: $data, indent: $parent.indent + 1} } --><!-- /ko -->
    <!-- /ko -->
</script>
<script type="text/html" id="activity-tree-node">
    <a href="#" data-bind="css: (($data.data === $root.chosenActivity()) ? 'list-group-item active' : 'list-group-item'), style: { marginLeft: (indent * 20).toString() + 'px' }, click: $root.showActivityContent">
        <span class="glyphicon glyphicon-minus"></span><span class="badge">...</span> <span data-bind="text: data.name"></span>
    </a>
    <!-- ko if: CheckArrayNonEmpty(data.approveRules()) -->
    <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
        <span>Approve rules</span>
    </a>
    <!-- /ko -->
    
    <!-- ko if: CheckArrayNonEmpty(data.rejectRules()) -->
    <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
        <span>Reject rules</span>
    </a>
    <!-- /ko -->
    
    <!-- ko if: CheckArrayNonEmpty(data.suspendRules()) -->
    <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
        <span>Suspend rules</span>
    </a>
    <!-- /ko -->
</script>

<script type='text/javascript'>
    function CheckArrayNonEmpty(array) {
        return array != null && array.length != 0;
    }

    function getStyle(el, styleProp) {
        var value, defaultView = (el.ownerDocument || document).defaultView;
        // W3C standard way:
        if (defaultView && defaultView.getComputedStyle) {
            // sanitize property name to css notation
            // (hypen separated words eg. font-Size)
            styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
            return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
        } else if (el.currentStyle) { // IE
            // sanitize property name to camelCase
            styleProp = styleProp.replace(/\-(\w)/g, function (str, letter) {
                return letter.toUpperCase();
            });
            value = el.currentStyle[styleProp];
            // convert other units to pixels on IE
            if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
                return (function (value) {
                    var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
                    el.runtimeStyle.left = el.currentStyle.left;
                    el.style.left = value || 0;
                    value = el.style.pixelLeft + "px";
                    el.style.left = oldLeft;
                    el.runtimeStyle.left = oldRsLeft;
                    return value;
                })(value);
            }
            return value;
        }
    }
    
    function getLeftMargin(el) {
        return parseInt(getStyle(el, "margin-left"), 10);
    }
    
    function getChildNodes(node) {
        var targetNodeMargin = getLeftMargin(node[0]);
        var result = [];
        while (true) {
            var nextNode = node.next(".list-group-item");
            
            if (nextNode == null || nextNode.length === 0 || getLeftMargin(nextNode[0]) <= targetNodeMargin) {
                break;
            }
            result.push(nextNode[0]);
            node = nextNode;
        }
        return result;
    }
    
    function getObservableActivityGroup(plainGroup) {
        var group = {
            name: ko.observable(plainGroup.Name), groups: ko.observableArray(),
            activities: ko.observableArray(), condition: ko.observable(plainGroup.Condition)
        };
        if (plainGroup.Groups != null) {
            for (var i = 0; i < plainGroup.Groups.length; i++) {
                group.groups.push(getObservableActivityGroup(plainGroup.Groups[i]));
            }
        }
        if (plainGroup.Activities != null) {
            for (var j = 0; j < plainGroup.Activities.length; j++) {
                group.activities.push(getObservableActivity(plainGroup.Activities[j]));
            }
        }
        return group;
    }
    
    function getObservableActivity(plainActivity) {
        var activity = {
            name: ko.observable(plainActivity.Name),
            condition: ko.observable(plainActivity.Condition),
            approveRules: ko.observableArray(),
            rejectRules: ko.observableArray(),
            suspendRules: ko.observableArray(),
        };
        if (plainActivity.ApproveRules != null) {
            for (var i = 0; i < plainActivity.ApproveRules.length; i++) {
                activity.approveRules.push(getObservableRule(plainActivity.ApproveRules[i]));
            }
        }
        if (plainActivity.RejectRules != null) {
            for (var j = 0; j < plainActivity.RejectRules.length; j++) {
                activity.rejectRules.push(getObservableRule(plainActivity.RejectRules[j]));
            }
        }
        if (plainActivity.SuspendRules != null) {
            for (var k = 0; k < plainActivity.SuspendRules.length; k++) {
                activity.suspendRules.push(getObservableRule(plainActivity.SuspendRules[k]));
            }
        }
        return activity;
    }
    
    function getObservableRule(plainRule) {
        var rule = {
            name: ko.observable(plainRule.Name),
            description: ko.observable(plainRule.Description),
            expression: ko.observable(plainRule.Expression)
        };
        return rule;
    }
    
    // view models
    function ActivityListViewModel() {
        // Data
        var self = this;
        self.rootGroups = ko.observableArray();
        self.showActivityContent = function (data) {
            self.chosenActivity(data.data);
            self.chosenGroup(null);

            var editor = ace.edit("activityConditionEditor");
            //editor.setTheme("ace/theme/monokai");
            editor.getSession().setMode("ace/mode/javascript");
            editor.setValue(data.data.condition());
            editor.setReadOnly(true);
            console.log("PISH!");
        };
        self.showGroupContent = function (data) {
            self.chosenActivity(null);
            self.chosenGroup(data.data);
            var editor = ace.edit("groupConditionEditor");
            //editor.setTheme("ace/theme/monokai");
            editor.getSession().setMode("ace/mode/javascript");
            editor.setValue(data.data.condition());
            editor.setReadOnly(true);
        };
        self.chosenActivity = ko.observable();
        self.chosenGroup = ko.observable();
        self.allowEdit = ko.observable(false);
        

        $.getJSON("/data/load", function (data) {
            for (var i = 0; i < data.Groups.length; i++) {
                self.rootGroups.push(getObservableActivityGroup(data.Groups[i]));
            }

            $(function () {

                var arr = $('.list-group-item');

                for (var i = 0; i < arr.length; i++) {
                    var currentIndent = getLeftMargin(arr[i]);
                    if (i < arr.length - 1 && getLeftMargin(arr[i + 1])> currentIndent) {
                        $(arr[i]).addClass('parent_li').find(' > span.glyphicon').attr('title', 'Collapse this branch');
                    }
                }

                $('.parent_li > span.glyphicon').on('click', function (e) {
                    var children = $(getChildNodes($(this).parent('.parent_li')));

                    if (children.is(":visible")) {
                        children.hide('fast');
                        $(this).attr('title', 'Expand this branch').addClass('glyphicon-plus').removeClass('glyphicon-minus');
                    } else {
                        children.show('fast');
                        $(this).attr('title', 'Collapse this branch').addClass('glyphicon-minus').removeClass('glyphicon-plus');
                    }
                    e.stopPropagation();
                });
            });
        });

        //self.viewActivity = function(activity) {  };
    };

    ko.applyBindings(new ActivityListViewModel());
    
   
    
</script><commit_msg>firday commit<commit_after>﻿@{
    Layout = null;
}

<!DOCTYPE html>

<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Configuring decision engine</title>
        <link href="@Url.Content("~/Content/bootstrap-theme.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/tree.css")" rel="stylesheet" type="text/css" />
        <script type='text/javascript' src='@Url.Content("~/Scripts/knockout-3.0.0.debug.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/json2.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/jquery-2.0.0.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/bootstrap.js")'></script>
        <script type='text/javascript' src='@Url.Content("~/Scripts/ace/ace.js")'></script>
        <script type='text/html' src='@Url.Content("helper.js")'></script>
        <script type="text/html" id="activities-group-tree-node">
            <a href="#" data-bind="css: (($data.data === $root.chosenGroup()) ? 'list-group-item active' : 'list-group-item'), style: { marginLeft: (indent * 20).toString() + 'px' }, click: $root.showGroupContent">
                <!-- ko if: CheckArrayNonEmpty($data.data.groups()) || CheckArrayNonEmpty($data.data.activities()) -->
                <span class="glyphicon glyphicon-minus"></span>
                <!-- /ko -->
                <span class="badge">...</span> <span data-bind="text: data.name"></span>
            </a>

            <!-- ko foreach: data.groups() -->
            <!-- ko template: { name: 'activities-group-tree-node', data: { data: $data, indent: $parent.indent + 1} } -->
            <!-- /ko -->
            <!-- /ko -->
            <!-- ko foreach: data.activities() -->
            <!-- ko template: { name: 'activity-tree-node', data: { data: $data, indent: $parent.indent + 1} } -->
            <!-- /ko -->
            <!-- /ko -->
        </script>
        <script type="text/html" id="activity-tree-node">
            <a href="#" data-bind="css: (($data.data === $root.chosenActivity()) ? 'list-group-item active' : 'list-group-item'), style: { marginLeft: (indent * 20).toString() + 'px' }, click: $root.showActivityContent">
                <span class="glyphicon glyphicon-minus"></span><span class="badge">...</span> <span data-bind="text: data.name"></span>
            </a>
            <!-- ko if: CheckArrayNonEmpty(data.approveRules()) -->
            <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
                <span>Approve rules</span>
            </a>
            <!-- /ko -->

            <!-- ko if: CheckArrayNonEmpty(data.rejectRules()) -->
            <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
                <span>Reject rules</span>
            </a>
            <!-- /ko -->

            <!-- ko if: CheckArrayNonEmpty(data.suspendRules()) -->
            <a href="#" class="list-group-item" data-bind="style: { marginLeft: ((indent + 1) * 20).toString() + 'px' }">
                <span>Suspend rules</span>
            </a>
            <!-- /ko -->
        </script>
    </head>
    <body style="padding-top: 50px">
        <!--<strong data-bind="text: JSON.stringify({name : 1})"></strong>-->

        <div class="navbar navbar-default navbar-fixed-top" role="navigation">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Decision engine configuration</a>
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li><button type="button" class="btn btn-default navbar-btn">Add activity</button></li>
                        <li><button type="button" class="btn btn-default navbar-btn">Add group</button></li>
                        <li><button type="button" class="btn btn-default navbar-btn" data-bind="click: setAllowEdit">Edit</button></li>
                        <li><button type="button" class="btn btn-default navbar-btn">Save</button></li>
                    </ul>
                </div>
                <!--/.nav-collapse -->
            </div>
        </div>

        <div class="container">
            <div class="panel panel-default" style="width: 300px; float: left">
                <div class="panel-heading">Activities tree</div>
                <div class="panel-body">
                    <div class="list-group" data-bind="foreach: rootGroups">
                        <!-- ko template: { name: 'activities-group-tree-node', data: { data: $data, indent: 0} } -->
                        <!-- /ko -->
                    </div>
                </div>
            </div>

            <!-- View for activity -->
            <div style="margin-left: 330px; margin-top: 30px" data-bind="with: chosenActivity">
                <div class="input-group">
                    <span class="input-group-addon">Name</span>

                    <!-- ko if: $root.allowEdit -->
                    <input type="text" class="form-control" placeholder="Activity name" data-bind="value: name">
                    <!-- /ko -->
                    <!-- ko ifnot: $root.allowEdit -->
                    <span class="form-control" data-bind="text: name"></span>
                    <!-- /ko -->
                </div>

                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Activity condition</h3>
                    </div>
                    <div class="panel-body" style="height: 100px; padding: 0">
                        <div id="activityConditionEditor" style="height: 100px"></div>
                    </div>
                </div>

                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Activity rules</h3>
                    </div>
                    <div class="panel-body" style="height: 200px">
                        <span>Rules list.</span>
                    </div>
                </div>
            </div>

            <!-- View for Group -->
            <div style="margin-left: 330px; margin-top: 30px" data-bind="with: chosenGroup">
                <div class="input-group">
                    <span class="input-group-addon">Name</span>

                    <!-- ko if: $root.allowEdit -->
                    <input type="text" class="form-control" placeholder="Group name" data-bind="value: name">
                    <!-- /ko -->
                    <!-- ko ifnot: $root.allowEdit -->
                    <span class="form-control" data-bind="text: name"></span>
                    <!-- /ko -->
                </div>

                <div class="panel panel-default" style="margin-top: 20px">
                    <div class="panel-heading">
                        <h3 class="panel-title">Group condition</h3>
                    </div>
                    <div class="panel-body" style="height: 100px; padding: 0">
                        <div id="groupConditionEditor" style="height: 100px"></div>
                    </div>
                </div>
            </div>

        </div>
    </body>
</html>

<script type='text/javascript'>
    function CheckArrayNonEmpty(array) {
        return array != null && array.length != 0;
    }

    function getStyle(el, styleProp) {
        var value, defaultView = (el.ownerDocument || document).defaultView;
        // W3C standard way:
        if (defaultView && defaultView.getComputedStyle) {
            // sanitize property name to css notation
            // (hypen separated words eg. font-Size)
            styleProp = styleProp.replace(/([A-Z])/g, "-$1").toLowerCase();
            return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
        } else if (el.currentStyle) { // IE
            // sanitize property name to camelCase
            styleProp = styleProp.replace(/\-(\w)/g, function (str, letter) {
                return letter.toUpperCase();
            });
            value = el.currentStyle[styleProp];
            // convert other units to pixels on IE
            if (/^\d+(em|pt|%|ex)?$/i.test(value)) {
                return (function (value) {
                    var oldLeft = el.style.left, oldRsLeft = el.runtimeStyle.left;
                    el.runtimeStyle.left = el.currentStyle.left;
                    el.style.left = value || 0;
                    value = el.style.pixelLeft + "px";
                    el.style.left = oldLeft;
                    el.runtimeStyle.left = oldRsLeft;
                    return value;
                })(value);
            }
            return value;
        }
    }

    function getLeftMargin(el) {
        return parseInt(getStyle(el, "margin-left"), 10);
    }

    function getChildNodes(node) {
        var targetNodeMargin = getLeftMargin(node[0]);
        var result = [];
        while (true) {
            var nextNode = node.next(".list-group-item");
            
            if (nextNode == null || nextNode.length === 0 || getLeftMargin(nextNode[0]) <= targetNodeMargin) {
                break;
            }
            result.push(nextNode[0]);
            node = nextNode;
        }
        return result;
    }
    
    function getObservableActivityGroup(plainGroup) {
        var group = {
            name: ko.observable(plainGroup.Name), groups: ko.observableArray(),
            activities: ko.observableArray(), condition: ko.observable(plainGroup.Condition)
        };
        if (plainGroup.Groups != null) {
            for (var i = 0; i < plainGroup.Groups.length; i++) {
                group.groups.push(getObservableActivityGroup(plainGroup.Groups[i]));
            }
        }
        if (plainGroup.Activities != null) {
            for (var j = 0; j < plainGroup.Activities.length; j++) {
                group.activities.push(getObservableActivity(plainGroup.Activities[j]));
            }
        }
        return group;
    }
    
    function getObservableActivity(plainActivity) {
        var activity = {
            name: ko.observable(plainActivity.Name),
            condition: ko.observable(plainActivity.Condition),
            approveRules: ko.observableArray(),
            rejectRules: ko.observableArray(),
            suspendRules: ko.observableArray(),
        };
        if (plainActivity.ApproveRules != null) {
            for (var i = 0; i < plainActivity.ApproveRules.length; i++) {
                activity.approveRules.push(getObservableRule(plainActivity.ApproveRules[i]));
            }
        }
        if (plainActivity.RejectRules != null) {
            for (var j = 0; j < plainActivity.RejectRules.length; j++) {
                activity.rejectRules.push(getObservableRule(plainActivity.RejectRules[j]));
            }
        }
        if (plainActivity.SuspendRules != null) {
            for (var k = 0; k < plainActivity.SuspendRules.length; k++) {
                activity.suspendRules.push(getObservableRule(plainActivity.SuspendRules[k]));
            }
        }
        return activity;
    }
    
    function getObservableRule(plainRule) {
        var rule = {
            name: ko.observable(plainRule.Name),
            description: ko.observable(plainRule.Description),
            expression: ko.observable(plainRule.Expression)
        };
        return rule;
    }
    
    // view model
    function ActivityListViewModel() {
        var self = this;
        self.rootGroups = ko.observableArray();

        self.saveGroupChanges = function(data) {
            if (self.chosenGroup() == null) return;
            var editor = ace.edit("groupConditionEditor");
            self.chosenGroup().condition(editor.getValue());
        };

        self.showActivityContent = function (data) {
            self.chosenActivity(data.data);
            self.saveGroupChanges();
            self.chosenGroup(null);
            var editor = ace.edit("activityConditionEditor");
            editor.getSession().setMode("ace/mode/javascript");
            editor.setValue(data.data.condition());
            editor.setReadOnly(true);
            self.allowEdit(false);
        };
        self.showGroupContent = function (data) {
            self.chosenActivity(null);
            self.saveGroupChanges();
            self.chosenGroup(data.data);
            var editor = ace.edit("groupConditionEditor");
            editor.getSession().setMode("ace/mode/javascript");
            editor.setValue(data.data.condition());
            editor.setReadOnly(true);
            self.allowEdit(false);
        };
        self.setAllowEdit = function (data) {
            self.allowEdit(true);
            var editor = null;
            if (self.chosenActivity() != null) {
                editor = ace.edit("activityConditionEditor");
            }
            if (self.chosenGroup() != null) {
                editor = ace.edit("groupConditionEditor");
            }
            if (editor != null) {
                editor.setReadOnly(false);
            }
        };
        self.chosenActivity = ko.observable();
        self.chosenGroup = ko.observable();
        self.allowEdit = ko.observable(false);
        

        $.getJSON("/data/load", function (data) {
            for (var i = 0; i < data.Groups.length; i++) {
                self.rootGroups.push(getObservableActivityGroup(data.Groups[i]));
            }

            $(function () {
                var arr = $('.list-group-item');

                for (var i = 0; i < arr.length; i++) {
                    var currentIndent = getLeftMargin(arr[i]);
                    if (i < arr.length - 1 && getLeftMargin(arr[i + 1])> currentIndent) {
                        $(arr[i]).addClass('parent_li').find(' > span.glyphicon').attr('title', 'Collapse this branch');
                    }
                }

                $('.parent_li > span.glyphicon').on('click', function (e) {
                    var children = $(getChildNodes($(this).parent('.parent_li')));

                    if (children.is(":visible")) {
                        children.hide('fast');
                        $(this).attr('title', 'Expand this branch').addClass('glyphicon-plus').removeClass('glyphicon-minus');
                    } else {
                        children.show('fast');
                        $(this).attr('title', 'Collapse this branch').addClass('glyphicon-minus').removeClass('glyphicon-plus');
                    }
                    e.stopPropagation();
                });
            });
        });
    };

    ko.applyBindings(new ActivityListViewModel());
</script>
{'fraction_non_alphanumeric': 0.1603617588499308, 'fraction_numerical': 0.006006816724597577, 'mean_word_length': 1.7137362637362636, 'pattern_counts': {'":': 2, '<': 383, '<?xml version=': 0, '>': 371, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5105519', 'n_tokens_mistral': 8361, 'n_tokens_neox': 7952, 'n_words': 1512}