Skip to content

Commit 924fd29

Browse files
authored
Add search to repository branch list (#343)
1 parent 27310ee commit 924fd29

File tree

13 files changed

+685
-673
lines changed

13 files changed

+685
-673
lines changed

composer.lock

Lines changed: 245 additions & 210 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docker/nodejs/run/entrypoint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22
set -e
33

4-
npm install
4+
npm install --no-save
55

66
if [ "${APP_ENV}" == "dev" ]; then
77
npm run watch &

package-lock.json

Lines changed: 312 additions & 433 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,33 @@
33
"axios": "^1.4.0",
44
"bootstrap": "^5.3.0-alpha3",
55
"bootstrap-icons": "^1.10.5",
6-
"highlight.js": "^11.7.0",
6+
"highlight.js": "^11.8.0",
77
"stimulus-use": "^0.52.0"
88
},
99
"devDependencies": {
10-
"@babel/core": "^7.20.7",
11-
"@babel/preset-env": "^7.20.2",
10+
"@babel/core": "^7.22.9",
11+
"@babel/preset-env": "^7.22.9",
1212
"@hotwired/stimulus": "^3.2.1",
13-
"@symfony/stimulus-bridge": "^3.2.1",
13+
"@symfony/stimulus-bridge": "^3.2.2",
1414
"@symfony/stimulus-bundle": "file:vendor/symfony/stimulus-bundle/assets",
15-
"@symfony/webpack-encore": "^4.3.0",
15+
"@symfony/webpack-encore": "^4.4.0",
1616
"@typescript-eslint/eslint-plugin": "^5.59.2",
17-
"core-js": "^3.30.1",
18-
"eslint": "^8.40.0",
17+
"core-js": "^3.31.1",
18+
"eslint": "^8.45.0",
1919
"eslint-config-standard-with-typescript": "^36.0.0",
2020
"eslint-plugin-import": "^2.27.5",
21-
"eslint-plugin-n": "^16.0.0",
21+
"eslint-plugin-n": "^16.0.1",
2222
"eslint-plugin-promise": "^6.1.1",
2323
"regenerator-runtime": "^0.13.11",
24-
"sass": "^1.63.6",
25-
"sass-loader": "^13.2.2",
26-
"stylelint": "^15.6.1",
24+
"sass": "^1.64.0",
25+
"sass-loader": "^13.3.2",
26+
"stylelint": "^15.10.2",
2727
"stylelint-config-standard-scss": "^10.0.0",
28-
"stylelint-scss": "^5.0.0",
29-
"ts-loader": "^9.4.2",
28+
"stylelint-scss": "^5.0.1",
29+
"ts-loader": "^9.4.4",
3030
"ts-node": "^10.9.1",
31-
"typescript": "^5.0.4",
32-
"webpack": "^5.88.0",
31+
"typescript": "^5.1.6",
32+
"webpack": "^5.88.2",
3333
"webpack-cli": "^5.1.4",
3434
"webpack-notifier": "^1.15.0"
3535
},

