Skip to content

Commit

Permalink
Merge pull request #420 from valor-software/feat/search
Browse files Browse the repository at this point in the history
feat: implemented search on blog page
  • Loading branch information
ZhmenZH authored Feb 5, 2024
2 parents e99c2fe + d6d2cd3 commit 42b0e4e
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 57 deletions.
8 changes: 4 additions & 4 deletions apps/valor-software-site/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
Expand Down Expand Up @@ -98,8 +98,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,14 @@ <h3 id="_make_the_solution_test_friendly">Make the solution test-friendly</h3>
<p>Run the CLI as a separate process and intercommunicate with them.</p>
</li>
<li>
<p>Run the CLI functionality inside the tests.
I chose the second one because it&#8217;s more suitable for integration testing. The first is mostly regarding e2e or Big (Google definitions) tests. Also, the second approach is much more straightforward in implementation. But there is one critical answer here. We must pass the input data (key presses) to the CLI.</p>
<p>Run the CLI functionality inside the tests.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>I chose the second one because it&#8217;s more suitable for integration testing. The first is mostly regarding e2e or Big (Google definitions) tests. Also, the second approach is much more straightforward in implementation. But there is one critical answer here. We must pass the input data (key presses) to the CLI.</p>
</div>
<div class="paragraph">
<p>If we talk about the first approach, the following approaches will be useful: <a href="https://stackoverflow.com/questions/13230370/nodejs-child-process-write-to-stdin-from-an-already-initialised-process" target="_blank" rel="noopener">Nodejs Child Process: write to stdin from an already initialised process</a>. It makes sense to note here that the approaches above are rather for e2e testing than integration.</p>
</div>
<div class="paragraph">
Expand Down
2 changes: 2 additions & 0 deletions apps/valor-software-site/src/assets/styles/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// swiper core styles
@import 'swiper/css';

@import 'material-icons/iconfont/material-icons.scss';

