<commit_before><link rel="import" href="../../../../polymer/polymer.html">
<link rel="import" href="../../../../iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../../iron-list/iron-list.html">


<script src="../../../../line-navigator/file-wrapper.js"></script>
<script src="../../../../line-navigator/line-navigator.js"></script>

<script src="validator.js"></script>
<script src="vcf-validator.js"></script>
<script src="bed-validator.js"></script>
<script src="expression-validator.js"></script>
<script src="experimental-design-validator.js"></script>

<dom-module name="jso-validator">
    <style is="custom-style" include="iron-flex iron-flex-reverse iron-flex-alignment iron-flex-factors iron-positioning">
        :host {
            display: block;
            position: relative;
            box-sizing: border-box;
            height: 300px;
        }

        #header,
        #footer {
            box-sizing: border-box;
            background-color: var(--light-secondary-color);
            padding: 0 7px;
        }

        #header {
            height: 30px;
            border-bottom: 1px solid var(--divider-color);
        }

        #footer {
            height: 30px;
            border-top: 1px solid var(--divider-color);
        }

        #footer>* {
            margin-left: 3px;
        }

        .line {
            width: 40px;
        }

        .type {
            width: 60px;
        }

        #stop {
            margin-left: 7px;
            background-color: var(--dark-button-color);
            color: var(--text-primary-color);
        }

        #stop:hover {
            background-color: var(--light-button-color);
        }

        .type[type="error"],
        .error-count {
            color: #bf4747;
        }

        .type[type="info"],
        .info-count {
            color: #4790bf;
        }

        .type[type="warning"],
        .warning-count {
            color: #bf9947;
        }

        .item {
            /*display: block;*/
            /*position: relative;*/
            /*box-sizing: border-box;*/
            /*height: auto;*/
            /*margin: 3px;*/
            padding: 1px 2px;
            height: 50px;
            border-left: 2px solid transparent;
        }

        .item:hover {
            border-left: 2px solid var(--divider-color);
        }

        .view {
            cursor: pointer;
            visibility: hidden;
        }

        .item:hover > .view {
            visibility: visible;
        }

        .view > i:hover {
            color: var(--dark-button-color);
        }

        .line {
            padding-right: 1px;
            text-align: center;
        }

        .type {
            padding: 0 1px;
            text-align: center;
        }

        .msg {
            word-break: break-all;
            font-size: .95em;
        }

        .item[type="error"] {
            background-color: rgba(191, 71, 71, 0.15);
            border: 1px solid rgba(191, 71, 71, 0.3)
        }

        .item[type="warning"] {
            background-color: rgba(255, 191, 0, 0.15);
            border: 1px solid rgba(255, 191, 0, 0.3);
        }

        .log {
            position: relative;
            height: calc(100% - 48px);
            overflow-y: auto;
            /*background-color: #FAFAFA;*/
            background-color: white;
        }

        .count {
            padding: 0 5px;
        }

        .count > span {
            color: black;
        }

        .uploadbar {
            position: relative;
            height: 18px;
            width: 100px;
            background-color: var(--light-primary-color);
            line-height: 18px;
            border: 1px solid var(--divider-color);
        }

        .uploadprogress {
            position: absolute;
            top: 0px;
            left: 0px;
            height: 100%;
            width: 100%;
            background-color: var(--hover-color);
            /*margin-top: 10px;*/
        }

        .uploadtext {
            position: absolute;
            text-align: center;
            top: 0px;
            left: 0px;
            height: 100%;
            width: 100%;
        }

        .header > div {
            padding-left: 2px;
        }

        .wrapped-text {
            white-space: pre-wrap;
            padding: 10px;
            overflow-y: auto;
            min-width: 400px;
            min-height: 150px;
        }

        #linePreview {
            width: 300px;
            background-color: var(--light-primary-color);
            height: 50px;

        }
    </style>
    <template>

        <div id="header" class="horizontal layout center">
            <div class="line">Line </div>
            <div class="type">Type</div>
            <div class="msg">Message</div>
            <div class="flex"></div>
            <div class="uploadbar" hidden$="{{!uploading}}">
                <div id="progressBar" class="uploadprogress"></div>
                <div class="uploadtext">
                    <i id="spin" hidden$="{{computeSpin(progress)}}" class="fa fa-spinner fa-spin"></i>
                    <span>{{progress}}</span> %
                </div>
                <br>
            </div>
            <div id="stop" class="jso-btn jso-btn-shdw" on-click="handleStop">Stop</div>
        </div>
        <iron-list class="log" items="{{logIron}}" as="item">
            <template>
                <div class="horizontal layout center item" type$="{{item.type}}">
                    <div class="line">{{item.line}}</div>
                    <div class="type" type$="{{item.type}}">{{item.type}}</div>
                    <div class="msg flex">{{item.msg}}</div>
                    <div class="view" line="{{item.line}}" column="{{item.column}}" on-click="handleLogViewClick" title="View line"><i class="fa fa-search"></i></div>
                </div>
            </template>
        </iron-list>

        <div id="footer" class="counts horizontal layout center">
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="error" data-checked$="{{computeView(view, 'error')}}">
                <div class="error-count count">Errors:
                    <span>{{errorCount}}</span>
                </div>
            </div>
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="warning" data-checked$="{{computeView(view, 'warning')}}">
                <div class="warning-count count">Warning:
                    <span>{{warningCount}}</span>
                </div>
            </div>
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="info" data-checked$="{{computeView(view, 'info')}}">
                <div class="info-count count">Info:
                    <span>{{infoCount}}</span>
                </div>
            </div>
            <div class="flex"></div>
            <div class="count">Lines:
                <span>{{numLines}}</span>
            </div>
        </div>

        <jso-panel modal movable closable hidden id="linePreviewPanel" on-close="handleCloseLinePreview">
            <div class="header">
                <i class="fa fa-view"></i> &nbsp; View line
            </div>
            <div class="container wrapped-text">{{linePreview}}</div>
        </jso-panel>


    </template>

    <script>
        Polymer({
            is: "jso-validator",
            properties: {
                file: {
                    type: Object,
                    value: function() {
                        return null;
                    },
                    observer: 'fileChanged'
                },
                validator: {
                    type: Object,
                    value: function() {
                        return new Validator({});
                    },
                    observer: 'validatorChanged'
                },
                logIron: {
                    type: Array
                },
                log: {
                    type: Object,
                    value: function() {
                        return {
                            error: [],
                            warning: [],
                            info: []
                        }
                    }
                },
                errorCount: {
                    type: Number,
                    value: 0
                },
                warningCount: {
                    type: Number,
                    value: 0
                },
                infoCount: {
                    type: Number,
                    value: 0
                },
                numLines: {
                    type: Number,
                    value: 0
                },
                progress: {
                    type: Number,
                    value: 0,
                    observer: 'progressChanged'
                },
                view: {
                    type: String,
                    value: 'error'
                },
            },
            ready: function() {
                this.set("logIron", this.log[this.view]);
            },
            handleView: function(e) {
                this.view = e.currentTarget.dataset.value;
                this.set("logIron", this.log[this.view]);
            },
            computeView: function(view, value) {
                return view === value;
            },
            reset: function() {
                this.progress = 0;
                this.set("log", {
                    error: [],
                    warning: [],
                    info: []
                });
                this.set("logIron", this.log[this.view]);
                this.errorCount = 0;
                this.warningCount = 0;
                this.infoCount = 0;
                this.numLines = 0;
                if (this.validator) {
                    this.validator.init();
                }
                this.setFile();
            },
            validate: function() {
                this.set("log", {
                    error: [],
                    warning: [],
                    info: []
                });
                this.set("logIron", this.log[this.view]);
                this.errorCount = 0;
                this.warningCount = 0;
                this.infoCount = 0;
                this.numLines = 0;
                this.validator.validate();
            },
            handleStop: function(e) {
                this.stop();
            },
            stop: function() {
                if (this.validator) {
                    this.validator.stop();
                }
            },
            setFile: function(file) {
                this.fileChanged(file);
            },
            validatorChanged: function(neo, old) {
                var me = this;
                neo.on("end", function(e) {
                    me.numLines = me.validator.numLines;
                    me.fire("end");
                });

                neo.on("err", function(e) {
                    me.fire("err");
                });

                neo.on("stop", function(e) {
                    me.$.spin.setAttribute('hidden', '');
                    me.fire("stop");
                });

                neo.on("log", function(e) {
                    switch (e.type) {
                        case "error":
                            me.errorCount++;
                            if (me.errorCount == 100) {
                                me.stop();
                                alert('File has more than 100 errors, the validation is stopped');
                            }
                            break;
                        case "warning":
                            me.warningCount++;
                            break;
                    }
                    if (me.log[e.type] == me.logIron) {
                        me.push("logIron", e);
                    } else {
                        me.push('log.' + e.type, e);
                    }
                });

                neo.on("lines", function(e) {
                    me.set('numLines', e);
                });

                neo.on("progress", function(e) {
                    me.set('progress', Math.ceil(e));
                });

                neo.init();

            },
            fileChanged: function(neo, old) {
                if (neo && this.validator) {
                    this.validator.init();
                    this.validator.file = neo;
                }
            },
            computeLog: function(validator) {
                if (validator) {
                    return validator.log;
                } else {
                    return [];
                }
            },
            progressChanged: function(neo, old) {
                // console.log("progress : " + neo);
                this.$.progressBar.style.width = neo + '%';
            },
            computeSpin: function(progress) {
                return progress >= 100 || progress <= 0;
            },
            handleLogViewClick: function(e) {
                var me = this;
                var elem = e.currentTarget;
                var line = elem.line - 1;
                this.column = elem.column;
                this.validator._navigator.readLines(line, 1, function linesReadHandler(err, index, lines, eof, progress) {
                    if (err) {
                        return;
                    }

                    if (lines.length > 0) {
                        var aux = lines[0].split("\t");
                        aux[me.column] = '<span style="color:red">' + aux[me.column] + '</span>';
                        me.linePreview = lines[0];
                        me.$.linePreviewPanel.hidden=false;
                    }

                    if (eof) {
                        return;
                    }

                });
            },
            handleCloseLinePreview: function(e) {
                e.stopPropagation();
                this.$.linePreviewPanel.innerHTML = "";
            }
        })
    </script>
