Skip to content

Commit 613d1d6

Browse files
committed
feat(repositories): search implementation
1 parent b304161 commit 613d1d6

File tree

8 files changed

+85
-15
lines changed

8 files changed

+85
-15
lines changed

src/api/db/repository.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,13 @@ export function getRepositoryByBuildId(buildId: number): Promise<any> {
8787
});
8888
}
8989

90-
export function getRepositories(userId: string): Promise<any[]> {
90+
export function getRepositories(userId: string, keyword: string): Promise<any[]> {
9191
return new Promise((resolve, reject) => {
92-
new Repository().fetchAll().then(repos => {
92+
new Repository().query(qb => {
93+
if (keyword !== '') {
94+
qb.where('full_name', 'like', `%${keyword}%`).orWhere('clone_url', 'like', `%${keyword}%`);
95+
}
96+
}).fetchAll().then(repos => {
9397
if (!repos) {
9498
reject();
9599
}

src/api/server-routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function repositoryRoutes(): express.Router {
104104
const router = express.Router();
105105

106106
router.get('/', (req: express.Request, res: express.Response) => {
107-
getRepositories('1').then(repos => {
107+
getRepositories(req.query.userId, req.query.keyword).then(repos => {
108108
return res.status(200).json({ data: repos });
109109
}).catch(err => res.status(200).json({ status: false }));
110110
});

src/app/components/app-job/app-job.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<div class="columns is-multiline">
1616
<div class="column is-9">
1717
<h1 class="bold">
18-
<span><a [routerLink]="['/repo', job?.builds_id]">{{ job?.build.head_full_name }}</a></span>
18+
<span><a [routerLink]="['/repo', job?.build.repository.id]">{{ job?.build.head_full_name }}</a></span>
1919
<span class="build-icon">
2020
<img src="images/icons/clock.svg" *ngIf="job?.status === 'queued'">
2121
<img src="images/icons/flickr.svg" *ngIf="job?.status === 'running'">

src/app/components/app-repositories/app-repositories.component.html

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,21 @@ <h1>Repositories</h1>
99
</div>
1010
<div class="nav-center"></div>
1111
<div class="nav-right">
12-
<div class="group-buttons">
13-
<button class="group-button is-active">Repositories</button>
14-
<button class="group-button">All Repositories</button>
12+
<div class="search-input-container">
13+
<input type="text" class="search-input" placeholder="Search" [(ngModel)]="searchKeyword" (ngModelChange)="onKeywordChanged($event)">
14+
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
15+
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
16+
<g transform="translate(-1376.000000, -97.000000)" fill="#A1A7AF">
17+
<g transform="translate(0.000000, 70.000000)">
18+
<g transform="translate(1136.000000, 17.000000)">
19+
<g>
20+
<path d="M250.5355,13.4645 C248.5825,11.5115 245.4175,11.5115 243.4645,13.4645 C241.5115,15.4175 241.5115,18.5825 243.4645,20.5355 C245.4175,22.4885 248.5825,22.4885 250.5355,20.5355 C252.4885,18.5825 252.4885,15.4175 250.5355,13.4645 M255.7355,25.7355 C255.3445,26.1255 254.7115,26.1255 254.3205,25.7355 L251.1715,22.5855 C248.4295,24.6355 244.5415,24.4415 242.0505,21.9495 C239.3165,19.2165 239.3165,14.7845 242.0505,12.0505 C244.7835,9.3165 249.2165,9.3165 251.9495,12.0505 C254.4415,14.5415 254.6355,18.4295 252.5855,21.1715 L255.7355,24.3215 C256.1255,24.7115 256.1255,25.3445 255.7355,25.7355" id="Icon"></path>
21+
</g>
22+
</g>
23+
</g>
24+
</g>
25+
</g>
26+
</svg>
1527
</div>
1628
</div>
1729
</div>
@@ -27,11 +39,8 @@ <h1>Repositories</h1>
2739

2840
<div class="columns is-multiline" *ngIf="!loading">
2941
<div class="column is-12" *ngIf="!repositories || !repositories.length">
30-
<div class="notification">
31-
<span class="icon">
32-
<img src="images/icons/info.svg">
33-
</span>
34-
<span>No repositories found.</span>
42+
<div class="notification is-info">
43+
No repositories found.
3544
</div>
3645
</div>
3746

src/app/components/app-repositories/app-repositories.component.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { ApiService } from '../../services/api.service';
44
import { AuthService } from '../../services/auth.service';
55
import { SocketService } from '../../services/socket.service';
66
import { ConfigService } from '../../services/config.service';
7+
import { Subject } from 'rxjs/Subject';
8+
import 'rxjs/add/operator/debounceTime';
9+
import 'rxjs/add/operator/distinctUntilChanged';
10+
import 'rxjs/add/operator/filter';
711

812
export interface Repository {
913
url: string;
@@ -21,6 +25,8 @@ export class AppRepositoriesComponent implements OnInit {
2125
dropdowns: boolean[];
2226
buildTriggered: boolean;
2327
url: string;
28+
searchKeyword: string;
29+
modelChanged: Subject<string> = new Subject<string>();
2430

2531
constructor(
2632
private apiService: ApiService,
@@ -36,10 +42,16 @@ export class AppRepositoriesComponent implements OnInit {
3642
this.url = this.config.url;
3743
this.userData = this.authService.getData();
3844
this.fetch();
45+
46+
this.modelChanged
47+
.debounceTime(400)
48+
.distinctUntilChanged()
49+
.subscribe(event => this.fetch(event));
3950
}
4051

41-
fetch(): void {
42-
this.apiService.getRepositories(this.userData.id).subscribe(event => {
52+
fetch(keyword = ''): void {
53+
this.loading = true;
54+
this.apiService.getRepositories(this.userData.id, keyword).subscribe(event => {
4355
this.repositories = event.map(repo => {
4456
repo.status_badge = this.url + '/api/repositories/badge/' + repo.id;
4557
return repo;
@@ -66,4 +78,8 @@ export class AppRepositoriesComponent implements OnInit {
6678
this.buildTriggered = true;
6779
setTimeout(() => this.buildTriggered = false, 5000);
6880
}
81+
82+
onKeywordChanged(text: string): void {
83+
this.modelChanged.next(text);
84+
}
6985
}

src/app/services/api.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ export class ApiService {
2424
return this.get(`${this.url}/jobs/${id}`);
2525
}
2626

27-
getRepositories(userId: string): Observable<any> {
27+
getRepositories(userId: string, keyword: string): Observable<any> {
2828
const params = new URLSearchParams();
2929
params.append('userId', userId);
30+
params.append('keyword', keyword);
3031
return this.get(`${this.url}/repositories`, params);
3132
}
3233

src/app/styles/colors.sass

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ $background-button: #273142
44
$color: #FFFFFF
55
$color-secondary: #7F8FA4
66
$color-disabled: #354052
7+
$color-search: #A1A7AF
78

89
$border: #313D4F
910
$divider: #364357

src/app/styles/content.sass

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,42 @@
218218
.justify-end
219219
display: flex
220220
justify-content: flex-end
221+
222+
.search-input-container
223+
display: inline-block
224+
position: relative
225+
226+
.search-input
227+
display: block
228+
background: $background
229+
border: 1px solid $divider
230+
border-radius: 4px
231+
min-width: 150px
232+
outline: none
233+
padding: 10px 30px 10px 20px
234+
font-size: 14px
235+
color: $color-search
236+
transition: min-width 300ms ease
237+
238+
&::-webkit-input-placeholder
239+
color: $color-search
240+
241+
&::-moz-placeholer
242+
color: $color-search
243+
244+
&:-ms-input-placeholder
245+
color: $color-search
246+
247+
&:-moz-olaceholder
248+
color: $color-search
249+
250+
&:focus
251+
min-width: 350px
252+
253+
svg
254+
display: block
255+
position: absolute
256+
width: 16px
257+
height: 16px
258+
right: 10px
259+
top: 11px

0 commit comments

Comments
 (0)