File

src/app/category-list/category-list-page.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods

Constructor

constructor(contentService: ContentService, formService: FormService, courseService: CourseService, profileService: ProfileService, commonUtilService: CommonUtilService, router: Router, appHeaderService: AppHeaderService, navService: NavigationService, telemetryGeneratorService: TelemetryGeneratorService, scrollService: ScrollToService, searchFilterService: SearchFilterService, modalController: ModalController)
Parameters :
Name Type Optional
contentService ContentService No
formService FormService No
courseService CourseService No
profileService ProfileService No
commonUtilService CommonUtilService No
router Router No
appHeaderService AppHeaderService No
navService NavigationService No
telemetryGeneratorService TelemetryGeneratorService No
scrollService ScrollToService No
searchFilterService SearchFilterService No
modalController ModalController No

Methods

Private Async applyFilter
applyFilter(appliedFilterCriteria: ContentSearchCriteria, refreshPillFilter, onSelectedFilter?, filterKey?)
Parameters :
Name Type Optional Default value
appliedFilterCriteria ContentSearchCriteria No
refreshPillFilter No true
onSelectedFilter Yes
filterKey Yes
Returns : any
deduceFilterCriteria
deduceFilterCriteria(isDataEmpty?)
Parameters :
Name Optional
isDataEmpty Yes
Private Async fetchAndSortData
fetchAndSortData(searchCriteria, isInitialCall: boolean, refreshPillFilter, onSelectedFilter?: any, filterKey?)
Parameters :
Name Type Optional Default value
searchCriteria No
isInitialCall boolean No
refreshPillFilter No true
onSelectedFilter any Yes
filterKey Yes
Returns : any
Private generateImpressionTelemetry
generateImpressionTelemetry()
Returns : void
getExistingFilters
getExistingFilters(formFields)
Parameters :
Name Optional
formFields No
Returns : {}
Async ionViewWillEnter
ionViewWillEnter()
Returns : any
navigateToDetailPage
navigateToDetailPage(event, sectionName)
Parameters :
Name Optional
event No
sectionName No
Returns : void
Async navigateToFilterFormPage
navigateToFilterFormPage()
Returns : any
navigateToViewMorePage
navigateToViewMorePage(items, subject, totalCount)
Parameters :
Name Optional
items No
subject No
totalCount No
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
Async ngOnInit
ngOnInit()
Returns : any
Async onPrimaryFacetFilterSelect
onPrimaryFacetFilterSelect(primaryFacetFilter: literal type, toApply: FilterValue[])
Parameters :
Name Type Optional
primaryFacetFilter literal type No
toApply FilterValue[] No
Returns : any
Async pillFilterHandler
pillFilterHandler(pill)
Parameters :
Name Optional
pill No
Returns : any
reloadDropdown
reloadDropdown(index, item)
Parameters :
Name Optional
index No
item No
Returns : any
scrollToSection
scrollToSection(id: string)
Parameters :
Name Type Optional
id string No
Returns : void

Properties

