File
Implements
Index
Properties
|
|
Methods
|
|
Inputs
|
|
existingSearchFilters
|
Type : literal type
|
|
Methods
applyFilter
|
applyFilter()
|
|
|
Private
Async
initilizeSearchFilter
|
initilizeSearchFilter()
|
|
|
Private
Async
refreshForm
|
refreshForm(formValue)
|
|
Parameters :
Name |
Optional |
formValue |
No
|
|
resetFilter
|
resetFilter()
|
|
|
valueChanged
|
valueChanged(event)
|
|
|
Public
Optional
baseSearchFilter
|
Type : literal type
|
|
Public
Optional
filterFormTemplateConfig
|
Type : IFacetFilterFieldTemplateConfig[]
|
|
Private
isPageLoadedFirstTime
|
Type : boolean
|
|
import {Component, Inject, Input, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Location, TitleCasePipe} from '@angular/common';
import {ModalController} from '@ionic/angular';
import {ContentService, ContentSearchCriteria, ContentSearchResult, SearchType, ContentSearchFilter} from 'sunbird-sdk';
import {FilterFormConfigMapper} from '@app/app/search-filter/filter-form-config-mapper';
import {CommonUtilService, Environment, FormAndFrameworkUtilService, InteractSubtype, InteractType, PageId, SearchFilterService, TelemetryGeneratorService} from '@app/services';
import {FieldConfig, IFacetFilterFieldTemplateConfig, SbSearchFacetFilterComponent} from 'common-form-elements';
@Component({
selector: 'app-search-filter.page',
templateUrl: './search-filter.page.html',
styleUrls: ['./search-filter.page.scss'],
providers: [FilterFormConfigMapper, TitleCasePipe]
})
export class SearchFilterPage implements OnInit {
@Input('initialFilterCriteria') initialFilterCriteria: ContentSearchCriteria;
@ViewChild('sbSearchFilterComponent', { static: false }) searchFilterComponent?: SbSearchFacetFilterComponent;
@Input('defaultFilterCriteria') readonly defaultFilterCriteria: ContentSearchCriteria;
@Input('existingSearchFilters') existingSearchFilters: {[key:string]:boolean};
@Input('formAPIFacets') formAPIFacets;
public config: FieldConfig<any>[];
public baseSearchFilter?: { [key: string]: string[] | string | undefined };
public filterFormTemplateConfig?: IFacetFilterFieldTemplateConfig[];
public searchResultFacets: ContentSearchFilter[];
private appliedFilterCriteria: ContentSearchCriteria;
private isPageLoadedFirstTime: boolean;
constructor(
@Inject('CONTENT_SERVICE') private contentService: ContentService,
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
private modalController: ModalController,
private commonUtilService: CommonUtilService,
private filterFormConfigMapper: FilterFormConfigMapper,
private formAndFrameworkUtilService: FormAndFrameworkUtilService,
private searchFilterService: SearchFilterService,
private telemetryGeneratorService: TelemetryGeneratorService
) {
}
ngOnInit() {
this.isPageLoadedFirstTime = true;
this.initilizeSearchFilter();
}
private async initilizeSearchFilter(){
this.initialFilterCriteria = await this.formAndFrameworkUtilService.changeChannelIdToName(this.initialFilterCriteria);
this.appliedFilterCriteria = JSON.parse(JSON.stringify(this.initialFilterCriteria));
if (!this.filterFormTemplateConfig) {
const {config, defaults} = await this.buildConfig(this.appliedFilterCriteria);
this.filterFormTemplateConfig = config;
this.baseSearchFilter = defaults;
}
this.searchResultFacets = this.appliedFilterCriteria.facetFilters || [];
}
resetFilter() {
if (this.searchFilterComponent) {
this.searchFilterComponent.resetFilter(true);
}
}
applyFilter() {
this.telemetryGeneratorService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.APPLY_FILTER_CLICKED,
Environment.HOME,
PageId.COURSE_SEARCH_FILTER,
undefined);
this.modalController.dismiss({
appliedFilterCriteria: this.formAndFrameworkUtilService.changeChannelNameToId(this.appliedFilterCriteria)
});
}
cancel() {
this.router.navigate([], { relativeTo: this.activatedRoute }).then(() => {
this.modalController.dismiss();
});
}
private async refreshForm(formValue) {
const searchCriteria: ContentSearchCriteria = {
...JSON.parse(JSON.stringify(this.appliedFilterCriteria)),
limit: 0,
mode: 'hard',
searchType: SearchType.FILTER,
fields: [],
};
searchCriteria.facetFilters.forEach((facetFilter) => {
const selection = formValue[facetFilter.name];
if (selection) {
facetFilter.values.forEach(f => {
//single select type == string || multiple select type == Array
if(typeof selection === 'string'){
f.apply = (f.name === selection)
} else {
f.apply = !!(selection.indexOf(f.name) !== -1);
}
});
}
});
this.formAndFrameworkUtilService.changeChannelNameToId(searchCriteria);
const loader = await this.commonUtilService.getLoader();
await loader.present();
try {
const contentSearchResult: ContentSearchResult = await this.contentService.searchContent(searchCriteria).toPromise();
if(contentSearchResult && contentSearchResult.filterCriteria && contentSearchResult.filterCriteria.facetFilters){
contentSearchResult.filterCriteria.facetFilters =
await this.searchFilterService.reformFilterValues(contentSearchResult.filterCriteria.facetFilters);
}
this.appliedFilterCriteria = await this.formAndFrameworkUtilService.changeChannelIdToName(contentSearchResult.filterCriteria);
this.searchResultFacets = this.appliedFilterCriteria.facetFilters || [];
} catch (e) {
console.error(e);
} finally {
await loader.dismiss();
}
}
private async buildConfig(filterCriteria: ContentSearchCriteria) {
return await this.filterFormConfigMapper.map(
filterCriteria.facetFilters.reduce((acc, f) => {
acc[f.name] = f.values;
return acc;
}, {}),
(this.existingSearchFilters || {})
);
}
valueChanged(event) {
if (!event) {
return;
}
if (this.isPageLoadedFirstTime) {
this.isPageLoadedFirstTime = false;
return;
}
this.refreshForm(event);
}
}
<ion-content>
<div>
<div class="filter-header px-16 pt-16">
<ion-button class="reset-button" fill="clear" (click)="resetFilter()">
<ion-icon role="button" aria-label="reset filter" name="refresh"></ion-icon>
{{'RESET' | translate}}
</ion-button>
</div>
<div class="p-16" *ngIf="searchResultFacets">
<sb-search-facet-filter [baseSearchFilter]="baseSearchFilter"
[searchResultFacets]="searchResultFacets"
[filterFormTemplateConfig]="filterFormTemplateConfig"
(searchFilterChange)="valueChanged($event)"
#sbSearchFilterComponent></sb-search-facet-filter>
</div>
</div>
</ion-content>
<div class="search-filter-footer">
<ion-row class="padding-12" style="--background: #FFFFFF !important;">
<ion-col>
<ion-button class= "cancel-button"
class="ion-text-capitalize mb-16" expand="block" (click)="cancel()">
{{'CANCEL' | translate}}
</ion-button>
</ion-col>
<ion-col>
<ion-button class="ion-text-capitalize mb-16" expand="block"
(click)="applyFilter()">{{'APPLY' | translate}}
</ion-button>
</ion-col>
</ion-row>
</div>
@import "~@project-sunbird/sb-styles/assets/_variables.scss";
@import "~@project-sunbird/sb-styles/assets/_colors.scss";
.reset-button {
float: right;
ion-icon {
color: var(--app-primary);
}
}
.filter-header {
border-bottom: 1px solid var(--app-primary-header);
p {
display: inline-block;
margin-bottom: 0;
line-height: 3rem;
font-size: 1.1rem;
}
}
.cancel-button {
--background: #f3f7fb !important;
color: #000000 !important;
}
.search-filter-footer {
z-index: -10;
}
:host ::ng-deep {
--sbt-pill-bg-active: #004594;
--sbt-pill-text-hover: #ffffff;
--sbt-pill-hs: 212,100%;
--sbt-pill-bg: hsl(var(--sbt-pill-hs), 90%);
--sbt-box-shadow-black: rgba(0, 0, 0, 0.1);
--sbt-box-shadow-3px: 0.1875rem 0.1875rem 0.125rem 0 var(--sbt-box-shadow-black);
--sbt-theme-purple-selectbox: #6841B3;
--sbt-bradius: 0.125rem;
--sbt-bradius-24: calc(var(--sbt-bradius) * 12);
.cfe-multiselect-container {
ul, li {
margin: 0;
padding: 0;
list-style: none;
}
margin-bottom: 1rem;
.cfe-multiselect-label {
margin: .5rem 0;
display: flex;
color: var(--app-black);
font-size: var(--font-size-normal);
}
.cfe-multiselect-field {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
position: relative;
box-sizing: border-box;
height: 2.5rem;
line-height: 2.5rem;
border-radius: var(--sbt-bradius-24) !important;
background: var(--sbt-theme-purple-selectbox-lbg);
color: var(--sbt-theme-purple-selectbox);
font-weight: 700;
font-size: .75rem;
width: 100%;
min-height: 2rem;
border: none;
padding: 0 1.25rem;
box-shadow: var(--sbt-box-shadow-3px);
border-color: var(--gray-200);
cursor: pointer;
word-wrap: break-word;
white-space: normal;
outline: 0;
min-width: 14rem;
transition: box-shadow .1s ease, width .1s ease;
-webkit-tap-highlight-color: transparent;
text-align: left;
.cfe-multiselect-field-label-container {
height: 100%;
width: 100%;
overflow: hidden;
order: 1;
flex-grow: 1;
ul {
height: 100%;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding-left: 0 !important;
}
.cfe-multiselect-field-label {
display: inline;
font-size: 0.75rem !important;
}
}
.cfe-multiselect-field-caret {
order: 2;
flex-shrink: 0;
box-sizing: border-box;
padding-top: 0.2rem;
padding-left: 1rem;
}
}
.cfe-multiselect-dropdown {
&[hidden] {
display: block;
}
overflow-x: hidden;
margin-top: .25rem;
border-radius: var(--sbt-bradius-24);
background: var(--sbt-theme-purple-selectbox-lbg);
width: 100%;
max-height: 12.5rem;
position: absolute;
z-index: 10000;
top: 100%;
left: 0;
&::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #F5F5F5;
}
&::-webkit-scrollbar
{
width: 0.25rem;
background-color: #F5F5F5;
}
&::-webkit-scrollbar-thumb
{
background-color: #999999;
}
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-animation-duration: .3s;
animation-duration: .3s;
-webkit-animation-timing-function: ease;
animation-timing-function: ease;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
opacity: 0;
transform: scaleY(0);
li {
position: relative;
display: flex;
padding: 0 1.25rem;
cursor: pointer;
& > div {
display: block;
text-transform: capitalize;
width: 100%;
}
&.selected-option {
color: var(--sbt-theme-purple-selectbox);
font-weight: 700;
background: rgba(0,0,0,.05);
}
}
.cfe-multiselect-dropdown-item {
flex-grow: 1;
}
}
&.closed {
.cfe-multiselect-dropdown {
-webkit-animation-name: slideOutY;
animation-name: slideOutY;
transform-origin: top center;
}
}
&.open {
.cfe-multiselect-field {
box-shadow: 0 2px 3px 0 rgba(34, 36, 38, .15);
}
.cfe-multiselect-dropdown {
-webkit-animation-name: slideInY;
animation-name: slideInY;
transform-origin: top center;
}
}
}
.cfe-multiselect-container {
.cfe-multiselect-pills-container {
display: flex;
align-items: center;
box-sizing: border-box;
flex-wrap: wrap;
justify-content: flex-start;
margin: 0 -.5rem 0 0;
.cfe-multiselect-pills-item {
display: unset;
width: 100px;
border-radius: 1rem;
flex-basis: 100px;
flex-grow: 1;
cursor: pointer;
transition: .25s ease-in-out;
font-size: 0.75rem;
-webkit-appearance: none;
text-overflow: ellipsis;
text-transform: capitalize;
text-decoration: none;
text-align: center;
font-weight: 400;
font-style: normal;
font-stretch: normal;
white-space: normal;
padding: .5rem 1rem;
margin: 0 .5rem .5rem 0;
background-color: var(--sbt-pill-bg);
&.selected-option {
color: var(--sbt-pill-text-hover);
background-color: var(--sbt-pill-bg-active);
box-shadow: var(--sbt-box-shadow-3px);
&:hover {
background-color: var(--gray-100);
color: var(--black);
}
}
}
}
}
@-webkit-keyframes slideInY {
0% {
opacity: 0;
transform: scaleY(0)
}
100% {
opacity: 1;
transform: scaleY(1)
}
}
@keyframes slideInY {
0% {
opacity: 0;
transform: scaleY(0)
}
100% {
opacity: 1;
transform: scaleY(1)
}
}
@-webkit-keyframes slideOutY {
0% {
opacity: 1;
transform: scaleY(1)
}
100% {
opacity: 0;
transform: scaleY(0)
}
}
@keyframes slideOutY {
0% {
opacity: 1;
transform: scaleY(1)
}
100% {
opacity: 0;
transform: scaleY(0)
}
}
.cfe-multiselect-modal-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1;
label {
font-size: $font-size-base;
font-weight: normal;
margin: 0
}
.list-border .placeholder {
margin: 0;
color: var(--gray-300);
}
.list-border ul[disabled] {
opacity: 0.7;
pointer-events: none;
}
.list-border ul {
list-style-type: none;
position: absolute;
margin: 0;
font-size: $font-size-base;
font-weight: bold;
}
.list-border {
border: 0.5px solid var(--gray-400);
padding: 1.3rem;
cursor: pointer;
display: flex;
align-items: center;
left: 0;
height: 2.5rem;
}
.list-border li {
float: left;
font-size: 0.75rem;
font-weight: 700;
margin-left: 4px;
}
.dropdown ul {
list-style-type: none;
}
.dropdown li {
cursor: pointer;
padding: 8px;
border: 1px solid var(--white);
}
.dropdown ul {
margin: 0;
padding: 0;
}
.row {
display: grid;
grid-template-columns: 1fr 10fr;
grid-gap: 0rem;
span {
font-size: 1rem !important;
text-transform: capitalize;
}
}
.footer {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 0rem;
padding-left: 8px;
padding-bottom: 8px;
padding-top: 8px;
}
.sb-modal-container {
position: fixed;
height: 100vh;
overflow: hidden;
width: 100%;
left: 0;
top: 0;
right: 0;
z-index: 10;
}
.sb-modal-overlay {
position: absolute;
width: 100%;
height: 100%;
top: 0;
background: rgba(0, 0, 0, 0.6);
left: 0;
z-index: 10;
}
.fa .fa-close {
float: right;
}
.sb-modal {
display: block;
position: absolute;
bottom: 0;
width: 100%;
--border-top: 0.5px solid var(--white);
z-index: 11;
background: var(--white);
}
.sb-modal ul {
list-style-type: none;
}
.sb-modal li {
cursor: pointer;
padding-bottom: 8px;
padding-top: 8px;
}
.value-label {
width: 16.875rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sb-forms-radio {
margin-top: 6px;
}
.sb-form-button {
display: inline;
padding: 10px;
}
.sb-btn-primary-outline {
color: var(--primary-color);
background-color: transparent;
border: 0.5px solid var(--primary-color);
border-radius: 4px;
padding: 10px 40px;
font-size: 1rem;
text-transform: uppercase;
width: 100%;
}
.sb-btn-primary {
color: var(--white);
background-color: var(--primary-color);
border: 0.5px solid var(--primary-color);
border-radius: 4px;
padding: 10px 40px;
font-size: 1rem;
text-transform: uppercase;
width: 100%;
}
.header {
padding: 16px;
margin-left: 8px;
font-weight: bold;
}
.body {
padding-top: 8px;
border-bottom: 0.5px solid var(--gray-100);
border-top: 0.5px solid var(--gray-100);
max-height: 18.75rem;
overflow: scroll;
}
.list-with-ellipsis:nth-child(3) {
float: left;
font-size: 0.75rem;
font-weight: 700;
margin-left: 4px;
width: 3.125rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list-with-ellipsis:nth-child(n+4) {
visibility: hidden;
}
/* The container */
.container {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 2px;
margin-right: 1rem;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Hide the browser's default checkbox */
.container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
/* Create a custom checkbox */
.checkmark {
display: flex;
justify-content: center;
align-items: center;
height: 0.938rem;
width: 0.938rem;
border: 0.4px solid var(--black);
}
/* On mouse-over, add a grey background color */
.container:hover input~.checkmark {
background-color: var(--white);
}
/* When the checkbox is checked, add a blue background */
.container input:checked~.checkmark {
background-color: var(--primary-600);
}
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: "";
display: none;
}
/* Show the checkmark when checked */
.container input:checked~.checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.container .checkmark:after {
width: 0.313rem;
height: 0.625rem;
border: solid var(--white);
border-width: 0 2px 2px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.sb-modal-dropdown-web ul {
list-style-type: none;
display: block;
position: absolute;
top: 2.375rem;
left: 0;
background-color: white;
width: 100%;
z-index: 999;
box-shadow: 2px 2px 2px 2px aliceblue;
border: 2px solid #80a7ce;
max-height: 19.625rem;
overflow: scroll;
}
.sb-modal-dropdown-web ul li {
margin-top: 10px;
margin-bottom: 8px;
padding: 8px;
font-size: 0.813rem;
}
.sb-modal-dropdown-web .selected-option {
font-weight: bold;
background-color: #eee;
}
/* width */
::-webkit-scrollbar {
width: 0.375rem;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}
.cursor-pointer {
cursor: pointer;
}
}
}
Legend
Html element with directive