</dom-module>
<commit_msg>Solved bug in line preview in jso-validator<commit_after><link rel="import" href="../../../../polymer/polymer.html">
<link rel="import" href="../../../../iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../../iron-list/iron-list.html">


<script src="../../../../line-navigator/file-wrapper.js"></script>
<script src="../../../../line-navigator/line-navigator.js"></script>

<script src="validator.js"></script>
<script src="vcf-validator.js"></script>
<script src="bed-validator.js"></script>
<script src="expression-validator.js"></script>
<script src="experimental-design-validator.js"></script>

<dom-module name="jso-validator">
    <style is="custom-style" include="iron-flex iron-flex-reverse iron-flex-alignment iron-flex-factors iron-positioning">
        :host {
            display: block;
            position: relative;
            box-sizing: border-box;
            height: 300px;
        }

        #header,
        #footer {
            box-sizing: border-box;
            background-color: var(--light-secondary-color);
            padding: 0 7px;
        }

        #header {
            height: 30px;
            border-bottom: 1px solid var(--divider-color);
        }

        #footer {
            height: 30px;
            border-top: 1px solid var(--divider-color);
        }

        #footer>* {
            margin-left: 3px;
        }

        .line {
            width: 40px;
        }

        .type {
            width: 60px;
        }

        #stop {
            margin-left: 7px;
            background-color: var(--dark-button-color);
            color: var(--text-primary-color);
        }

        #stop:hover {
            background-color: var(--light-button-color);
        }

        .type[type="error"],
        .error-count {
            color: #bf4747;
        }

        .type[type="info"],
        .info-count {
            color: #4790bf;
        }

        .type[type="warning"],
        .warning-count {
            color: #bf9947;
        }

        .item {
            /*display: block;*/
            /*position: relative;*/
            /*box-sizing: border-box;*/
            /*height: auto;*/
            /*margin: 3px;*/
            padding: 1px 2px;
            height: 50px;
            border-left: 2px solid transparent;
        }

        .item:hover {
            border-left: 2px solid var(--divider-color);
        }

        .view {
            cursor: pointer;
            visibility: hidden;
        }

        .item:hover > .view {
            visibility: visible;
        }

        .view > i:hover {
            color: var(--dark-button-color);
        }

        .line {
            padding-right: 1px;
            text-align: center;
        }

        .type {
            padding: 0 1px;
            text-align: center;
        }

        .msg {
            word-break: break-all;
            font-size: .95em;
        }

        .item[type="error"] {
            background-color: rgba(191, 71, 71, 0.15);
            border: 1px solid rgba(191, 71, 71, 0.3)
        }

        .item[type="warning"] {
            background-color: rgba(255, 191, 0, 0.15);
            border: 1px solid rgba(255, 191, 0, 0.3);
        }

        .log {
            position: relative;
            height: calc(100% - 48px);
            overflow-y: auto;
            /*background-color: #FAFAFA;*/
            background-color: white;
        }

        .count {
            padding: 0 5px;
        }

        .count > span {
            color: black;
        }

        .uploadbar {
            position: relative;
            height: 18px;
            width: 100px;
            background-color: var(--light-primary-color);
            line-height: 18px;
            border: 1px solid var(--divider-color);
        }

        .uploadprogress {
            position: absolute;
            top: 0px;
            left: 0px;
            height: 100%;
            width: 100%;
            background-color: var(--hover-color);
            /*margin-top: 10px;*/
        }

        .uploadtext {
            position: absolute;
            text-align: center;
            top: 0px;
            left: 0px;
            height: 100%;
            width: 100%;
        }

        .header > div {
            padding-left: 2px;
        }

        .wrapped-text {
            white-space: pre-wrap;
            padding: 10px;
            overflow-y: auto;
            min-width: 400px;
            min-height: 150px;
        }

        #linePreview {
            width: 300px;
            background-color: var(--light-primary-color);
            height: 50px;

        }
    </style>
    <template>

        <div id="header" class="horizontal layout center">
            <div class="line">Line </div>
            <div class="type">Type</div>
            <div class="msg">Message</div>
            <div class="flex"></div>
            <div class="uploadbar" hidden$="{{!uploading}}">
                <div id="progressBar" class="uploadprogress"></div>
                <div class="uploadtext">
                    <i id="spin" hidden$="{{computeSpin(progress)}}" class="fa fa-spinner fa-spin"></i>
                    <span>{{progress}}</span> %
                </div>
                <br>
            </div>
            <div id="stop" class="jso-btn jso-btn-shdw" on-click="handleStop">Stop</div>
        </div>
        <iron-list class="log" items="{{logIron}}" as="item">
            <template>
                <div class="horizontal layout center item" type$="{{item.type}}">
                    <div class="line">{{item.line}}</div>
                    <div class="type" type$="{{item.type}}">{{item.type}}</div>
                    <div class="msg flex">{{item.msg}}</div>
                    <div class="view" line="{{item.line}}" column="{{item.column}}" on-click="handleLogViewClick" title="View line"><i class="fa fa-search"></i></div>
                </div>
            </template>
        </iron-list>

        <div id="footer" class="counts horizontal layout center">
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="error" data-checked$="{{computeView(view, 'error')}}">
                <div class="error-count count">Errors:
                    <span>{{errorCount}}</span>
                </div>
            </div>
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="warning" data-checked$="{{computeView(view, 'warning')}}">
                <div class="warning-count count">Warning:
                    <span>{{warningCount}}</span>
                </div>
            </div>
            <div class="jso-btn jso-btn-shdw but" on-click="handleView" data-value="info" data-checked$="{{computeView(view, 'info')}}">
                <div class="info-count count">Info:
                    <span>{{infoCount}}</span>
                </div>
            </div>
            <div class="flex"></div>
            <div class="count">Lines:
                <span>{{numLines}}</span>
            </div>
        </div>

        <jso-panel modal movable closable hidden id="linePreviewPanel" on-close="handleCloseLinePreview">
            <div class="header">
                <i class="fa fa-view"></i> &nbsp; View line
            </div>
            <div class="container wrapped-text">{{linePreview}}</div>
        </jso-panel>


    </template>

    <script>
        Polymer({
            is: "jso-validator",
            properties: {
                file: {
                    type: Object,
                    value: function() {
                        return null;
                    },
                    observer: 'fileChanged'
                },
                validator: {
                    type: Object,
                    value: function() {
                        return new Validator({});
                    },
                    observer: 'validatorChanged'
                },
                logIron: {
                    type: Array
                },
                log: {
                    type: Object,
                    value: function() {
                        return {
                            error: [],
                            warning: [],
                            info: []
                        }
                    }
                },
                errorCount: {
                    type: Number,
                    value: 0
                },
                warningCount: {
                    type: Number,
                    value: 0
                },
                infoCount: {
                    type: Number,
                    value: 0
                },
                numLines: {
                    type: Number,
                    value: 0
                },
                progress: {
                    type: Number,
                    value: 0,
                    observer: 'progressChanged'
                },
                view: {
                    type: String,
                    value: 'error'
                },
            },
            ready: function() {
                this.set("logIron", this.log[this.view]);
            },
            handleView: function(e) {
                this.view = e.currentTarget.dataset.value;
                this.set("logIron", this.log[this.view]);
            },
            computeView: function(view, value) {
                return view === value;
            },
            reset: function() {
                this.progress = 0;
                this.set("log", {
                    error: [],
                    warning: [],
                    info: []
                });
                this.set("logIron", this.log[this.view]);
                this.errorCount = 0;
                this.warningCount = 0;
                this.infoCount = 0;
                this.numLines = 0;
                if (this.validator) {
                    this.validator.init();
                }
                this.setFile();
            },
            validate: function() {
                this.set("log", {
                    error: [],
                    warning: [],
                    info: []
                });
                this.set("logIron", this.log[this.view]);
                this.errorCount = 0;
                this.warningCount = 0;
                this.infoCount = 0;
                this.numLines = 0;
                this.validator.validate();
            },
            handleStop: function(e) {
                this.stop();
            },
            stop: function() {
                if (this.validator) {
                    this.validator.stop();
                }
            },
            setFile: function(file) {
                this.fileChanged(file);
            },
            validatorChanged: function(neo, old) {
                var me = this;
                neo.on("end", function(e) {
                    me.numLines = me.validator.numLines;
                    me.fire("end");
                });

                neo.on("err", function(e) {
                    me.fire("err");
                });

                neo.on("stop", function(e) {
                    me.$.spin.setAttribute('hidden', '');
                    me.fire("stop");
                });

                neo.on("log", function(e) {
                    switch (e.type) {
                        case "error":
                            me.errorCount++;
                            if (me.errorCount == 100) {
                                me.stop();
                                alert('File has more than 100 errors, the validation is stopped');
                            }
                            break;
                        case "warning":
                            me.warningCount++;
                            break;
                    }
                    if (me.log[e.type] == me.logIron) {
                        me.push("logIron", e);
                    } else {
                        me.push('log.' + e.type, e);
                    }
                });

                neo.on("lines", function(e) {
                    me.set('numLines', e);
                });

                neo.on("progress", function(e) {
                    me.set('progress', Math.ceil(e));
                });

                neo.init();

            },
            fileChanged: function(neo, old) {
                if (neo && this.validator) {
                    this.validator.init();
                    this.validator.file = neo;
                }
            },
            computeLog: function(validator) {
                if (validator) {
                    return validator.log;
                } else {
                    return [];
                }
            },
            progressChanged: function(neo, old) {
                // console.log("progress : " + neo);
                this.$.progressBar.style.width = neo + '%';
            },
            computeSpin: function(progress) {
                return progress >= 100 || progress <= 0;
            },
            handleLogViewClick: function(e) {
                var me = this;
                var elem = e.currentTarget;
                var line = elem.line - 1;
                this.column = elem.column;
                this.validator._navigator.readLines(line, 1, function linesReadHandler(err, index, lines, eof, progress) {
                    if (err) {
                        return;
                    }

                    if (lines.length > 0) {
                        var aux = lines[0].split("\t");
                        aux[me.column] = '<span style="color:red">' + aux[me.column] + '</span>';
                        me.linePreview = lines[0];
                        me.$.linePreviewPanel.hidden=false;
                    }

                    if (eof) {
                        return;
                    }

                });
            },
            handleCloseLinePreview: function(e) {
                e.stopPropagation();
                this.linePreview = "";
            }
        })
    </script>
</dom-module>

{'fraction_non_alphanumeric': 0.13516098182977368, 'fraction_numerical': 0.011121736974462509, 'mean_word_length': 1.0152748037116346, 'pattern_counts': {'":': 4, '<': 205, '<?xml version=': 0, '>': 217, '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': '5984581', 'n_tokens_mistral': 7799, 'n_tokens_neox': 7021, 'n_words': 1370}