appName
Type : string
Default value : ''
categoryDescription
Type : string
Default value : ''
categoryTitle
Type : string
Default value : ''
Public commonUtilService
Type : CommonUtilService
Private corRelationList
Type : []
Default value : []
defaultImage
Type : string
Default value : ''
defaultImg
Type : string
displayFacetFilters
Type : literal type
Default value : {}
Private env
Type : string
Default value : Environment.SEARCH
Private existingSearchFilters
Type : object
Default value : {}
facetFilters
Type : literal type
Default value : {}
Private Readonly filterCriteria
Type : ContentSearchCriteria
filterFields
Type : literal type
Default value : {}
filterIdentifier
Type : any
filterPillList
Type : []
Default value : []
formAPIFacets
formField
Type : literal type
fromLibrary
Default value : false
Private fromPage
Type : string
Default value : PageId.SEARCH
Public imageSrcMap
Default value : new Map()
Optional initialFacetFilters
Type : literal type
Private initialFilterCriteria
Type : ContentSearchCriteria
layoutConfiguration
Type : object
Default value : { layout: 'v4' }
Private pageId
Type : string
Default value : PageId.CATEGORY_RESULTS
PillBorder
Default value : PillBorder
Private preFetchedFilterCriteria
Type : ContentSearchCriteria
primaryFacetFilters
Type : literal type[]
primaryFacetFiltersFormGroup
Type : FormGroup
primaryFacetFiltersTemplateOptions
Type : object
Default value : { cssClass: 'select-box' }
profile
Type : Profile
Private resentFilterCriteria
Type : ContentSearchCriteria
Private Readonly searchCriteria
Type : ContentSearchCriteria
sectionCode
Type : string
Default value : ''
Optional sectionGroup
Type : ContentsGroupedByPageSection
selectedFilterPill
selectedPillTheme
Type : PillsColorTheme
Default value : { pillBgColor: getComputedStyle(document.querySelector('html')).getPropertyValue('--app-primary'), pillTextColor: getComputedStyle(document.querySelector('html')).getPropertyValue('--app-white') }
Private shouldGenerateImpressionTelemetry
Default value : true
showSheenAnimation
Default value : true
Private subscriptions
Type : Subscription[]
Default value : []
Private Optional supportedFacets
Type : string[]
Private supportedUserTypesConfig
Type : Array<any>
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import {
    AppHeaderService,
    CommonUtilService,
    CorReleationDataType,
    Environment,
    SearchFilterService,
    ImpressionType,
    InteractSubtype,
    InteractType,
    PageId,
    TelemetryGeneratorService
} from '@app/services';
import { Router } from '@angular/router';
import {
    ContentService,
    ContentsGroupedByPageSection,
    CourseService,
    FilterValue,
    FormService,
    ProfileService,
    ContentData,
    ContentSearchCriteria,
    SearchType,
    CorrelationData,
    Profile
} from 'sunbird-sdk';
import { AggregatorConfigField, ContentAggregation } from 'sunbird-sdk/content/handlers/content-aggregator';
import { ContentUtil } from '@app/util/content-util';
import { ProfileConstants, RouterLinks } from '@app/app/app.constant';
import { NavigationService } from '@app/services/navigation-handler.service';
import { ScrollToService } from '@app/services/scroll-to.service';
import { ModalController } from '@ionic/angular';
import { SearchFilterPage } from '@app/app/search-filter/search-filter.page';
import { FormControl, FormGroup } from '@angular/forms';
import { Subscription } from 'rxjs';
import { PillBorder, PillsColorTheme } from '@project-sunbird/common-consumption';
import { ObjectUtil } from '@app/util/object.util';

@Component({
    selector: 'app-category-list-page',
    templateUrl: './category-list-page.html',
    styleUrls: ['./category-list-page.scss'],
})
export class CategoryListPage implements OnInit, OnDestroy {

    sectionGroup?: ContentsGroupedByPageSection;
    formField: {
        facet: string;
        searchCriteria: ContentSearchCriteria;
        aggregate: {
            sortBy?: {
                [field in keyof ContentData]: 'asc' | 'desc';
            }[];
            groupBy?: keyof ContentData;
            groupSortBy?: any
        };
        showNavigationPill?: boolean;
        filterPillBy?: string;
    };
    public imageSrcMap = new Map();
    defaultImg: string;
    showSheenAnimation = true;
    primaryFacetFiltersTemplateOptions = {
        cssClass: 'select-box'
    };
    facetFilters: {
        [code: string]: FilterValue[]
    } = {};
    displayFacetFilters: {
        [code: string]: FilterValue[]
    } = {};
    initialFacetFilters?: {
        [code: string]: FilterValue[]
    };
    primaryFacetFilters: {
        code: string,
        translations: string,
        sort: boolean
    }[];
    fromLibrary = false;
    sectionCode = '';
    primaryFacetFiltersFormGroup: FormGroup;
    filterFields: {[k: string]: any} = {};

    private readonly searchCriteria: ContentSearchCriteria;
    private readonly filterCriteria: ContentSearchCriteria;

