Asymmetrik/mean2-starter

View on GitHub
src/client/app/teams/select-teams.component.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { Component, Output, EventEmitter, Input } from '@angular/core';

import * as _ from 'lodash';
import { Observable } from 'rxjs';

import { ObservableUtils } from '../shared/observable-utils.class';
import { TagsService } from './tags/tags.service';
import { TeamsService } from './teams.service';
import { TeamMember, Team } from './teams.class';
import { Tag } from './tags/tags.class';
import { PagingOptions } from '../shared/pager.component';

@Component({
    selector: 'select-teams',
    templateUrl: './select-teams.component.html'
})
export class SelectTeamsComponent {

    @Input() showTags: boolean = true;

    @Output() alertError = new EventEmitter();

    @Output() setSelection = new EventEmitter();

    user: TeamMember;

    // Tag filter variables
    allTagOption: Tag = new Tag('All', 'All Tags');

    selectedTag: Tag = this.allTagOption;

    preselectedTag: Tag;

    tagOptions: Tag[] = [];

    // Team filter variables
    allTeamOption: Team = new Team('All', 'All Teams');

    selectedTeam: Team = this.allTeamOption;

    preselectedTeam: Team;

    teamOptions: Team[] = [];

    constructor(
        public tagsService: TagsService,
        public teamsService: TeamsService
    ) {
    }

    ngOnInit() {
        // Get current user info in order to access permissions
        this.user = this.teamsService.getCurrentUserAsTeamMember();

        ObservableUtils.wrapArray([
            this.initializeTeams(), this.initializeTags(), this.handleSelection()
        ]).subscribe(() => {}, (err: any) => { this.alertError.emit(err); });
    }

    /**
     * Allows parent components to set pre-selected teams and tags
     */
    setSelectionInput(tag: Tag, team: Team) {
        this.preselectedTeam = team;
        this.preselectedTag = tag;
    }

    sortByName(a: any, b: any) {
        let aname = a.name.toUpperCase();
        let bname = b.name.toUpperCase();

        if (aname === bname) {
            return 0;
        }

        return (aname < bname) ? -1 : 1;
    }

    /**
     * Populates the team option dropdown depending on the user's role
     * If the user is a system admin, show all teams in the system.
     * If user is not an admin, only show teams that the user belongs to
     */
    initializeTeams() {
        return Observable.create((observer: any) => {
            this.teamsService.selectionList()
                .subscribe(
                    (result: any) => {
                        let results = (_.isArray(result)) ? result : result.elements;
                        if (_.isArray(results)) {
                            this.teamOptions = results.map((r: any) => new Team(r._id, r.name)).sort(this.sortByName);
                        }

                        observer.complete();
                    },
                    (err: any) => {
                        observer.error(err);
                    });
        });
    }

    initializeTags() {
        return Observable.create((observer: any) => {
            if (!this.showTags) {
                observer.complete();
            }
            else {
                this.tagsService.selectionList()
                    .subscribe(
                        (result: any) => {
                            this.populateTagOptions(result);
                            observer.complete();
                        },
                        (err: any) => {
                            observer.error(err);
                        }
                    );
            }
        });
    }

    handleSelection() {
        if (null != this.preselectedTeam) {
            this.applyTeamFilter(this.preselectedTeam, false);
        }
        return Observable.empty();
    }

    populateTagOptions(result: any) {
        // Default to preselected tag or all tags
        this.selectedTag = (null != this.preselectedTag) ? this.preselectedTag : this.allTagOption;

        if (null != result && null != result.elements && result.elements.length > 0) {
            this.tagOptions = result.elements.map((r: any) => new Tag(r._id, r.name)).sort(this.sortByName);
        }
        else {
            this.tagOptions = [];
        }
    }

    /**
     * Helper functions for team and tag filtering
     */
    getTagsForTeam(t: Team) {
        return Observable.create((observer: any) => {
            // Get all tags or get tags for selected team
            let obs: Observable<any>;
            if (t._id === this.allTeamOption._id) {
                obs = this.tagsService.selectionList();
            }
            else {
                obs = this.tagsService.searchTags({ owner: { $in: [t._id] } }, null, new PagingOptions(0, 1000), {});
            }

            obs.subscribe(
                (result: any) => {
                    this.populateTagOptions(result);
                    observer.next();
                },
                (err: any) => {
                    this.tagOptions = [];
                    observer.error(err);
                },
                () => {
                    observer.complete();
                });
        });
    }

    applyTeamFilter(t: Team, update: boolean = true) {
        if (update) {
            this.preselectedTag = null;
        }

        // Check that filter actually changed
        if (t._id !== this.selectedTeam._id) {
            this.selectedTeam = t;
            this.getTagsForTeam(t)
                .subscribe(
                    () => {
                        if (update) {
                            this.updateSelection();
                        }
                    },
                    (err: any) => {
                        this.alertError.emit(err);
                    });
        }
    }

    applyTagFilter(t: Tag) {
        // Check that the filter actually changed
        if (t._id !== this.selectedTag._id) {
            this.selectedTag = t;

            this.updateSelection();
        }
    }

    updateSelection() {
        let team = (this.selectedTeam._id === this.allTeamOption._id) ? null : this.selectedTeam;
        let tag = (this.selectedTag._id === this.allTagOption._id) ? null : this.selectedTag;

        this.setSelection.emit({tag: tag, team: team});
    }
}