Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/app/glossary/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ def get_glossary_record_by_id(self, record_id: int) -> GlossaryRecord:
return record
raise NotFoundGlossaryRecordExc()

def get_glossary_records_for_segment(
self, segment: str, glossary_ids: list[int]
def get_glossary_records_for_phrase(
self, phrase: str, glossary_ids: list[int]
) -> list[GlossaryRecord]:
words = postprocess_stemmed_segment(stem_sentence(segment))
words = postprocess_stemmed_segment(stem_sentence(phrase))
or_clauses = [GlossaryRecord.source.ilike(f"%{word}%") for word in words]
records = self.db.execute(
select(GlossaryRecord).where(
Expand Down
28 changes: 24 additions & 4 deletions backend/app/routers/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ def get_doc_records(
approved=record.approved,
repetitions_count=repetitions_count,
has_comments=has_comments,
translation_src=record.target_source.value
if record.target_source
else None,
translation_src=(
record.target_source.value if record.target_source else None
),
)
for record, repetitions_count, has_comments in records
]
Expand All @@ -140,6 +140,26 @@ def get_doc_records(
)


@router.get("/{doc_id}/glossary_search")
def doc_glossary_search(
doc_id: int,
db: Annotated[Session, Depends(get_db)],
query: Annotated[str, Query()],
) -> list[GlossaryRecordSchema]:
doc = get_doc_by_id(db, doc_id)
glossary_ids = [gl.id for gl in doc.glossaries]
return (
[
GlossaryRecordSchema.model_validate(record)
for record in GlossaryQuery(db).get_glossary_records_for_phrase(
query, glossary_ids
)
]
if glossary_ids
else []
)


@router.get("/records/{record_id}/comments")
def get_comments(
record_id: int,
Expand Down Expand Up @@ -200,7 +220,7 @@ def get_record_glossary_records(
return (
[
GlossaryRecordSchema.model_validate(record)
for record in GlossaryQuery(db).get_glossary_records_for_segment(
for record in GlossaryQuery(db).get_glossary_records_for_phrase(
original_segment.source, glossary_ids
)
]
Expand Down
122 changes: 122 additions & 0 deletions backend/tests/routers/test_routes_documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,125 @@ def test_get_doc_records_with_repetitions(
assert record_counts["Hello World"] == 3
assert record_counts["Goodbye"] == 1
assert record_counts["Test"] == 1


def test_doc_glossary_search_with_matching_records(
user_logged_client: TestClient, session: Session
):
with session as s:
records = [
DocumentRecord(source="Regional Effects", target=""),
DocumentRecord(source="User Interface", target=""),
]
s.add(
Document(
name="test_doc.txt",
type=DocumentType.txt,
records=records,
processing_status="pending",
created_by=1,
)
)
s.commit()

gq = GlossaryQuery(session)
g = gq.create_glossary(1, GlossarySchema(name="test"), ProcessingStatuses.DONE)
gq.create_glossary_record(
1,
GlossaryRecordCreate(
comment=None, source="Regional Effects", target="Региональные эффекты"
),
g.id,
)
gq.create_glossary_record(
1,
GlossaryRecordCreate(
comment=None, source="User Interface", target="Пользовательский интерфейс"
),
g.id,
)

dq = GenericDocsQuery(session)
dq.set_document_glossaries(dq.get_document(1), [g])

response = user_logged_client.get(
"/document/1/glossary_search?query=Regional Effects"
)
assert response.status_code == 200
response_json = response.json()
assert len(response_json) == 1
assert response_json[0]["source"] == "Regional Effects"
assert response_json[0]["target"] == "Региональные эффекты"
assert response_json[0]["glossary_id"] == 1
assert response_json[0]["comment"] is None
assert response_json[0]["created_by_user"]["id"] == 1


def test_doc_glossary_search_returns_empty_when_no_glossaries(
user_logged_client: TestClient, session: Session
):
with session as s:
records = [
DocumentRecord(source="Regional Effects", target=""),
]
s.add(
Document(
name="test_doc.txt",
type=DocumentType.txt,
records=records,
processing_status="pending",
created_by=1,
)
)
s.commit()

response = user_logged_client.get(
"/document/1/glossary_search?query=Regional Effects"
)
assert response.status_code == 200
assert response.json() == []


def test_doc_glossary_search_returns_empty_when_no_matches(
user_logged_client: TestClient, session: Session
):
with session as s:
records = [
DocumentRecord(source="Regional Effects", target=""),
]
s.add(
Document(
name="test_doc.txt",
type=DocumentType.txt,
records=records,
processing_status="pending",
created_by=1,
)
)
s.commit()

gq = GlossaryQuery(session)
g = gq.create_glossary(1, GlossarySchema(name="test"), ProcessingStatuses.DONE)
gq.create_glossary_record(
1,
GlossaryRecordCreate(
comment=None, source="Regional Effects", target="Региональные эффекты"
),
g.id,
)

dq = GenericDocsQuery(session)
dq.set_document_glossaries(dq.get_document(1), [g])

response = user_logged_client.get(
"/document/1/glossary_search?query=Nonexistent Term"
)
assert response.status_code == 200
assert response.json() == []


def test_doc_glossary_search_returns_404_for_nonexistent_document(
user_logged_client: TestClient,
):
response = user_logged_client.get("/document/99/glossary_search?query=test")
assert response.status_code == 404
2 changes: 1 addition & 1 deletion backend/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def translate_segments(
]
data_to_translate: list[LineWithGlossaries] = []
for segment in segments_to_translate:
glossary_records = GlossaryQuery(session).get_glossary_records_for_segment(
glossary_records = GlossaryQuery(session).get_glossary_records_for_phrase(
segment, glossary_ids
)
data_to_translate.append(
Expand Down
21 changes: 19 additions & 2 deletions frontend/mocks/documentMocks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {http, HttpResponse} from 'msw'
import {faker, fakerRU} from '@faker-js/faker'

import {glossaries} from './glossaryMocks'
import {AwaitedReturnType} from './utils'
import {
getComments,
getDoc,
getDocRecords,
getDocs,
getGlossaries,
getRecordGlossaryRecords,
getRecordSubstitutions,
updateDocRecord,
Expand Down Expand Up @@ -209,7 +211,7 @@ const segments: DocumentRecord[] = [
has_comments: true,
translation_src: 'mt',
},
{
{
id: 10003,
approved: true,
source: 'Adventure Hooks',
Expand Down Expand Up @@ -263,6 +265,22 @@ export const documentMocks = [
}
}
),
http.get<{id: string}>(
'http://localhost:8000/document/:id/glossaries',
({params}) => {
const doc = docs.find((doc) => doc.id === Number(params.id))
if (doc !== undefined) {
return HttpResponse.json<AwaitedReturnType<typeof getGlossaries>>([
{
document_id: doc.id,
glossary: glossaries[0],
},
])
} else {
return new HttpResponse(null, {status: 404})
}
}
),
http.put<{id: string}, DocumentRecordUpdate>(
'http://localhost:8000/document/record/:id',
async ({params, request}) => {
Expand Down Expand Up @@ -345,7 +363,6 @@ export const documentMocks = [
}
}
),

http.get<{segmentId: string}>(
'http://localhost:8000/document/records/:segmentId/comments',
({params}) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/mocks/glossaryMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const glossarySegments: GlossaryRecordSchema[] = new Array(125)
}
})

const glossaries: GlossaryResponse[] = [
export const glossaries: GlossaryResponse[] = [
{
id: 51,
name: 'Some glossary',
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/client/services/DocumentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import {Document} from '../schemas/Document'
import {Body_create_doc_document__post} from '../schemas/Body_create_doc_document__post'
import {StatusMessage} from '../schemas/StatusMessage'
import {DocumentRecordListResponse} from '../schemas/DocumentRecordListResponse'
import {GlossaryRecordSchema} from '../schemas/GlossaryRecordSchema'
import {CommentResponse} from '../schemas/CommentResponse'
import {CommentCreate} from '../schemas/CommentCreate'
import {MemorySubstitution} from '../schemas/MemorySubstitution'
import {GlossaryRecordSchema} from '../schemas/GlossaryRecordSchema'
import {DocumentRecordUpdateResponse} from '../schemas/DocumentRecordUpdateResponse'
import {DocumentRecordUpdate} from '../schemas/DocumentRecordUpdate'
import {DocTranslationMemory} from '../schemas/DocTranslationMemory'
Expand Down Expand Up @@ -38,6 +38,9 @@ export const deleteDoc = async (doc_id: number): Promise<StatusMessage> => {
export const getDocRecords = async (doc_id: number, page?: number | null, source?: string | null, target?: string | null): Promise<DocumentRecordListResponse> => {
return await api.get<DocumentRecordListResponse>(`/document/${doc_id}/records`, {query: {page, source, target}})
}
export const docGlossarySearch = async (doc_id: number, query: string): Promise<GlossaryRecordSchema[]> => {
return await api.get<GlossaryRecordSchema[]>(`/document/${doc_id}/glossary_search`, {query: {query}})
}
export const getComments = async (record_id: number): Promise<CommentResponse[]> => {
return await api.get<CommentResponse[]>(`/document/records/${record_id}/comments`)
}
Expand Down
Loading