    private supportedUserTypesConfig: Array<any>;
    private supportedFacets?: string[];
    private subscriptions: Subscription[] = [];
    layoutConfiguration = {
        layout: 'v4'
    };
    defaultImage = '';
    appName = '';
    categoryDescription = '';
    categoryTitle = '';
    PillBorder = PillBorder;
    filterPillList = [];
    selectedFilterPill;
    selectedPillTheme: PillsColorTheme = {
        pillBgColor: getComputedStyle(document.querySelector('html')).getPropertyValue('--app-primary'),
        pillTextColor: getComputedStyle(document.querySelector('html')).getPropertyValue('--app-white')
    }
    formAPIFacets;

    private shouldGenerateImpressionTelemetry = true;
    private corRelationList = [];
    private pageId: string = PageId.CATEGORY_RESULTS;
    private fromPage: string = PageId.SEARCH;
    private env: string = Environment.SEARCH;
    private initialFilterCriteria: ContentSearchCriteria;
    private resentFilterCriteria: ContentSearchCriteria;
    private preFetchedFilterCriteria: ContentSearchCriteria;
    profile: Profile;
    private existingSearchFilters = {};
    filterIdentifier: any;

    constructor(
        @Inject('CONTENT_SERVICE') private contentService: ContentService,
        @Inject('FORM_SERVICE') private formService: FormService,
        @Inject('COURSE_SERVICE') private courseService: CourseService,
        @Inject('PROFILE_SERVICE') private profileService: ProfileService,
        public commonUtilService: CommonUtilService,
        private router: Router,
        private appHeaderService: AppHeaderService,
        private navService: NavigationService,
        private telemetryGeneratorService: TelemetryGeneratorService,
        private scrollService: ScrollToService,
        private searchFilterService: SearchFilterService,
        private modalController: ModalController
    ) {
        const extrasState = this.router.getCurrentNavigation().extras.state;
        if (extrasState) {
            this.formField = extrasState.formField;
            this.sectionCode = extrasState.code;
            this.searchCriteria = JSON.parse(JSON.stringify(extrasState.formField.searchCriteria));
            if (this.formField && this.formField.facet && this.formField.facet.toLowerCase() === 'course') {
                if (!this.searchCriteria.impliedFiltersMap) {
                    this.searchCriteria.impliedFiltersMap = [];
                }
                this.searchCriteria.impliedFiltersMap = this.searchCriteria.impliedFiltersMap.concat([{
                    'batches.enrollmentType': 'open'
                }, {
                    'batches.status': 1
                }
                ]);
            }
            this.filterIdentifier = extrasState.formField.filterIdentifier;
            this.primaryFacetFilters = extrasState.formField.primaryFacetFilters;
            this.formField.facet = this.formField.facet.replace(/(^\w|\s\w)/g, m => m.toUpperCase());
            this.categoryDescription = extrasState.description || '';
            this.categoryTitle = extrasState.title || '';
            if (this.primaryFacetFilters) {
                this.primaryFacetFiltersFormGroup = this.primaryFacetFilters.reduce<FormGroup>((acc, filter) => {
                    const facetFilterControl = new FormControl();
                    this.subscriptions.push(
                        facetFilterControl.valueChanges.subscribe((v) => {
                            this.onPrimaryFacetFilterSelect(filter, v);
                        })
                    );
                    acc.addControl(filter.code, facetFilterControl);
                    return acc;
                }, new FormGroup({}));
            }
            this.existingSearchFilters = this.getExistingFilters(extrasState.formField);
        }
    }

    async ngOnInit() {
        this.appName = await this.commonUtilService.getAppName();
        if (!this.supportedFacets) {
            this.formAPIFacets = await this.searchFilterService.fetchFacetFilterFormConfig(this.filterIdentifier);
            this.supportedFacets = this.formAPIFacets.reduce((acc, filterConfig) => {
                    acc.push(filterConfig.code);
                    return acc;
                }, []);
        }

        await this.fetchAndSortData({
            ...this.searchCriteria,
            facets: this.supportedFacets,
            searchType: SearchType.SEARCH,
        }, true);
        (await this.commonUtilService.convertFileToBase64('assets/imgs/ic_launcher.png')).subscribe((img) => {
            this.defaultImage = img;
        });
    }

