<commit_before>module KanbanColumn {
    export interface IKanbanColumnScope extends ng.IScope {
        vm: KanbanColumnCtrl;
        column: Column;
        columnFilter: Function;
        columnOrderTitle: string;
        columnOrderBy: string;
        query: string;
        fields: any;
    }

    export class ColumnFilter {
        layerIds: string[];
        prio: number;
        roles: string[];
        tags: string[];
    }

    export class Column {
        filters: ColumnFilter;
        fields: any;
        orderBy: string;
        actions: string[];
    }

    declare var _;

    export class KanbanColumnCtrl {
        public scope: IKanbanColumnScope;
        public column: Column;

        // $inject annotation.
        // It provides $injector with information about dependencies to be injected into constructor
        // it is better to have it close to the constructor, because the parameters must match in count and type.
        // See http://docs.angularjs.org/guide/di
        public static $inject = [
            '$scope',
            'layerService',
            'messageBusService',
            'mapService'
        ];

        public sortOptions = [];

        // dependencies are injected via AngularJS $injector
        // controller's name is registered in Application.ts and specified from ng-controller attribute in index.html
        constructor(
            private $scope: IKanbanColumnScope,
            private $layerService: csComp.Services.LayerService,
            private $messageBus: csComp.Services.MessageBusService,
            private mapService: csComp.Services.MapService
            ) {
            $scope.vm = this;

            //var par = <any>$scope.$parent;
            //this.kanban = par.widget.data;
            this.column = $scope.column;
            $scope.fields = this.column.fields;

            if ($scope.fields.hasOwnProperty('prio')) this.sortOptions = this.sortOptions.concat(['High priority', 'Low Priority']);
            if ($scope.fields.hasOwnProperty('date')) this.sortOptions = this.sortOptions.concat(['New', 'Old']);
            this.sortOptions = this.sortOptions.concat(['Title']);

            // check if layers should be enabled
            this.initLayers();

            if (this.column.orderBy)
                this.setOrder(this.column.orderBy)
            else
                this.setOrder(this.sortOptions[0]);

            $scope.columnFilter = (feature: csComp.Services.IFeature) => {
                var result = true;
                if (!$scope.column) return false;
                if (this.column.filters.roles && feature.properties.hasOwnProperty('roles')) {
                    this.column.filters.roles.forEach((r: string) => {
                        if (!_.contains(feature.properties['roles'], r)) result = false;
                    });
                }
                if (result && !_.contains(this.column.filters.layerIds, feature.layerId)) return false;
                if (result && this.column.filters.tags) {
                    if (!feature.properties.hasOwnProperty('tags')) return false;
                    this.column.filters.tags.forEach((tag: string) => {
                        if (tag[0] === "!") {
                            var t = tag.slice(1, tag.length);
                            if (_.contains(feature.properties['tags'], t)) result = false;
                        }
                        else if (!_.contains(feature.properties['tags'], tag)) result = false;
                        return;
                    })
                }
                return result;
            }
            setInterval(() => { this.updateTime() }, 1000);
        }

        public clickPrio($event) {


            // var dropdown: any = $($event.target, "> ul");
            // dropdown.css('top', angular.element($event.target).prop('offsetLeft') + "px");
            // dropdown.css('left', angular.element($event.target).prop('offsetTop') + "px");

        }

        public createForm(feature: csComp.Services.IFeature) {
            if (this.$layerService.lockFeature(feature)) {
                feature.gui["questions"] = [];
                feature.properties[this.column.fields['question']].forEach((s: string) => {
                    feature.gui["questions"].push(s);
                });
            }
        }

        public sendForm(feature: csComp.Services.IFeature) {
            feature.properties["answered"] = true;
            delete feature.gui["questions"];
            this.$layerService.unlockFeature(feature);
            this.$layerService.saveFeature(feature, true);

        }

        public updateTime() {
            this.$layerService.project.features.forEach((feature: csComp.Services.IFeature) => {
                if (feature.properties.hasOwnProperty('date')) {

                    var d = feature.properties['date'];
                    if (!feature.hasOwnProperty('gui')) feature.gui = new Object;
                    feature.gui['relativeTime'] = moment(d).fromNow();
                }
                return "";
            })
        }

        public logFilter(feature: csComp.Services.IFeature) {

        }

        public startAction(action: string, feature: csComp.Services.IFeature) {
            this.$messageBus.publish("kanbanaction", action, feature);
        }

        public getPrioColor(feature: csComp.Services.IFeature) {
            var colors = ["white", "black", "red", "orange", "blue", "green"];
            if (feature.properties.hasOwnProperty(this.column.fields['prio']))
                return {
                    "background-color": colors[parseInt(feature.properties[this.column.fields['prio']])]
                }
            return {};
        }

        public setOrder(order: string) {
            this.$scope.columnOrderTitle = order;
            this.column.orderBy = order;
            switch (order) {
                case 'High priority': this.$scope.columnOrderBy = "properties." + this.$scope.fields['prio']; break;
                case 'Low Priority': this.$scope.columnOrderBy = "-properties." + this.$scope.fields['prio']; break;
                case 'New': this.$scope.columnOrderBy = "properties." + this.$scope.fields['date']; break;
                case 'Old': this.$scope.columnOrderBy = "-properties." + this.$scope.fields['date']; break;
                case 'Title': this.$scope.columnOrderBy = "properties." + this.$scope.fields['title']; break;
            }
        }

        public updateFeature(feature: csComp.Services.Feature) {
            this.$layerService.saveFeature(feature, true);
        }

        selectFeature(feature: csComp.Services.IFeature) {
            this.$layerService.selectFeature(feature);
        }

        editFeature(feature: csComp.Services.IFeature) {<commit_msg>kanban: Fix for reverse sort order<commit_after>module KanbanColumn {
    export interface IKanbanColumnScope extends ng.IScope {
        vm: KanbanColumnCtrl;
        column: Column;
        columnFilter: Function;
        columnOrderTitle: string;
        columnOrderBy: string;
        query: string;
        fields: any;
    }

    export class ColumnFilter {
        layerIds: string[];
        prio: number;
        roles: string[];
        tags: string[];
    }

    export class Column {
        filters: ColumnFilter;
        fields: any;
        orderBy: string;
        actions: string[];
    }

    declare var _;

    export class KanbanColumnCtrl {
        public scope: IKanbanColumnScope;
        public column: Column;

        // $inject annotation.
        // It provides $injector with information about dependencies to be injected into constructor
        // it is better to have it close to the constructor, because the parameters must match in count and type.
        // See http://docs.angularjs.org/guide/di
        public static $inject = [
            '$scope',
            'layerService',
            'messageBusService',
            'mapService'
        ];

        public sortOptions = [];

        // dependencies are injected via AngularJS $injector
        // controller's name is registered in Application.ts and specified from ng-controller attribute in index.html
        constructor(
            private $scope: IKanbanColumnScope,
            private $layerService: csComp.Services.LayerService,
            private $messageBus: csComp.Services.MessageBusService,
            private mapService: csComp.Services.MapService
            ) {
            $scope.vm = this;

            //var par = <any>$scope.$parent;
            //this.kanban = par.widget.data;
            this.column = $scope.column;
            $scope.fields = this.column.fields;

            if ($scope.fields.hasOwnProperty('prio')) this.sortOptions = this.sortOptions.concat(['High priority', 'Low Priority']);
            if ($scope.fields.hasOwnProperty('date')) this.sortOptions = this.sortOptions.concat(['New', 'Old']);
            this.sortOptions = this.sortOptions.concat(['Title']);

            // check if layers should be enabled
            this.initLayers();

            if (this.column.orderBy)
                this.setOrder(this.column.orderBy)
            else
                this.setOrder(this.sortOptions[0]);

            $scope.columnFilter = (feature: csComp.Services.IFeature) => {
                var result = true;
                if (!$scope.column) return false;
                if (this.column.filters.roles && feature.properties.hasOwnProperty('roles')) {
                    this.column.filters.roles.forEach((r: string) => {
                        if (!_.contains(feature.properties['roles'], r)) result = false;
                    });
                }
                if (result && !_.contains(this.column.filters.layerIds, feature.layerId)) return false;
                if (result && this.column.filters.tags) {
                    if (!feature.properties.hasOwnProperty('tags')) return false;
                    this.column.filters.tags.forEach((tag: string) => {
                        if (tag[0] === "!") {
                            var t = tag.slice(1, tag.length);
                            if (_.contains(feature.properties['tags'], t)) result = false;
                        }
                        else if (!_.contains(feature.properties['tags'], tag)) result = false;
                        return;
                    })
                }
                return result;
            }
            setInterval(() => { this.updateTime() }, 1000);
        }

        public clickPrio($event) {


            // var dropdown: any = $($event.target, "> ul");
            // dropdown.css('top', angular.element($event.target).prop('offsetLeft') + "px");
            // dropdown.css('left', angular.element($event.target).prop('offsetTop') + "px");

        }

        public createForm(feature: csComp.Services.IFeature) {
            if (this.$layerService.lockFeature(feature)) {
                feature.gui["questions"] = [];
                feature.properties[this.column.fields['question']].forEach((s: string) => {
                    feature.gui["questions"].push(s);
                });
            }
        }

        public sendForm(feature: csComp.Services.IFeature) {
            feature.properties["answered"] = true;
            delete feature.gui["questions"];
            this.$layerService.unlockFeature(feature);
            this.$layerService.saveFeature(feature, true);

        }

        public updateTime() {
            this.$layerService.project.features.forEach((feature: csComp.Services.IFeature) => {
                if (feature.properties.hasOwnProperty('date')) {

                    var d = feature.properties['date'];
                    if (!feature.hasOwnProperty('gui')) feature.gui = new Object;
                    feature.gui['relativeTime'] = moment(d).fromNow();
                }
                return "";
            })
        }

        public logFilter(feature: csComp.Services.IFeature) {

        }

        public startAction(action: string, feature: csComp.Services.IFeature) {
            this.$messageBus.publish("kanbanaction", action, feature);
        }

        public getPrioColor(feature: csComp.Services.IFeature) {
            var colors = ["white", "black", "red", "orange", "blue", "green"];
            if (feature.properties.hasOwnProperty(this.column.fields['prio']))
                return {
                    "background-color": colors[parseInt(feature.properties[this.column.fields['prio']])]
                }
            return {};
        }

        public setOrder(order: string) {
            this.$scope.columnOrderTitle = order;
            this.column.orderBy = order;
            switch (order) {
                case 'High priority': this.$scope.columnOrderBy = "properties." + this.$scope.fields['prio']; break;
                case 'Low Priority': this.$scope.columnOrderBy = "-properties." + this.$scope.fields['prio']; break;
                case 'New': this.$scope.columnOrderBy = "-properties." + this.$scope.fields['date']; break;
                case 'Old': this.$scope.columnOrderBy = "properties." + this.$scope.fields['date']; break;
                case 'Title': this.$scope.columnOrderBy = "properties." + this.$scope.fields['title']; break;
            }
        }

        public updateFeature(feature: csComp.Services.Feature) {
            this.$layerService.saveFeature(feature, true);
        }

        selectFeature(feature: csComp.Services.IFeature) {
            this.$layerService.selectFeature(feature);
        }

        editFeature(feature: csComp.Services.IFeature) {
{'fraction_non_alphanumeric': 0.12585108719525587, 'fraction_numerical': 0.0010249652243941724, 'mean_word_length': 1.8188196450680973, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4885500', 'n_tokens_mistral': 3520, 'n_tokens_neox': 3359, 'n_words': 711}