src/Controller/App/Project/ProjectBranchesController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use DR\Review\Controller\AbstractController;
77
use DR\Review\Entity\Repository\Repository;
88
use DR\Review\Exception\RepositoryException;
9+
use DR\Review\Request\Project\ProjectBranchRequest;
910
use DR\Review\Security\Role\Roles;
1011
use DR\Review\ViewModel\App\Project\ProjectBranchesViewModel;
1112
use DR\Review\ViewModelProvider\ProjectBranchesViewModelProvider;
@@ -30,11 +31,11 @@ public function __construct(
3031
#[Route('app/projects/{id<\d+>}/branches', name: self::class, methods: 'GET')]
3132
#[Template('app/repository/branches.html.twig')]
3233
#[IsGranted(Roles::ROLE_USER)]
33-
public function __invoke(#[MapEntity] Repository $repository): array
34+
public function __invoke(ProjectBranchRequest $request, #[MapEntity] Repository $repository): array
3435
{
3536
return [
3637
'page_title' => $this->translator->trans('branches'),
37-
'branchesViewModel' => $this->viewModelProvider->getProjectBranchesViewModel($repository)
38+
'branchesViewModel' => $this->viewModelProvider->getProjectBranchesViewModel($repository, $request->getSearchQuery())
3839
];
3940
}
4041
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace DR\Review\Request\Project;
5+
6+
use DigitalRevolution\SymfonyRequestValidation\AbstractValidatedRequest;
7+
use DigitalRevolution\SymfonyRequestValidation\ValidationRules;
8+
9+
class ProjectBranchRequest extends AbstractValidatedRequest
10+
{
11+
public function getSearchQuery(): ?string
12+
{
13+
$value = trim($this->request->query->get('search', ''));
14+
15+
return trim($value) === '' ? null : $value;
16+
}
17+
18+
protected function getValidationRules(): ?ValidationRules
19+
{
20+
return new ValidationRules(
21+
[
22+
'query' => [
23+
'search' => 'string'
24+
]
25+
]
26+
);
27+
}
28+
}

src/ViewModel/App/Project/ProjectBranchesViewModel.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class ProjectBranchesViewModel
1515
*/
1616
public function __construct(
1717
public readonly Repository $repository,
18+
public readonly ?string $searchQuery,
1819
public readonly array $branches,
1920
public readonly array $mergedBranches,
2021
private readonly array $reviews

src/ViewModelProvider/ProjectBranchesViewModelProvider.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@ public function __construct(private readonly GitBranchService $branchService, pr
2020
/**
2121
* @throws RepositoryException
2222
*/
23-
public function getProjectBranchesViewModel(Repository $repository): ProjectBranchesViewModel
23+
public function getProjectBranchesViewModel(Repository $repository, ?string $searchQuery): ProjectBranchesViewModel
2424
{
2525
$branches = $this->branchService->getRemoteBranches($repository);
2626
$mergedBranches = $this->branchService->getRemoteBranches($repository, true);
2727

28+
// filter branches based on searchQuery
29+
if ($searchQuery !== null) {
30+
$branches = array_filter($branches, static fn(string $branch): bool => stripos($branch, $searchQuery) !== false);
31+
}
32+
2833
$branchReviews = $this->reviewRepository->findBy(['repository' => $repository, 'type' => CodeReviewType::BRANCH, 'referenceId' => $branches]);
2934
$branchReviews = Arrays::reindex($branchReviews, static fn($review) => (string)$review->getReferenceId());
3035

31-
return new ProjectBranchesViewModel($repository, $branches, $mergedBranches, $branchReviews);
36+
return new ProjectBranchesViewModel($repository, $searchQuery, $branches, $mergedBranches, $branchReviews);
3237
}
3338
}

templates/app/repository/branches.html.twig

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,19 @@
2323
</ul>
2424
</div>
2525

26-
<table class="table table-bordered table-hover table-sm repository-branch-list">
26+
<form method="get">
27+
<div class="input-group">
28+
<input type="search" name="search" value="{{ branchesViewModel.searchQuery }}" class="form-control"
29+
{{ stimulus_controller('search-field') }}
30+
placeholder="{{ 'search'|trans }}"/>
31+
32+
{% if branchesViewModel.searchQuery != '' %}
33+
<a href="?search=" class="btn btn-secondary">&times;</a>
34+
{% endif %}
35+
</div>
36+
</form>
37+
38+
<table class="table table-bordered table-hover table-sm repository-branch-list mt-3">
2739
<thead>
2840
<tr>
2941
<th scope="col">{{ 'branch'|trans }}</th>

tests/Unit/Controller/App/Project/ProjectBranchesControllerTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use DR\Review\Controller\AbstractController;
77
use DR\Review\Controller\App\Project\ProjectBranchesController;
88
use DR\Review\Entity\Repository\Repository;
9+
use DR\Review\Request\Project\ProjectBranchRequest;
910
use DR\Review\Tests\AbstractControllerTestCase;
1011
use DR\Review\ViewModel\App\Project\ProjectBranchesViewModel;
1112
use DR\Review\ViewModelProvider\ProjectBranchesViewModelProvider;
@@ -31,10 +32,13 @@ public function testInvoke(): void
3132
$repository = new Repository();
3233
$viewModel = $this->createMock(ProjectBranchesViewModel::class);
3334

34-
$this->viewModelProvider->expects(self::once())->method('getProjectBranchesViewModel')->with($repository)->willReturn($viewModel);
35+
$request = $this->createMock(ProjectBranchRequest::class);
36+
$request->expects(self::once())->method('getSearchQuery')->willReturn('search');
37+
38+
$this->viewModelProvider->expects(self::once())->method('getProjectBranchesViewModel')->with($repository, 'search')->willReturn($viewModel);
3539
$this->translator->expects(self::once())->method('trans')->with('branches')->willReturn('Branches');
3640

37-
$result = ($this->controller)($repository);
41+
$result = ($this->controller)($request, $repository);
3842
static::assertSame('Branches', $result['page_title']);
3943
static::assertSame($viewModel, $result['branchesViewModel']);
4044
}

0 commit comments

Comments
 (0)