    async ionViewWillEnter() {
        this.appHeaderService.showHeaderWithBackButton();

        const corRelationList: Array<CorrelationData> = [];
        corRelationList.push({ id: this.formField.facet, type: CorReleationDataType.FORM_PAGE });
        this.telemetryGeneratorService.generateImpressionTelemetry(
            ImpressionType.PAGE_LOADED,
            '',
            PageId.CATEGORY_RESULTS,
            Environment.HOME,
            undefined, undefined, undefined, undefined,
            corRelationList
        );
    }

    private async fetchAndSortData(searchCriteria, isInitialCall: boolean, refreshPillFilter = true, onSelectedFilter?: any, filterKey?) {
        this.showSheenAnimation = true;
        this.profile = await this.profileService.getActiveSessionProfile({ requiredFields: ProfileConstants.REQUIRED_FIELDS }).toPromise();
        if (onSelectedFilter) {
            const selectedData = [];
            onSelectedFilter.forEach((selectedFilter) => {
                selectedData.push(selectedFilter.name);
            });
            if (filterKey) {
                this.filterFields = this.filterFields ? this.filterFields : {};
                this.filterFields[filterKey] = selectedData;
            }
            if (this.formField.aggregate && this.formField.aggregate.groupSortBy && this.formField.aggregate.groupSortBy.length) {
                this.formField.aggregate.groupSortBy.forEach((data) => {
                    let applyFilters = [];
                    Object.keys(this.filterFields).forEach((e) => {
                        if (this.filterFields[e].length) {
                            applyFilters = applyFilters.concat(this.filterFields[e]);
                        }
                    });
                    if (data.name && data.name.preference && data.name.preference.length) {
                        data.name.preference.push(selectedData);
                    } else {
                        data.name.preference = selectedData;
                    }
                });
            }
        }

        if (this.profile.subject.length >= 1) {
            if (this.formField.aggregate && this.formField.aggregate.groupSortBy && this.formField.aggregate.groupSortBy.length) {
                this.formField.aggregate.groupSortBy.forEach((sortData) => {
                    if (sortData.name.preference) {
                        sortData.name.preference.push(this.profile.subject);
                    }
                });
            }
        }
        const temp = ((await this.contentService.buildContentAggregator
            (this.formService, this.courseService, this.profileService)
            .aggregate({
                interceptSearchCriteria: () => (searchCriteria),
                userPreferences: {
                    board: this.profile.board,
                    medium: this.profile.medium,
                    gradeLevel: this.profile.grade,
                    subject: this.profile.subject,
                  }
            },
                [], null, [{
                    dataSrc: {
                        type: 'CONTENTS',
                        request: {
                            type: 'POST',
                            path: '/api/content/v1/search',
                            withBearerToken: true
                        },
                        mapping: [{
                            aggregate: this.formField.aggregate
                        }]
                    },
                    sections: [
                        {
                            index: 0,
                            title: this.formField.facet,
                            theme: {}
                        }
                    ],
                } as AggregatorConfigField<'CONTENTS'>]).toPromise()).result);
        (this as any)['filterCriteria'] = temp[0].meta.filterCriteria;

        if(this.filterCriteria && this.filterCriteria.facetFilters){
            this.filterCriteria.facetFilters =
            await this.searchFilterService.reformFilterValues(this.filterCriteria.facetFilters, this.formAPIFacets);
        }

        this.facetFilters = (this.filterCriteria.facetFilters || []).reduce((acc, f) => {
            acc[f.name] = f.values;
            return acc;
        }, {});

        if(this.facetFilters){
            this.displayFacetFilters = JSON.parse(JSON.stringify(this.facetFilters));
        }
        if (isInitialCall) {
            this.initialFilterCriteria = JSON.parse(JSON.stringify(this.filterCriteria));
        }

        if (!this.initialFacetFilters) {
            this.initialFacetFilters = JSON.parse(JSON.stringify(this.facetFilters));
        }

        if (this.primaryFacetFiltersFormGroup) {
            this.primaryFacetFiltersFormGroup.patchValue(
                this.primaryFacetFilters.reduce((acc, p) => {
                    if (p.sort) {
                        this.displayFacetFilters[p.code].sort((a, b) => a.name > b.name && 1 || -1);
                    }
                    acc[p.code] = this.facetFilters[p.code]
                        .filter(v => v.apply)
                        .map(v => {
                            return this.displayFacetFilters[p.code].find(i => (i.name === v.name));
                        });
                    return acc;
                }, {}),
                { emitEvent: false }
            );
        }

        if (this.formField.filterPillBy) {
            if (refreshPillFilter) {
                this.filterPillList = [];
                setTimeout(() => {
                    this.filterPillList = (this.facetFilters[this.formField.filterPillBy] && JSON.parse(JSON.stringify(this.facetFilters[this.formField.filterPillBy]))) || [];
                    if (this.filterPillList.length) {
                        this.preFetchedFilterCriteria = JSON.parse(JSON.stringify(this.filterCriteria));
                        if (this.filterPillList.length === 1) {
                            this.selectedFilterPill = this.filterPillList[0];
                        } else {
                            this.pillFilterHandler(this.filterPillList[0]);
                        }
                    }
                }, 0);
            }
        }

        this.sectionGroup = (temp[0] as ContentAggregation<'CONTENTS'>).data;
        this.showSheenAnimation = false;
        this.generateImpressionTelemetry();
    }

