function controller()

in ui-modules/app-inspector/app/components/task-list/task-list.directive.js [54:299]


    function controller($scope, $element) {
        const isActivityChildren = !! $scope.parentTaskId;

        // selected filters are shared with other views esp kilt view so they can see what is and isn't included.
        // currently only used for transient.
        $scope.globalFilters = {
            // transient set when those tags seen
        };

        $scope.isEmpty = x => _.isNil(x) || x.length==0 || (typeof x === "object" && Object.keys(x).length==0);
        $scope.model = {
            appendTo: $element,
            filterResult: null,
        };
        $scope.tasksFilteredByTag = [];

        $scope.findTasksExcludingCategory = (tasks, selected, categoryToExclude) => {
            let result = tasks || [];

            if (selected) {
                _.uniq(Object.values(selected).map(f => f.categoryForEvaluation || f.category)).forEach(category => {
                    if (categoryToExclude === '' || categoryToExclude != category) {
                        let newResult = [];
                        if ($scope.filters.startingSetFilterForCategory[category]) {
                            newResult = $scope.filters.startingSetFilterForCategory[category](result);
                        }
                        Object.values(selected).filter(f => (f.categoryForEvaluation || f.category) === category).forEach(f => {
                            const filter = f.filter;
                            if (!filter) {
                                console.warn("Incomplete activities tag filter", f);
                            } else {
                                newResult = newResult.concat(filter(result));
                            }
                        });

                        // limit result, but preserving order
                        newResult = newResult.map(t => t.id);
                        result = result.filter(t => newResult.includes(t.id));
                    }
                })
            }
            return result;
        };
        $scope.recomputeTasks = () => {
            $scope.tasksFilteredByTag = $scope.findTasksExcludingCategory(
                    tasksAfterGlobalFilters($scope.tasks, $scope.globalFilters),
                    $scope.filters.selectedFilters, '')
                .sort((t1,t2) => {
                    if (!t1.endTimeUtc || !t2.endTimeUtc) {
                        if (!t1.endTimeUtc && !t2.endTimeUtc) return t2.startTimeUtc - t1.startTimeUtc;
                        if (t1.endTimeUtc) return 1;
                        return -1;
                    }
                    return t2.endTimeUtc - t1.endTimeUtc ||
                        // if same end time, sort by start time
                        (t2.startTimeUtc && t1.startTimeUtc && t2.startTimeUtc - t1.startTimeUtc) ||
                        (t2.submitTimeUtc && t1.submitTimeUtc && t2.submitTimeUtc - t1.submitTimeUtc);
                });

            // do this to update the counts
            setFiltersForTasks($scope, isActivityChildren);

            // now update name
            const enabledCategories = _.uniq(Object.values($scope.filters.selectedFilters).map(f => f.category));
            $scope.filters.selectedDisplay = [];
            Object.entries($scope.filters.displayNameFunctionForCategory).forEach(([category, nf]) => {
                if (!enabledCategories.includes(category)) return null;
                let badges = nf ? nf(Object.values($scope.filters.selectedFilters).filter(f => (f.categoryForBadges || f.category) === category)) : null;
                badges = (badges || []).filter(x=>x);
                if (badges.length) $scope.filters.selectedDisplay.push({ class: 'dropdown-category-'+category, badges });
            });
            if (!$scope.filters.selectedDisplay.length) $scope.filters.selectedDisplay.push({ class: 'dropdown-category-default', badges: ['all'] });
        };

        function selectFilter(filterId, explicitNewValueOrUndefinedForToggle) {
            //console.debug("selecting filter: "+filterId+" = "+explicitNewValueOrUndefinedForToggle);
            const f = $scope.filters.available[filterId];
            if (!f) {
                //console.debug("selected filter not found; available are", $scope.filters.available);
                // we tried to select eg effector, when it didn't exist, just ignore
                return false;
            } else {
                f.select(filterId, f, explicitNewValueOrUndefinedForToggle); // see defaultToggleFilter for params
                return true;
            }
        }
        $scope.clickFilter = (filter, tag) => {
            filter.onClick(tag, filter);
            if ($scope.contextKey) {
                try {
                    const filters = JSON.stringify(Object.keys($scope.filters.selectedFilters));
                    const storageKey = 'brooklyn-task-list-filters-' + $scope.contextKey;
                    sessionStorage.setItem(storageKey, filters);
                    //console.debug("Saved filters to session storage", storageKey, filters);
                } catch (e) {
                    console.warn("Unable to save filiters from session storage for", $scope.contextKey, e);
                }
            }
        }

        $scope.filterValue = $scope.search;

        $scope.isScheduled = isScheduled;

        function roundChangingMillis(x) {
            if (x<100) return "-";
            if (x<1000) return Math.round(x/100)*100;
            return Math.round(x/1000)*1000;
        }

        $scope.getTaskDuration = function(task) {
            if (!task.startTimeUtc) {
                return null;
            }
            if (!_.isNil(task.endTimeUtc) && task.endTimeUtc <= 0) return null;
            return (task.endTimeUtc === null ? roundChangingMillis(new Date().getTime() - task.startTimeUtc) : task.endTimeUtc - task.startTimeUtc);
        }
        $scope.getTaskWorkflowId = task => {
            const tag = getTaskWorkflowTag(task);
            if (tag) return tag.workflowId;
            return null;
        };

        $scope.$watch('model.filterResult', function () {
            if ($scope.filteredCallback && $scope.model.filterResult) $scope.filteredCallback()( $scope.model.filterResult, $scope.globalFilters );
        });

        let tasksLoadedTrueReceived = false;
        let filtersFromSessionStorage = 'initializing';  // | 'absent' | 'loaded'

        $scope.resetFilters = () => {
            tasksLoadedTrueReceived = false;
            $scope.uiDropdownInteraction = false;
            filtersFromSessionStorage = 'initializing';
            sessionStorage.removeItem('brooklyn-task-list-filters-' + $scope.contextKey)
            refreshDropdownsUntilTasksAreLoaded();
        }

        function refreshDropdownsUntilTasksAreLoaded() {
            if (tasksLoadedTrueReceived || $scope.uiDropdownInteraction) return;
            tasksLoadedTrueReceived = $scope.tasksLoaded;

            let preselectedFilters;
            if (filtersFromSessionStorage=='initializing') {
                if (!$scope.contextKey) filtersFromSessionStorage = 'absent';
                else {
                    filtersFromSessionStorage = 'absent';
                    try {
                        const filters = sessionStorage.getItem('brooklyn-task-list-filters-' + $scope.contextKey);
                        if (filters) {
                            // console.debug("Read filters for", $scope.contextKey, filters);
                            preselectedFilters = JSON.parse(filters);
                        }
                    } catch (e) {
                        console.warn("Unable to load filiters from session storage for", $scope.contextKey, e);
                    }
                }
            }
            if (filtersFromSessionStorage=='loaded') {
                // don't auto-compute if taken from session storage
            } else {

                $scope.filters = {available: {}, selectedFilters: {}};
                setFiltersForTasks($scope, isActivityChildren);

                if (preselectedFilters) {
                    try {
                        if ($scope.selectedFilters) Object.entries($scope.selectedFilters, (k,v) => selectFilter(k, v, false));

                        $scope.selectedFilters = {};
                        preselectedFilters.forEach(fid => {
                            const f = $scope.filters.available[fid];
                            if (!f) {
                                // don't keep retrying the load, unless tasks aren't loaded yet
                                if (!$scope.tasksLoaded) {
                                    filtersFromSessionStorage = 'initializing';  // we don't have all the filters yet
                                }
                            } else {
                                selectFilter(fid, f, true);
                            }
                        });
                        filtersFromSessionStorage = 'loaded';
                    } catch (e) {
                        filtersFromSessionStorage = 'absent';
                        console.warn("Unable to process filiters from session storage for", $scope.contextKey, preselectedFilters, e);
                    }
                }

                if (filtersFromSessionStorage == 'absent') {

                    selectFilter("_top", true);
                    selectFilter("_anyTypeTag", true);
                    if ($scope.taskType) {
                        if ($scope.taskType == "ALL") {
                            selectFilter("_top", false);
                        } else {
                            selectFilter($scope.taskType);
                        }
                    } else {
                        selectFilter('_cross_entity');
                        selectFilter('_all_effectors');
                        selectFilter('TOP-LEVEL');
                        selectFilter('EFFECTOR');
                        selectFilter('WORKFLOW');
                        selectFilter('_periodic');
                        selectFilter('_other_entity');

                        if (isActivityChildren) {
                            // in children mode we also want sub-tasks
                            // (previously selected no filters in subtask view)
                            selectFilter('SUB-TASK');
                        }
                    }
                    if (!isActivityChildren) selectFilter("_workflowStepsHidden");
                    selectFilter("_workflowReplayedTopLevel");
                    selectFilter("_workflowNonLastReplayHidden");
                    selectFilter("_workflowCompletedWithoutTaskHidden");

                    // pick other filter combos until we get some conetnt
                    if ($scope.tasksFilteredByTag.length == 0) {
                        selectFilter('INITIALIZATION');
                    }
                    if ($scope.tasksFilteredByTag.length == 0) {
                        selectFilter("_anyTypeTag", true);
                    }
                    if (!isActivityChildren && $scope.tasksFilteredByTag.length == 0) {
                        selectFilter("_top", false);
                    }
                }
            }

            $scope.recomputeTasks();
        }

        $scope.$watch('tasks', ()=>{
            $scope.recomputeTasks();
        });
        $scope.$watch('globalFilters', ()=>{
            $scope.recomputeTasks();
        });

        $scope.$watch('tasksLoaded', v => {
            refreshDropdownsUntilTasksAreLoaded();
        });
        refreshDropdownsUntilTasksAreLoaded();
    }