Skip to content

Commit 2c3100e

Browse files
committed
Vectors: Started front-end work, moved to own controller
1 parent 54f883e commit 2c3100e

File tree

7 files changed

+159
-44
lines changed

7 files changed

+159
-44
lines changed

app/Search/QueryController.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace BookStack\Search;
4+
5+
use BookStack\Http\Controller;
6+
use BookStack\Search\Vectors\VectorSearchRunner;
7+
use Illuminate\Http\Request;
8+
9+
class QueryController extends Controller
10+
{
11+
public function __construct(
12+
protected SearchRunner $searchRunner,
13+
) {
14+
}
15+
16+
/**
17+
* Show the view to start a vector/LLM-based query search.
18+
*/
19+
public function show(Request $request)
20+
{
21+
// TODO - Validate if query system is active
22+
$query = $request->get('ask', '');
23+
24+
// TODO - Placeholder
25+
$entities = $this->searchRunner->searchEntities(SearchOptions::fromString("cat"), 'all', 1, 20)['results'];
26+
27+
// TODO - Set page title
28+
29+
return view('search.query', [
30+
'query' => $query,
31+
'entities' => $entities,
32+
]);
33+
}
34+
35+
/**
36+
* Perform a vector/LLM-based query search.
37+
*/
38+
public function run(Request $request, VectorSearchRunner $runner)
39+
{
40+
// TODO - Validate if query system is active
41+
$query = $request->get('query', '');
42+
43+
if ($query) {
44+
$results = $runner->run($query);
45+
} else {
46+
$results = null;
47+
}
48+
49+
return view('search.query', [
50+
'results' => $results,
51+
]);
52+
}
53+
}

app/Search/SearchController.php

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public function searchSuggestions(Request $request)
129129
}
130130

131131
/**
132-
* Search siblings items in the system.
132+
* Search sibling items in the system.
133133
*/
134134
public function searchSiblings(Request $request, SiblingFetcher $siblingFetcher)
135135
{
@@ -140,23 +140,4 @@ public function searchSiblings(Request $request, SiblingFetcher $siblingFetcher)
140140

141141
return view('entities.list-basic', ['entities' => $entities, 'style' => 'compact']);
142142
}
143-
144-
/**
145-
* Perform a vector/LLM-based query search.
146-
*/
147-
public function searchQuery(Request $request, VectorSearchRunner $runner)
148-
{
149-
// TODO - Validate if query system is active
150-
$query = $request->get('query', '');
151-
152-
if ($query) {
153-
$results = $runner->run($query);
154-
} else {
155-
$results = null;
156-
}
157-
158-
return view('search.query', [
159-
'results' => $results,
160-
]);
161-
}
162143
}

resources/js/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export {PagePicker} from './page-picker';
4444
export {PermissionsTable} from './permissions-table';
4545
export {Pointer} from './pointer';
4646
export {Popup} from './popup';
47+
export {QueryManager} from './query-manager';
4748
export {SettingAppColorScheme} from './setting-app-color-scheme';
4849
export {SettingColorPicker} from './setting-color-picker';
4950
export {SettingHomepageControl} from './setting-homepage-control';
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {Component} from "./component";
2+
3+
export class QueryManager extends Component {
4+
protected input!: HTMLTextAreaElement;
5+
protected generatedLoading!: HTMLElement;
6+
protected generatedDisplay!: HTMLElement;
7+
protected contentLoading!: HTMLElement;
8+
protected contentDisplay!: HTMLElement;
9+
protected form!: HTMLFormElement;
10+
11+
setup() {
12+
this.input = this.$refs.input as HTMLTextAreaElement;
13+
this.form = this.$refs.form as HTMLFormElement;
14+
this.generatedLoading = this.$refs.generatedLoading;
15+
this.generatedDisplay = this.$refs.generatedDisplay;
16+
this.contentLoading = this.$refs.contentLoading;
17+
this.contentDisplay = this.$refs.contentDisplay;
18+
19+
// TODO - Start lookup if query set
20+
21+
// TODO - Update URL on query change
22+
23+
// TODO - Handle query form submission
24+
}
25+
}

resources/sass/_forms.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,3 +597,21 @@ input.shortcut-input {
597597
max-width: 120px;
598598
height: auto;
599599
}
600+
601+
.query-form {
602+
display: flex;
603+
flex-direction: row;
604+
gap: vars.$m;
605+
textarea {
606+
font-size: 1.4rem;
607+
height: 100px;
608+
box-shadow: vars.$bs-card;
609+
border-radius: 8px;
610+
color: #444;
611+
}
612+
button {
613+
align-self: start;
614+
margin: 0;
615+
font-size: 1.6rem;
616+
}
617+
}
Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,62 @@
11
@extends('layouts.simple')
22