    private generateImpressionTelemetry() {
        if (!this.shouldGenerateImpressionTelemetry) {
            return;
        }
        const facet = this.formField.facet;
        const selectedFacet = facet && ObjectUtil.isJSON(facet) ? JSON.parse(facet)['en'] : facet;
        switch (this.sectionCode) {
            case 'popular_categories':
                this.corRelationList.push({
                    type: CorReleationDataType.CATEGORY,
                    id: selectedFacet
                });
                this.pageId = PageId.CATEGORY_RESULTS;
                this.fromPage = PageId.SEARCH;
                this.env = Environment.SEARCH;
                break;
            case 'other_boards':
                this.corRelationList.push({
                    type: CorReleationDataType.BOARD,
                    id: selectedFacet
                });
                this.pageId = PageId.BOARD_RESULTS;
                this.fromPage = PageId.SEARCH;
                this.env = Environment.SEARCH;
                break;
            case 'browse_by_subject':
                this.corRelationList.push({
                    type: CorReleationDataType.SUBJECT,
                    id: selectedFacet
                });
                this.pageId = PageId.SUBJECT_RESULTS;
                this.fromPage = PageId.HOME;
                this.env = Environment.HOME;
                break;
            case 'browse_by_category':
                this.corRelationList.push({
                    type: CorReleationDataType.CATEGORY,
                    id: selectedFacet
                });
                this.pageId = PageId.CATEGORY_RESULTS;
                this.fromPage = PageId.HOME;
                this.env = Environment.HOME;
                break;
            case 'browse_by_audience':
                this.corRelationList.push({
                    type: CorReleationDataType.AUDIENCE,
                    id: selectedFacet
                });
                this.pageId = PageId.AUDIENCE_RESULTS;
                this.fromPage = PageId.SEARCH;
                this.env = Environment.SEARCH;
                break;
        }

        this.corRelationList.push({
            type: CorReleationDataType.FROM_PAGE,
            id: this.fromPage
        });
        let upDatedCorRelationList = [];
        if (this.sectionGroup && this.sectionGroup.sections && this.sectionGroup.sections.length) {
            const categoryResultCount = this.sectionGroup.sections.reduce((acc, curr) => {
                return acc + curr.count;
            }, 0);
            upDatedCorRelationList = this.corRelationList.concat([{
                type: CorReleationDataType.COUNT_CONTENT,
                id: categoryResultCount + ''
            }]);
        }
        this.shouldGenerateImpressionTelemetry = false;
        this.telemetryGeneratorService.generateImpressionTelemetry(
            ImpressionType.PAGE_LOADED, '',
            this.pageId,
            this.env, undefined, undefined, undefined, undefined,
            upDatedCorRelationList
        );
    }

