Skip to content

Commit

Permalink
Implementation of Search, Make SearchFilter standalone
Browse files Browse the repository at this point in the history
  • Loading branch information
cremertim committed Oct 7, 2024
1 parent 05338f0 commit fb1ad44
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 67 deletions.
12 changes: 12 additions & 0 deletions src/main/webapp/app/faq/faq.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,16 @@ export class FaqService {
return categories.some((category) => filteredCategory.has(category!));
}
}

hasSearchTokens(faq: Faq, searchTerm: string) {
if (searchTerm == '') {
return true;
}
const tokens = searchTerm.split(' ');
if (tokens) {
let faqText = faq.questionTitle + ' ' + faq.questionAnswer;
faqText = faqText.toLowerCase();
return tokens.every((token) => faqText.includes(token.toLowerCase()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div>
<div class="input-group mb-2 rounded-3 p-2 me-2 module-bg d-flex justify-content-between">
<jhi-search class="flex-grow-1" (newSearchEvent)="setSearchValue($event)" />
<jhi-search-filter class="flex-grow-1" (newSearchEvent)="setSearchValue($event)" />
<div class="ms-2 me-2" aria-label="Filter Dropdown" ngbDropdown>
<button class="btn" [ngClass]="{ 'btn-secondary': activeFilters.size === 0, 'btn-success': activeFilters.size > 0 }" ngbDropdownToggle id="filter-dropdown-button">
<fa-icon [icon]="faFilter" />
Expand Down
28 changes: 21 additions & 7 deletions src/main/webapp/app/overview/course-faq/course-faq.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { map } from 'rxjs/operators';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';
import { BehaviorSubject, Subject, Subscription } from 'rxjs';
import { faFilter } from '@fortawesome/free-solid-svg-icons';
import { ButtonType } from 'app/shared/components/button.component';
import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module';
Expand All @@ -15,15 +15,15 @@ import { FaqCategory } from 'app/entities/faq-category.model';
import { loadCourseFaqCategories } from 'app/faq/faq.utils';
import { CustomExerciseCategoryBadgeComponent } from 'app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component';
import { onError } from 'app/shared/util/global.utils';
import { SearchComponent } from 'app/shared/search/search.component';
import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.component';

@Component({
selector: 'jhi-course-faq',
templateUrl: './course-faq.component.html',
styleUrls: ['../course-overview.scss', 'course-faq.component.scss'],
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [ArtemisSharedComponentModule, ArtemisSharedModule, CourseFaqAccordionComponent, CustomExerciseCategoryBadgeComponent, SearchComponent],
imports: [ArtemisSharedComponentModule, ArtemisSharedModule, CourseFaqAccordionComponent, CustomExerciseCategoryBadgeComponent, SearchFilterComponent],
})
export class CourseFaqComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject<void>();
Expand All @@ -39,7 +39,7 @@ export class CourseFaqComponent implements OnInit, OnDestroy {
hasCategories = false;
isCollapsed = false;

searchValue = '';
searchInput = new BehaviorSubject<string>('');

readonly ButtonType = ButtonType;

Expand All @@ -57,6 +57,9 @@ export class CourseFaqComponent implements OnInit, OnDestroy {
this.loadFaqs();
this.loadCourseExerciseCategories(this.courseId);
});
this.searchInput.pipe(debounceTime(500)).subscribe((searchTerm: string) => {
this.defineSearchedAndFilteredFaq(searchTerm);
});
}

private loadCourseExerciseCategories(courseId: number) {
Expand Down Expand Up @@ -87,14 +90,25 @@ export class CourseFaqComponent implements OnInit, OnDestroy {

toggleFilters(category: string) {
this.activeFilters = this.faqService.toggleFilter(category, this.activeFilters);
this.applyFilters();
this.defineSearchedAndFilteredFaq(this.searchInput.getValue());
}

private applyFilters(): void {
this.filteredFaqs = this.faqService.applyFilters(this.activeFilters, this.faqs);
}

private applySearch(searchTerm: string) {
this.filteredFaqs = this.filteredFaqs.filter((faq) => {
return this.faqService.hasSearchTokens(faq, searchTerm);
});
}

setSearchValue(searchValue: string) {
this.searchValue = searchValue;
this.searchInput.next(searchValue);
}

defineSearchedAndFilteredFaq(searchTerm: string) {
this.applyFilters();
this.applySearch(searchTerm);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { faMagnifyingGlass, faTimes } from '@fortawesome/free-solid-svg-icons';
import { ArtemisSharedModule } from 'app/shared/shared.module';

@Component({
selector: 'jhi-search-filter',
templateUrl: './search-filter.component.html',
styleUrls: ['./search-filter.component.scss'],
standalone: true,
imports: [ArtemisSharedModule],
})
export class SearchFilterComponent {
faMagnifyingGlass = faMagnifyingGlass;
Expand Down
19 changes: 0 additions & 19 deletions src/main/webapp/app/shared/search/search.component.html

This file was deleted.

4 changes: 0 additions & 4 deletions src/main/webapp/app/shared/search/search.component.scss

This file was deleted.

31 changes: 0 additions & 31 deletions src/main/webapp/app/shared/search/search.component.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/main/webapp/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { StickyPopoverDirective } from 'app/shared/sticky-popover/sticky-popover
import { ConfirmEntityNameComponent } from 'app/shared/confirm-entity-name/confirm-entity-name.component';
import { DetailOverviewNavigationBarComponent } from 'app/shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component';
import { ScienceDirective } from 'app/shared/science/science.directive';
import { SearchFilterComponent } from './search-filter/search-filter.component';

@NgModule({
imports: [ArtemisSharedLibsModule, ArtemisSharedCommonModule, ArtemisSharedPipesModule, RouterModule],
Expand Down Expand Up @@ -56,7 +55,6 @@ import { SearchFilterComponent } from './search-filter/search-filter.component';
AssessmentWarningComponent,
StickyPopoverDirective,
ScienceDirective,
SearchFilterComponent,
],
exports: [
ArtemisSharedLibsModule,
Expand Down Expand Up @@ -87,7 +85,6 @@ import { SearchFilterComponent } from './search-filter/search-filter.component';
CompetencySelectionComponent,
StickyPopoverDirective,
ScienceDirective,
SearchFilterComponent,
],
})
export class ArtemisSharedModule {}
2 changes: 2 additions & 0 deletions src/main/webapp/app/shared/sidebar/sidebar.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SidebarCardDirective } from 'app/shared/sidebar/sidebar-card.directive'
import { ConversationOptionsComponent } from 'app/shared/sidebar/conversation-options/conversation-options.component';
import { AccordionAddOptionsComponent } from 'app/shared/sidebar/accordion-add-options/accordion-add-options.component';
import { ArtemisExamSharedModule } from 'app/exam/shared/exam-shared.module';
import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.component';

@NgModule({
imports: [
Expand All @@ -28,6 +29,7 @@ import { ArtemisExamSharedModule } from 'app/exam/shared/exam-shared.module';
SubmissionResultStatusModule,
SidebarCardDirective,
ArtemisExamSharedModule,
SearchFilterComponent,
],
declarations: [
SidebarAccordionComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import { FaqCategory } from 'app/entities/faq-category.model';
function createFaq(id: number, category: string, color: string): Faq {
const faq = new Faq();
faq.id = id;
faq.questionTitle = 'questionTitle';
faq.questionAnswer = 'questionAnswer';
faq.questionTitle = 'questionTitle ' + id;
faq.questionAnswer = 'questionAnswer ' + id;
faq.categories = [new FaqCategory(category, color)];
return faq;
}
Expand Down Expand Up @@ -84,6 +84,9 @@ describe('CourseFaqs', () => {
applyFilters: () => {
return [faq2, faq3];
},
hasSearchTokens: () => {
return true;
},
}),
],
})
Expand Down Expand Up @@ -125,6 +128,20 @@ describe('CourseFaqs', () => {
expect(courseFaqComponent.filteredFaqs).toEqual([faq2, faq3]);
});

it('should search through already filtered array', () => {
const searchSpy = jest.spyOn(faqService, 'hasSearchTokens');
const applyFilterSpy = jest.spyOn(faqService, 'applyFilters');
courseFaqComponent.setSearchValue('questionTitle');
courseFaqComponent.defineSearchedAndFilteredFaq(courseFaqComponent.searchInput.getValue());
expect(applyFilterSpy).toHaveBeenCalledOnce();
expect(searchSpy).toHaveBeenCalledTimes(2);
expect(searchSpy).toHaveBeenCalledWith(faq2, 'questionTitle');
expect(searchSpy).toHaveBeenCalledWith(faq3, 'questionTitle');
expect(courseFaqComponent.filteredFaqs).toHaveLength(2);
expect(courseFaqComponent.filteredFaqs).not.toContain(faq1);
expect(courseFaqComponent.filteredFaqs).toEqual([faq2, faq3]);
});

it('should catch error if no categories are found', () => {
alertServiceStub = jest.spyOn(alertService, 'error');
const error = { status: 404 };
Expand Down
9 changes: 9 additions & 0 deletions src/test/javascript/spec/service/faq.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,14 @@ describe('Faq Service', () => {
const convertedCategory = FaqService.stringifyFaqCategories(faq2);
expect(convertedCategory).toEqual(['{"color":"red","category":"testing"}']);
});

it('should return if all tokens exist in FAQ title or answer', () => {
const faq1 = new Faq();
faq1.questionTitle = 'Title';
faq1.questionAnswer = 'Answer';

expect(service.hasSearchTokens(faq1, 'title answer')).toBeTrue();
expect(service.hasSearchTokens(faq1, 'title answer missing')).toBeFalse();
});
});
});

0 comments on commit fb1ad44

Please sign in to comment.