33
@section('body')
4-
<div class="container mt-xl" id="search-system">
5-
6-
<form action="{{ url('/search/query') }}" method="get">
7-
<input name="query" type="text">
8-
<button class="button">Query</button>
9-
</form>
10-
11-
@if($results)
12-
<h2>Results</h2>
13-
14-
<h3>LLM Output</h3>
15-
<p>{{ $results['llm_result'] }}</p>
16-
17-
<h3>Entity Matches</h3>
18-
@foreach($results['entity_matches'] as $match)
19-
<div>
20-
<div><strong>{{ $match['entity_type'] }}:{{ $match['entity_id'] }}; Distance: {{ $match['distance'] }}</strong></div>
21-
<details>
22-
<summary>match text</summary>
23-
<div>{{ $match['text'] }}</div>
24-
</details>
4+
<div component="query-manager" class="container small pt-xxl">
5+
6+
<div class="card content-wrap auto-height">
7+
<h1 class="list-heading">Start a Query</h1>
8+
<form action="{{ url('/query') }}"
9+
refs="query-manager@form"
10+
title="Run Query"
11+
method="post"
12+
class="query-form">
13+
<textarea name="query"
14+
refs="query-manager@input"
15+
class="input-fill-width"
16+
rows="5"
17+
placeholder="Enter a query"
18+
autocomplete="off">{{ $query }}</textarea>
19+
<button class="button icon">@icon('search')</button>
20+
</form>
21+
</div>
22+
23+
<div class="card content-wrap auto-height pb-xl">
24+
<h2 class="list-heading">Generated Response</h2>
25+
<div refs="query-manager@generated-loading">
26+
@include('common.loading-icon')
27+
</div>
28+
<p refs="query-manager@generated-display">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad adipisci aliquid architecto cupiditate dolor doloribus eligendi et expedita facilis fugiat fugit illo, ipsa laboriosam maiores, molestias mollitia non obcaecati porro quasi quis quos reprehenderit rerum sunt tenetur ullam unde voluptate voluptates! Distinctio et eum id molestiae nisi quisquam sed ut.</p>
29+
</div>
30+
31+
32+
<div class="card content-wrap auto-height pb-xl">
33+
<h2 class="list-heading">Relevant Content</h2>
34+
<div refs="query-manager@content-loading">
35+
@include('common.loading-icon')
36+
</div>
37+
<div class="book-contents">
38+
<div refs="query-manager@content-display" class="entity-list">
39+
@include('entities.list', ['entities' => $entities, 'showPath' => true, 'showTags' => true])
2540
</div>
26-
@endforeach
27-
@endif
41+
</div>
42+
</div>
43+
44+
{{-- @if($results)--}}
45+
{{-- <h2>Results</h2>--}}
46+
47+
{{-- <h3>LLM Output</h3>--}}
48+
{{-- <p>{{ $results['llm_result'] }}</p>--}}
49+
50+
{{-- <h3>Entity Matches</h3>--}}
51+
{{-- @foreach($results['entity_matches'] as $match)--}}
52+
{{-- <div>--}}
53+
{{-- <div><strong>{{ $match['entity_type'] }}:{{ $match['entity_id'] }}; Distance: {{ $match['distance'] }}</strong></div>--}}
54+
{{-- <details>--}}
55+
{{-- <summary>match text</summary>--}}
56+
{{-- <div>{{ $match['text'] }}</div>--}}
57+
{{-- </details>--}}
58+
{{-- </div>--}}
59+
{{-- @endforeach--}}
60+
{{-- @endif--}}
2861
</div>
2962
@stop

routes/web.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use BookStack\Http\Middleware\VerifyCsrfToken;
1212
use BookStack\Permissions\PermissionsController;
1313
use BookStack\References\ReferenceController;
14+
use BookStack\Search\QueryController;
1415
use BookStack\Search\SearchController;
1516
use BookStack\Settings as SettingControllers;
1617
use BookStack\Sorting as SortingControllers;
@@ -189,14 +190,17 @@
189190

190191
// Search
191192
Route::get('/search', [SearchController::class, 'search']);
192-
Route::get('/search/query', [SearchController::class, 'searchQuery']);
193193
Route::get('/search/book/{bookId}', [SearchController::class, 'searchBook']);
194194
Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']);
195195
Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']);
196196
Route::get('/search/entity-selector', [SearchController::class, 'searchForSelector']);
197197
Route::get('/search/entity-selector-templates', [SearchController::class, 'templatesForSelector']);
198198
Route::get('/search/suggest', [SearchController::class, 'searchSuggestions']);
199199

200+
// Queries
201+
Route::get('/query', [QueryController::class, 'show']);
202+
Route::post('/query', [QueryController::class, 'run']);
203+
200204
// User Search
201205
Route::get('/search/users/select', [UserControllers\UserSearchController::class, 'forSelect']);
202206

0 commit comments

Comments
 (0)