    navigateToViewMorePage(items, subject, totalCount) {
        this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH,
            InteractSubtype.VIEW_MORE_CLICKED,
            Environment.HOME,
            PageId.LIBRARY,
            ContentUtil.getTelemetryObject(items));
        if (this.commonUtilService.networkInfo.isNetworkAvailable || items.isAvailableLocally) {
            const corRelationList = [
                { id: subject || '', type: CorReleationDataType.SECTION },
                { id: this.sectionCode || '', type: CorReleationDataType.ROOT_SECTION },
                { id: this.formField || '', type: CorReleationDataType.CONTENT}
            ];
            this.router.navigate([RouterLinks.TEXTBOOK_VIEW_MORE], {
                state: {
                    contentList: items,
                    subjectName: subject,
                    corRelation: corRelationList,
                    supportedFacets: this.supportedFacets,
                    totalCount
                }
            });
        } else {
            this.commonUtilService.presentToastForOffline('OFFLINE_WARNING_ETBUI').then();
        }
    }

    navigateToDetailPage(event, sectionName) {
        event.data = event.data.content ? event.data.content : event.data;
        const item = event.data;
        const index = event.index;
        const identifier = item.contentId || item.identifier;
        const corRelationList = [
            { id: sectionName || '', type: CorReleationDataType.SECTION },
            { id: this.sectionCode || '', type: CorReleationDataType.ROOT_SECTION }
        ];
        const values = {};
        values['sectionName'] = sectionName;
        values['positionClicked'] = index;
        this.telemetryGeneratorService.generateInteractTelemetry(
            InteractType.SELECT_CONTENT,
            '',
            this.env,
            this.pageId,
            ContentUtil.getTelemetryObject(item),
            values,
            ContentUtil.generateRollUp(undefined, identifier),
            this.corRelationList);
        if (this.commonUtilService.networkInfo.isNetworkAvailable || item.isAvailableLocally) {
            this.navService.navigateToDetailPage(item, { content: item, corRelation: corRelationList });
        } else {
            this.commonUtilService.presentToastForOffline('OFFLINE_WARNING_ETBUI').then();
        }
    }

    scrollToSection(id: string) {
        this.scrollService.scrollTo(id, {
            block: 'center',
            behavior: 'smooth'
        });
    }

    async navigateToFilterFormPage() {
        this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH,
            InteractSubtype.FILTER_BUTTON_CLICKED,
            Environment.COURSE,
            PageId.COURSE_PAGE_FILTER
            );
        const isDataEmpty = (this.sectionGroup && this.sectionGroup.sections && this.sectionGroup.sections.length) ? false : true;
        const inputFilterCriteria: ContentSearchCriteria = this.deduceFilterCriteria(isDataEmpty);
        const openFiltersPage = await this.modalController.create({
            component: SearchFilterPage,
            componentProps: {
                initialFilterCriteria: inputFilterCriteria,
                defaultFilterCriteria: JSON.parse(JSON.stringify(this.initialFilterCriteria)),
                existingSearchFilters: this.existingSearchFilters,
                formAPIFacets: this.formAPIFacets
            }
        });
        await openFiltersPage.present();
        openFiltersPage.onDidDismiss().then(async (result) => {
            if (result && result.data) {
                this.resentFilterCriteria = result.data.appliedFilterCriteria;
                await this.applyFilter(result.data.appliedFilterCriteria);
            }
        });
    }

    async onPrimaryFacetFilterSelect(primaryFacetFilter: { code: string }, toApply: FilterValue[]) {
        const appliedFilterCriteria: ContentSearchCriteria = this.deduceFilterCriteria();
        const facetFilter = appliedFilterCriteria.facetFilters.find(f => f.name === primaryFacetFilter.code);
        if (facetFilter) {
            facetFilter.values.forEach(facetFilterValue => {
                if (toApply.find(apply => facetFilterValue.name === apply.name)) {
                    facetFilterValue.apply = true;
                } else {
                    facetFilterValue.apply = false;
                }
            });

            await this.applyFilter(appliedFilterCriteria, true, toApply, primaryFacetFilter.code);
        }
    }

    private async applyFilter(appliedFilterCriteria: ContentSearchCriteria, refreshPillFilter = true, onSelectedFilter?, filterKey?) {
        const tempSearchCriteria: ContentSearchCriteria = {
            ...appliedFilterCriteria,
            mode: 'hard',
            facets: this.supportedFacets,
            searchType: SearchType.FILTER
        };
        tempSearchCriteria.facetFilters.forEach(facet => {
            if (facet.values && facet.values.length > 0) {
                if (facet.name === 'audience' && this.supportedUserTypesConfig) {
                    facet.values = ContentUtil.getAudienceFilter(facet, this.supportedUserTypesConfig);
                }
            }
        });
        await this.fetchAndSortData(tempSearchCriteria, false, refreshPillFilter, onSelectedFilter, filterKey);
    }

    async pillFilterHandler(pill){
        if(!pill){
            return;
        }
        const appliedFilterCriteria: ContentSearchCriteria = this.deduceFilterCriteria();
        const facetFilter = appliedFilterCriteria.facetFilters.find(f => f.name === this.formField.filterPillBy);
        if (facetFilter) {
            pill.apply = true;
            facetFilter.values = [pill];
            this.selectedFilterPill = pill
        }
        await this.applyFilter(appliedFilterCriteria, false);
    }

    deduceFilterCriteria(isDataEmpty?) {
        let filterCriteriaData: ContentSearchCriteria;
        if (isDataEmpty && this.resentFilterCriteria) {
            filterCriteriaData = JSON.parse(JSON.stringify(this.resentFilterCriteria));
        } else if (this.filterPillList.length && this.formField.filterPillBy && this.preFetchedFilterCriteria) {
            filterCriteriaData = JSON.parse(JSON.stringify(this.preFetchedFilterCriteria));
        } else {
            filterCriteriaData = JSON.parse(JSON.stringify(this.filterCriteria))
        }
        return filterCriteriaData;
    }

    getExistingFilters(formFields){
        const existingSearchFilters = {};
        if(formFields){
            if(formFields.filterPillBy){
                existingSearchFilters[formFields.filterPillBy] = true;
            }
            if(formFields.primaryFacetFilters){
                formFields.primaryFacetFilters.forEach(facets => {
                    existingSearchFilters[facets.code] = true;
                });
            }
        }
        return existingSearchFilters;
    }

    reloadDropdown(index, item){
        return item;
    }

    ngOnDestroy() {
        this.subscriptions.forEach(s => s.unsubscribe());
    }
}
<ion-content>
    <div class="container-focus">
        <div class="px-16 pb-2">
            <h3 *ngIf="categoryTitle" class="mt-4"
                style="font-weight: 600;">{{(categoryTitle | translateJson: {'%category': (formField.facet | translateJson), '%appName': appName} ) | translate }}</h3>
            <p *ngIf="categoryDescription">{{(categoryDescription | translateJson: {'%category': (formField.facet | translateJson), '%appName': appName} ) | translate }}</p>
        </div>

        <!-- filter from discover search page-->
        <form [formGroup]="primaryFacetFiltersFormGroup" *ngIf="primaryFacetFiltersFormGroup">
            <ion-grid class="filter-container">
                <ion-row>
                    <ion-col size="5" *ngFor="let primaryFacetFilter of primaryFacetFilters">
                        <ion-item class="filter-items">
                            <ion-label position="stacked" class="hide-label">
                                {{primaryFacetFilter.translations | translateJson}}
                            </ion-label>
                            <ion-select class="ion-text-capitalize"
                                        [interfaceOptions]="primaryFacetFiltersTemplateOptions"
                                        [formControlName]="primaryFacetFilter.code"
                                        okText="{{'BTN_SUBMIT' | translate}}"
                                        cancelText="{{'CANCEL' | translate}}"
                                        multiple="true"
                                        placeholder="{{primaryFacetFilter.translations | translateJson}}">
                                <ion-select-option
                                        *ngFor="let facet of ((displayFacetFilters && displayFacetFilters[primaryFacetFilter.code]) || []); trackBy:reloadDropdown"
                                        [value]="facet"
                                        class="ion-text-capitalize">
                                    {{facet.name | titlecase }}
                                </ion-select-option>
                            </ion-select>
                        </ion-item>
                    </ion-col>

                    <ion-col size="2">
                        <button class="filter-button" (click)="navigateToFilterFormPage()">
                            <img src="./assets/imgs/filter.svg" alt="filter">
                        </button>
                    </ion-col>
                </ion-row>
            </ion-grid>
        </form>
    </div>

    <div class="p-8 sticky-header-pills">
        <ng-container *ngIf="!showSheenAnimation">
            <sb-pills-grid *ngIf="sectionGroup?.sections && formField?.aggregate && formField?.showNavigationPill" [pillShape]="'default'"
                           [pillsViewType]="'scroll'"
                           [pillBorder]="PillBorder.SEMI_ROUND">
                <sb-pill-item (click)="scrollToSection(sectionGroup.name + '_'+ section.name)"
                              *ngFor="let section of sectionGroup?.sections" [name]="section?.name"></sb-pill-item>
            </sb-pills-grid>
        </ng-container>

        <ng-container *ngIf="sectionGroup?.sections && formField?.filterPillBy && filterPillList && filterPillList.length">
            <sb-pills-grid [pillShape]="'default'"
                           [pillsViewType]="'scroll'"
                           [pillBorder]="PillBorder.SEMI_ROUND">
                <sb-pill-item *ngFor="let pill of (filterPillList || [])" [name]="pill?.name | titlecase"
                    (click)="pillFilterHandler(pill)" [theme]="(pill?.name === selectedFilterPill?.name) && selectedPillTheme"></sb-pill-item>
            </sb-pills-grid>
        </ng-container>
    </div>

    <ion-list class="m-n" *ngIf="showSheenAnimation">
        <app-skeleton-item height="16px" width="40%" style="padding: 16px;"></app-skeleton-item>
        <ion-item *ngFor="let i of [0,1,2,3,4,5,6,7,8]" class="animation-background">
            <ion-avatar item-start>
                <app-skeleton-item height="72px" width="72px"></app-skeleton-item>
            </ion-avatar>
            <ion-label style="padding-left: 40px;">
                <app-skeleton-item height="12px" width="67%" style="padding-bottom: 8px;"></app-skeleton-item>
                <app-skeleton-item height="12px" width="47%" style="padding-bottom: 8px;"></app-skeleton-item>
            </ion-label>
        </ion-item>
    </ion-list>

    <div *ngIf="!showSheenAnimation">
        <div *ngFor="let section of sectionGroup?.sections">
            <div [id]="sectionGroup.name + '_'+ section.name"
                 *ngIf="section?.contents && section?.contents?.length" class="pb-8">
                <sb-library-cards-stack [title]="section?.name" [contentList]="section?.contents"
                                        [viewMoreButtonText]="'VIEW_MORE' | translate" [maxCardCount]="3"
                                        [layoutConfig]="layoutConfiguration"
                                        (viewMoreClick)="navigateToViewMorePage(section?.contents, section.name, section?.totalCount)"
                                        (cardClick)="navigateToDetailPage($event, section.name)"
                                        [defaultImage]="defaultImage">
                </sb-library-cards-stack>
            </div>
        </div>

        <div class="no-result-found" *ngIf="!sectionGroup?.sections?.length">
            {{ 'EMPTY_SEARCH_RESULTS' | translate }}
        </div>
    </div>
</ion-content>

./category-list-page.scss

@import "../../assets/styles/variables";
.animation-background {
  padding: 0 8px 0 8px;
  background-color: map-get($colors, white_f2);
}

.sticky-header-pills{
  position: sticky;
  top: 1rem;
  z-index: 9;
  background-color: var(--app-primary-background);
}

.ios .sticky-header-pills {
  top: 0
}

.filter-items{
  height: 70%;
  ion-select{
    border: none !important;
  }
  border-radius: 2rem;
  .hide-label{
    display: none;
  }
}

.container-focus {
  padding-bottom: 0 !important;
}

.filter-button {
  width: 100%;
  height: 70%;
  box-shadow: 0 0 50px 0 rgba(0,0,0,0.1) !important;
  background-color: var(--app-primary-header-light);
}

.no-result-found{
  text-align: center;
  font-size: 1rem;
  font-weight: bold;
  padding-top: 2rem;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""