body, html {
@apply bg-grey_bg h-full;
scroll-behavior: smooth;
Expand Down
17 changes: 14 additions & 3 deletions libs/route-pages/blog/src/blog.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,33 @@ import { CommonDocsModule } from '@valor-software/common-docs';
import { BlogComponent, ArticleComponent, BlogItemComponent } from './components';
import { FeedbackModule } from '@valor-software/feedback';
import { SwiperModule } from 'swiper/angular';
import { DomainNamePipe } from './pipes/domain-name.pipe';
import { DomainNamePipe, HighlightMatchingLettersPipe } from './pipes';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';

@NgModule({
declarations: [
BlogPageComponent,
BlogComponent,
ArticleComponent,
BlogItemComponent,
DomainNamePipe
DomainNamePipe,
HighlightMatchingLettersPipe
],
imports: [
CommonModule,
RouterModule.forChild(routes),
CommonDocsModule,
FeedbackModule,
SwiperModule
SwiperModule,
MatAutocompleteModule,
MatInputModule,
MatIconModule,
ReactiveFormsModule,
MatButtonModule
]
})
export class BlogModule {
Expand Down
111 changes: 72 additions & 39 deletions libs/route-pages/blog/src/pages/blog-page/blog-page.component.html
Original file line number Diff line number Diff line change
@@ -1,52 +1,85 @@
<section class="landing-section !pt-24 lg:!pt-40 !pb-0">
<div *ngIf="firstArticles.length > 0 && activeArticle"
class="container flex flex-col lg:flex-row">
<section class="landing-section !pt-24 !pb-0">
<div class="container flex flex-col items-end">
<mat-form-field *ngIf="articles.length > 0"
class="search">
<input type="text"
matInput
[placeholder]="'Search'"
[formControl]="searchTermControl"
[matAutocomplete]="autoGroup">
<mat-autocomplete [disableRipple]="true"
#autoGroup="matAutocomplete">
<mat-optgroup *ngFor="let group of groupedAndFilteredArticles" [label]="group.tag">
<mat-option *ngFor="let article of group.articles" [value]="article.title"
(click)="navigateToArticle(article.title)"
(onSelectionChange)="navigateToArticle(article.title)">
<span class="cursor-pointer"
[innerHtml]="article.title | highlightMatchingLetters: searchTermControl.value"></span>
</mat-option>
</mat-optgroup>
</mat-autocomplete>

<a *ngIf="activeArticle?.title"
href="javascript:void(0)"
[routerLink]="[getRouteLink(activeArticle.title)]"
class="cursor-pointer main-image">
<blog-item
class="w-full lg:pt-0"
[showActiveArticle]="true"
[article]="activeArticle">
</blog-item>
</a>
<mat-icon matPrefix>search</mat-icon>
<button *ngIf="searchTermControl?.value?.length ?? 0 > 0"
[disableRipple]="true"
mat-icon-button
(click)="searchTermControl.reset()"
matSuffix>
<mat-icon>close</mat-icon>
</button>
</mat-form-field>

<div class="first-articles">
<ng-container *ngFor="let article of firstArticles">
<a
href="javascript:void(0)"
[routerLink]="[getRouteLink(article.title)]"
class="w-full cursor-pointer smaller-article-item mb-8">
<blog-item
*ngIf="article?.title !== activeArticle?.title"
[showLatestArticles]="true"
[article]="article"
></blog-item>
</a>
</ng-container>
</div>

<div class="block lg:hidden mt-4 lg:mt-0">
<h1 class="main-title mb-4">Latest Articles</h1>
<div class="flex flex-col lg:flex-row mt-7"
*ngIf="firstArticles.length > 0 && activeArticle">

<a *ngIf="activeArticle?.title"
href="javascript:void(0)"
[routerLink]="[getRouteLink(activeArticle.title)]"
class="cursor-pointer main-image">
<blog-item
class="w-full lg:pt-0"
[showActiveArticle]="true"
[article]="activeArticle">
</blog-item>
</a>

<swiper
[config]="swiperConfig"
class="pink_swiper transparent_slides">
<ng-template swiperSlide *ngFor="let article of firstArticles">
<a href="javascript:void(0)" [routerLink]="[getRouteLink(article.title)]"
class="w-full lg:max-w-380 lg:w-31% cursor-pointer smaller-article-item">
<div class="first-articles">
<ng-container *ngFor="let article of articles | slice : 0: 4">
<a
href="javascript:void(0)"
[routerLink]="[getRouteLink(article.title)]"
class="w-full cursor-pointer smaller-article-item">
<blog-item
*ngIf="article?.title !== activeArticle?.title"
[showLatestArticles]="true"
[article]="article">
</blog-item>
[article]="article"
></blog-item>
</a>
</ng-template>
</ng-container>
</div>

<div class="block lg:hidden mt-4 lg:mt-0">
<h1 class="main-title mb-4">Latest Articles</h1>

</swiper>
<swiper
[config]="swiperConfig"
class="pink_swiper transparent_slides">
<ng-template swiperSlide *ngFor="let article of firstArticles">
<a href="javascript:void(0)" [routerLink]="[getRouteLink(article.title)]"
class="w-full lg:max-w-380 lg:w-31% cursor-pointer smaller-article-item">
<blog-item
*ngIf="article?.title !== activeArticle?.title"
[showLatestArticles]="true"
[article]="article">
</blog-item>
</a>
</ng-template>

</swiper>
</div>
</div>

</div>
</section>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ $bp-large: 1024px;
}

.first-articles {
width: 30%;
width: 32%;
display: none;
flex-direction: column;
max-height: 100%;
Expand All @@ -35,4 +35,86 @@ $bp-large: 1024px;

::ng-deep .pink_swiper .swiper-slide {
padding-top: 0;
}

.search {
width: 32%;
}

::ng-deep .cdk-overlay-pane {
.mat-mdc-autocomplete-panel {
background-color: #515151;
padding-top: 0;
padding-bottom: 16px;
max-height: 306px
}

.mat-mdc-optgroup {
color: #E3E3E3;
}

.mat-mdc-optgroup-label {
min-height: auto;
margin-bottom: 8px;
margin-top: 16px;
}

.mat-mdc-option {
background-color: #343434;
margin: 0 16px 4px;
color: #E3E3E3;
border-radius: 4px;
}

.mat-mdc-optgroup .mat-mdc-option:not(.mat-mdc-option-multiple) {
padding: 10px 12px;
}

.mat-mdc-option:hover:not(.mdc-list-item--disabled) {
background-color: rgba(226, 78, 99, 1) !important;
color: rgba(255, 255, 255, 1) !important;
}

.mat-mdc-option:focus:not(.mdc-list-item--disabled) {
background-color: rgba(226, 78, 99, 1) !important;
color: rgba(255, 255, 255, 1) !important;
}

.mat-mdc-option:active:not(.mdc-list-item--disabled) {
background-color: rgba(226, 78, 99, 1) !important;
color: rgba(255, 255, 255, 1) !important;
}

.mat-mdc-option:focus.mdc-list-item, .mat-mdc-option.mat-mdc-option-active.mdc-list-item {
background-color: rgba(226, 78, 99, 1) !important;
color: rgba(255, 255, 255, 1) !important;
}
}

::ng-deep .mat-icon {
color: #8C8C8C;
}

::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled) {
background-color: #515151 !important;
}

::ng-deep .mdc-text-field__input:focus {
box-shadow: none;
}

::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::after {
border-bottom-color: transparent !important;
}

::ng-deep .mat-mdc-autocomplete-trigger {
color: rgba(255, 255, 255, 1) !important;
}

::ng-deep .mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input {
caret-color: white !important;
}

::ng-deep .mat-mdc-input-element::placeholder{
color: #8C8C8C !important;
}
Loading

0 comments on commit 42b0e4e

Please sign in to comment.