Unverified Commit f66267d3 authored by Sharath Prasad's avatar Sharath Prasad Committed by GitHub
Browse files

Merge pull request #17 from rajeshkumaravel/master

Issue #SB-20404 feat: Facets filters added - dropdown and pills component added
parents 053eb4e0 3e83e661
dependabot/npm_and_yarn/angular/core-11.0.5 dependabot/npm_and_yarn/browserslist-4.16.6 dependabot/npm_and_yarn/decode-uri-component-0.2.2 dependabot/npm_and_yarn/dns-packet-1.3.4 dependabot/npm_and_yarn/elliptic-6.5.4 dependabot/npm_and_yarn/engine.io-and-karma-6.2.1 dependabot/npm_and_yarn/eventsource-1.1.1 dependabot/npm_and_yarn/express-4.18.2 dependabot/npm_and_yarn/follow-redirects-1.14.8 dependabot/npm_and_yarn/handlebars-4.7.7 dependabot/npm_and_yarn/hosted-git-info-2.8.9 dependabot/npm_and_yarn/json5-and-angular-devkit/build-angular-2.2.3 dependabot/npm_and_yarn/jszip-3.10.1 dependabot/npm_and_yarn/loader-utils-and-angular-devkit/build-angular-3.2.1 dependabot/npm_and_yarn/lodash-4.17.21 dependabot/npm_and_yarn/ng-packagr-10.1.1 dependabot/npm_and_yarn/path-parse-1.0.7 dependabot/npm_and_yarn/qs-6.5.3 dependabot/npm_and_yarn/shelljs-0.8.5 dependabot/npm_and_yarn/socket.io-parser-and-karma-4.2.1 dependabot/npm_and_yarn/url-parse-1.5.10 dependabot/npm_and_yarn/y18n-3.2.2 master release-3.6.0 release-3.7.0-v8 release-3.8.0 release-3.9.0 release-4.0.0 release-4.1.0 release-4.1.0-v9 release-4.10.1 release-4.2.0 release-4.3.0 release-4.4.0 release-4.5.0 release-4.6.0 release-4.7.0 release-4.8.0 release-4.9.0 release-5.0.0 release-5.0.1 release-5.1.0_v10 release-5.1.0_v11 release-5.1.0_v12 release-6.0.0_v13 release-6.0.0_v13-mobile release-6.0.0_v14 revert-117-tag-input revert-119-hotfix/edit-details revert-61-richtext revert-63-richtextnew revert-94-tag-input snyk-fix-bb6706a537ba2f5a29d4d0c4ea441193 snyk-upgrade-12c917ac8d79f5e72ebd71b7407f6ac6 snyk-upgrade-39fee69ffac9d0a0df5d5d24424777d8 snyk-upgrade-822eb34879b2fea17e28fad6b3e6a789 snyk-upgrade-f42e30417b693e2eb5ca260d9cbfc5b9
No related merge requests found
Showing with 315 additions and 6 deletions
+315 -6
...@@ -67,3 +67,7 @@ export interface FieldConfig<T> { ...@@ -67,3 +67,7 @@ export interface FieldConfig<T> {
}[]; }[];
asyncValidation?: FieldConfigAsyncValidation; asyncValidation?: FieldConfigAsyncValidation;
} }
export enum FilterType {
FACET = 'facet'
}
...@@ -15,6 +15,8 @@ import { PipesModule } from './pipes/pipes.module'; ...@@ -15,6 +15,8 @@ import { PipesModule } from './pipes/pipes.module';
import { RedExclamationComponent } from './icon/red-exclamation/red-exclamation.component'; import { RedExclamationComponent } from './icon/red-exclamation/red-exclamation.component';
import { GreenTickComponent } from './icon/green-tick/green-tick.component'; import { GreenTickComponent } from './icon/green-tick/green-tick.component';
import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component'; import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component';
import { FiltersComponent } from './filters/filters.component';
import { PillsComponent } from './pills/pills.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -30,7 +32,9 @@ import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component ...@@ -30,7 +32,9 @@ import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component
CaretDownComponent, CaretDownComponent,
RedExclamationComponent, RedExclamationComponent,
GreenTickComponent, GreenTickComponent,
EmptyCircleComponent EmptyCircleComponent,
FiltersComponent,
PillsComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
...@@ -51,7 +55,8 @@ import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component ...@@ -51,7 +55,8 @@ import { EmptyCircleComponent } from './icon/empty-circle/empty-circle.component
RedExclamationComponent, RedExclamationComponent,
GreenTickComponent, GreenTickComponent,
EmptyCircleComponent, EmptyCircleComponent,
MultipleDropdownComponent MultipleDropdownComponent,
FiltersComponent
] ]
}) })
export class CommonFormElementsModule { } export class CommonFormElementsModule { }
<div class="sb-dropdown"> <div class="sb-dropdown" *ngIf="!type">
<label>{{label}}</label> <label>{{label}}</label>
<ng-container *ngIf="options"> <ng-container *ngIf="options">
<div class="dropdown-container"> <div class="dropdown-container">
...@@ -24,3 +24,21 @@ ...@@ -24,3 +24,21 @@
</div> </div>
</ng-container> </ng-container>
</div> </div>
<!-- Dropdown for filters component -->
<div class="sb-dropdown" *ngIf="type === 'facet'">
<label>{{label}}</label>
<ng-container *ngIf="options && options.data">
<div class="dropdown-container">
<sb-icon-dropdown class="dropdown-icon"></sb-icon-dropdown>
<select [attr.disabled]="disabled ? true : ( context ? (context.invalid ? true : null) : null )"
class="sb-dropdown-select" [ngClass]="(styleClass ? styleClass : 'default-dropdown')" id="sb-dropdown" name="sb-dropdown"
(change)="onChangeFacet($event)" placeholder="placeHolder">
<option *ngIf="!default" [disabled]="true" selected>{{placeHolder}}</option>
<option *ngFor="let option of options.data" [ngValue]="option" [selected]="options.default === option.value">{{option.label}}</option>
</select>
</div>
</ng-container>
</div>
<!-- Dropdown for filters component -->
import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core'; import {Component, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, EventEmitter} from '@angular/core';
import {FormControl} from '@angular/forms'; import {FormControl} from '@angular/forms';
import {Observable, Subject, Subscription} from 'rxjs'; import {Observable, Subject, Subscription} from 'rxjs';
import {FieldConfigOption, FieldConfigOptionsBuilder} from '../common-form-config'; import {FieldConfigOption, FieldConfigOptionsBuilder} from '../common-form-config';
...@@ -23,10 +23,12 @@ export class DropdownComponent implements OnInit, OnChanges, OnDestroy { ...@@ -23,10 +23,12 @@ export class DropdownComponent implements OnInit, OnChanges, OnDestroy {
@Input() default?: any; @Input() default?: any;
@Input() contextData: any; @Input() contextData: any;
@Input() dataLoadStatusDelegate: Subject<'LOADING' | 'LOADED'>; @Input() dataLoadStatusDelegate: Subject<'LOADING' | 'LOADED'>;
@Input() type?: string;
@Input() styleClass?: string;
@Output() onChangeFilter: EventEmitter<any> = new EventEmitter();
options$?: Observable<FieldConfigOption<any>[]>; options$?: Observable<FieldConfigOption<any>[]>;
contextValueChangesSubscription?: Subscription; contextValueChangesSubscription?: Subscription;
selectedType: any;
constructor() { constructor() {
} }
...@@ -70,4 +72,13 @@ export class DropdownComponent implements OnInit, OnChanges, OnDestroy { ...@@ -70,4 +72,13 @@ export class DropdownComponent implements OnInit, OnChanges, OnDestroy {
isOptionsMap(input: any) { isOptionsMap(input: any) {
return !Array.isArray(input) && typeof input === 'object'; return !Array.isArray(input) && typeof input === 'object';
} }
onChangeFacet($event) {
const selectedObject = this.options.data[$event.currentTarget.options.selectedIndex - 1];
let emitPayload = JSON.parse(JSON.stringify(this.options));
emitPayload['data'] = selectedObject;
emitPayload['selectedLabel'] = selectedObject.label;
emitPayload['selectedValue'] = selectedObject.value;
this.onChangeFilter.emit(emitPayload);
}
} }
<div *ngIf="type === FilterType.FACET">
<div *ngFor="let facet of formattedFacets">
<!-- Start of Dropdown -->
<sb-dropdown *ngIf="facet.type === 'dropdown'" [type]="type" [label]="facet.label" [options]="facet"
[placeHolder]="facet.placeHolder" [default]="facet.default" [styleClass]="styleClass"
(onChangeFilter)="selectedFilter.emit($event)">
</sb-dropdown>
<!-- End of Dropdown -->
<!-- Start of pills -->
<div *ngIf="facet.type === 'pills'">
<sb-pills [label]="facet.label" [options]="facet" [styleClass]="styleClass"
(onChangeFilter)="selectedFilter.emit($event)"></sb-pills>
</div>
<!-- End of pills -->
</div>
</div>
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FiltersComponent } from './filters.component';
describe('FiltersComponent', () => {
let component: FiltersComponent;
let fixture: ComponentFixture<FiltersComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FiltersComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FiltersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import { FilterType } from '../common-form-config';
@Component({
selector: 'sb-filters',
templateUrl: './filters.component.html',
styleUrls: ['./filters.component.css']
})
export class FiltersComponent implements OnInit {
@Input() type: string;
@Input() facets: any = [];
@Input() config?: object;
@Input() styleClass?: string;
@Output() selectedFilter: EventEmitter<any> = new EventEmitter();
FilterType = FilterType;
formGroup: FormGroup;
formattedFacets: any = [];
constructor() {
}
ngOnInit() {
this.formatFacets();
}
formatFacets () {
this.facets.forEach((facet, index) => {
let facetObj = {};
facetObj['name'] = facet['name'];
facetObj['type'] = this.config[facet['name']] && this.config[facet['name']]['type'] ? this.config[facet['name']]['type'] : 'dropdown';
facetObj['index'] = this.config[facet['name']] && this.config[facet['name']]['index'] ? this.config[facet['name']]['index'] : index;
facetObj['label'] = this.config[facet['name']] && this.config[facet['name']]['label'] ? this.config[facet['name']]['label'] : facet['name'];
facetObj['placeHolder'] = this.config[facet['name']] && this.config[facet['name']]['placeHolder'] ? this.config[facet['name']]['placeHolder'] : 'Select ' + facet['name'];
facetObj['default'] = this.config[facet['name']] && this.config[facet['name']]['default'] ? this.config[facet['name']]['default'] : '';
facetObj['data'] = [];
facet['values'].forEach(facetValue => {
facetObj['data'].push({
label: facetValue['name'],
value: facetValue['name']
});
});
this.formattedFacets.push(facetObj);
this.formattedFacets.sort((a, b) => a.index - b.index);
});
}
}
.sbt-class-bar .sb-slider-pills-container {
overflow-x: inherit !important;
}
.sbt-class-bar .sb-slider-pills-container .sb-grade-pills-container {
background: inherit !important;
padding-top: 0px !important;
}
.sbt-class-bar .sb-slider-pills-container .sb-pills-container {
display: flex !important;
flex-wrap: wrap;
justify-content: flex-start;
margin: 0px -8px 0px 0;
}
html[dir="rtl"] .sbt-class-bar .sb-slider-pills-container .sb-pills-container {
margin: 0px 0 0px -8px !important;
}
.sbt-class-bar .sb-slider-pills-container .sb-pills-container .pill {
padding: 8px 16px !important;
color: #ffffff !important;
margin: 0 8px 8px 0 !important;
background-color: #0077FF;
font-size: 12px !important;
display: unset !important;
width: 100px;
flex-basis: 100px;
flex-grow: 1;
}
html[dir="rtl"] .sbt-class-bar .sb-slider-pills-container .sb-pills-container .pill {
margin: 0 0 8px 8px !important;
}
.sbt-class-bar .sb-slider-pills-container .sb-pills-container .pill.active, .sbt-class-bar .sb-slider-pills-container .sb-pills-container .pill:hover {
color: #ffffff !important;
background-color: #0076FE !important;
box-shadow: rgba(0, 0, 0, 0.1) 3px 3px 2px 0px;
}
.sb-slider-pills-container {
overflow-x: auto;
}
.sb-slider-pills-container .sb-pills-container {
display: inline-flex;
align-items: center;
box-sizing: border-box;
}
.sb-slider-pills-container .sb-pills-container .pill {
background-color: #ffffff;
white-space: nowrap;
-webkit-appearance: none;
text-overflow: ellipsis;
min-height: 32px;
cursor: pointer;
transition: all 0.25s ease-in-out;
border-radius: 2px;
text-transform: capitalize;
text-decoration: none;
text-align: center;
font-weight: normal;
font-style: normal;
font-stretch: normal;
font-size: 12px;
box-sizing: border-box;
display: flex;
align-items: center;
line-height: 16px;
}
.sb-slider-pills-container .sb-medium-pills-container {
min-height: 64px;
background: #ffffff;
min-width: 100%;
}
.sb-slider-pills-container .sb-medium-pills-container .pill {
border: #008840 1px solid;
color: #008840;
}
.sb-slider-pills-container .sb-medium-pills-container .pill:active, .sb-slider-pills-container .sb-medium-pills-container .pill:hover, .sb-slider-pills-container .sb-medium-pills-container .pill.active {
color: #ffffff;
background-color: #008840;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, );
}
.sb-slider-pills-container .sb-grade-pills-container {
min-height: 48px;
/* background: var(--gray-0); */
min-width: 100%;
}
.sb-slider-pills-container .sb-grade-pills-container .pill {
border-radius: 16px;
color: #024f9d;
min-height: 32px;
}
.sb-slider-pills-container .sb-grade-pills-container .pill:active, .sb-slider-pills-container .sb-grade-pills-container .pill:hover, .sb-slider-pills-container .sb-grade-pills-container .pill.active {
background-color: #024f9d;
color: #ffffff;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, );
}
.sb-slider-pills-container .sb-grade-pills-container .pill:active .icon-svg svg, .sb-slider-pills-container .sb-grade-pills-container .pill:hover .icon-svg svg, .sb-slider-pills-container .sb-grade-pills-container .pill.active .icon-svg svg {
fill: #ffffff;
}
.sb-slider-pills-container .sb-grade-pills-container .pill.rounded {
font-size: 14px;
}
.sb-slider-pills-container .sb-grade-pills-container .pill.rounded-with-icon .icon-svg {
margin-right: 4px;
top: 0;
}
html[dir="rtl"] .sb-slider-pills-container .sb-grade-pills-container .pill.rounded-with-icon .icon-svg {
margin-left: 4px;
margin-right: inherit;
}
.sb-slider-pills-container .sb-grade-pills-container .pill.rounded-with-icon .name {
align-self: center;
display: inline-block;
line-height: 16px;
}
<div class="sbt-class-bar">
<label>{{label}}</label>
<div class="sb-slider-pills-container">
<div class="sb-pills-container sb-grade-pills-container" id="gradeScroll">
<div class="pill rounded" *ngFor="let facet of options.data; let i = index;" [ngClass]="((options.default === facet.value ? 'active' : '') + ' ' + styleClass)"
attr.id="class{{i}}" (click)="onChangeFacet(facet)">
{{facet.value}}
</div>
</div>
</div>
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PillsComponent } from './pills.component';
describe('PillsComponent', () => {
let component: PillsComponent;
let fixture: ComponentFixture<PillsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PillsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PillsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'sb-pills',
templateUrl: './pills.component.html',
styleUrls: ['./pills.component.css']
})
export class PillsComponent implements OnInit {
@Input() options: any = [];
@Input() label?: string;
@Input() styleClass?: string;
@Output() onChangeFilter: EventEmitter<any> = new EventEmitter();
constructor() { }
ngOnInit() {
}
onChangeFacet(selectedValue) {
let emitPayload = JSON.parse(JSON.stringify(this.options));
emitPayload['data'] = selectedValue;
emitPayload['selectedLabel'] = selectedValue.label;
emitPayload['selectedValue'] = selectedValue.value;
this.onChangeFilter.emit(emitPayload);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment