Skip to content

Commit

Permalink
Merge pull request #45 from UUDigitalHumanitieslab/feature/type-speci…
Browse files Browse the repository at this point in the history
…fic-highlight

Feature/type specific highlight
  • Loading branch information
XanderVertegaal authored Jul 26, 2024
2 parents 88153ae + 93fe007 commit 06e5d95
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 126 deletions.
98 changes: 57 additions & 41 deletions backend/aethel_db/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ def aethel_status():
return dataset is not None


@dataclass
class AethelSamplePhrase:
display: str
highlight: bool


@dataclass
class AethelListSample:
name: str
sentence: str
phrases: List[AethelSamplePhrase] = field(default_factory=list)


@dataclass
Expand All @@ -48,29 +54,16 @@ class AethelListResponse:
results: List[AethelListItem] = field(default_factory=list)
error: Optional[str] = None

def existing_result(
self, lemma: str, word: str, type: str
) -> Optional[AethelListItem]:
def get_or_create_result(self, lemma: str, word: str, type: str) -> AethelListItem:
"""
Return an existing result with the same lemma, word, and type, if it exists.
Return an existing result with the same lemma, word, and type, or create a new one if it doesn't exist.
"""
for item in self.results:
if item.lemma == lemma and item.type == type and item.word == word:
return item
return None

def add_result(
self, lemma: str, word: str, type: str, sample_name: str, sample_sentence: str
) -> None:
result_item = self.existing_result(lemma, word, type)

if result_item is None:
result_item = AethelListItem(lemma=lemma, word=word, type=type)
self.results.append(result_item)

result_item.samples.append(
AethelListSample(name=sample_name, sentence=sample_sentence)
)
for result in self.results:
if result.lemma == lemma and result.type == type and result.word == word:
return result
new_result = AethelListItem(lemma=lemma, word=word, type=type, samples=[])
self.results.append(new_result)
return new_result

def json_response(self) -> JsonResponse:
results = [result.serialize() for result in self.results]
Expand All @@ -90,33 +83,52 @@ def get(self, request: HttpRequest) -> JsonResponse:
if query_input is None or len(query_input) < 3:
return AethelListResponse().json_response()

# First we select all relevant samples from the dataset that contain the query string.
query_result = search(
bank=dataset.samples,
query=in_word(query_input) | in_lemma(query_input),
)

def item_contains_query_string(item: LexicalItem) -> bool:
def item_contains_query_string(item: LexicalItem, query_input: str) -> bool:
"""
Checks if a LexicalItem contains a given input string in its word or its lemma.
"""
return (
query_input.lower() in item.lemma.lower()
or query_input.lower() in item.word.lower()
)

response_object = AethelListResponse()
# Then we loop over the samples and extract what we need from them (lemma, word, type etc.).

# First we select all relevant samples from the dataset that contain the query string.
query_result = search(
bank=dataset.samples,
query=in_word(query_input) | in_lemma(query_input),
)

for sample in query_result:
lexical_phrases = sample.lexical_phrases
for phrase in lexical_phrases:
for phrase_index, phrase in enumerate(sample.lexical_phrases):
for item in phrase.items:
if item_contains_query_string(item):
response_object.add_result(
item.lemma,
item.word,
str(phrase.type),
sample.name,
sample.sentence,
if item_contains_query_string(item, query_input):
result = response_object.get_or_create_result(
lemma=item.lemma, word=item.word, type=str(phrase.type)
)

# Check whether we have already added this sample for this result
existing_sample = next(
(s for s in result.samples if s.name == sample.name),
None,
)

if existing_sample:
existing_sample.phrases[phrase_index].highlight = True
else:
new_sample = AethelListSample(name=sample.name, phrases=[])
for index, sample_phrase in enumerate(
sample.lexical_phrases
):
highlighted = index == phrase_index
new_phrase = AethelSamplePhrase(
display=sample_phrase.string,
highlight=highlighted,
)
new_sample.phrases.append(new_phrase)
result.samples.append(new_sample)

return response_object.json_response()


Expand All @@ -129,9 +141,10 @@ class AethelDetailError(Enum):
aethel_detail_status_codes = {
AethelDetailError.NO_QUERY_INPUT: status.HTTP_400_BAD_REQUEST,
AethelDetailError.SAMPLE_NOT_FOUND: status.HTTP_404_NOT_FOUND,
AethelDetailError.MULTIPLE_FOUND: status.HTTP_500_INTERNAL_SERVER_ERROR
AethelDetailError.MULTIPLE_FOUND: status.HTTP_500_INTERNAL_SERVER_ERROR,
}


@dataclass
class AethelDetailResult:
sentence: str
Expand All @@ -140,6 +153,7 @@ class AethelDetailResult:
subset: str
phrases: list[dict]


@dataclass
class AethelDetailResponse:
result: Optional[AethelDetailResult] = None
Expand All @@ -156,7 +170,9 @@ def parse_sample(self, sample: Sample) -> None:

def json_response(self) -> JsonResponse:
result = asdict(self.result) if self.result else None
status_code = aethel_detail_status_codes[self.error] if self.error else status.HTTP_200_OK
status_code = (
aethel_detail_status_codes[self.error] if self.error else status.HTTP_200_OK
)

return JsonResponse(
{
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/app/aethel/aethel.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ <h2 class="title is-2" i18n>Æthel</h2>
<ng-template pTemplate="rowexpansion" let-row>
@for (sample of row.samples; track $index) {
<tr class="expanded-row">
<td
colspan="4"
[innerHTML]="sample.sentence | highlight: row.word"
></td>
<td colspan="4">
@for (phrase of sample.phrases; track phrase.index) {
<span [class.highlight]="phrase.highlight">{{ phrase.display }} </span>
}
</td>
<td class="button-container" colspan="1">
<a
[routerLink]="getSampleURL(sample.name)"
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/app/aethel/aethel.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@
text-align: center;
vertical-align: middle;
}

.highlight {
font-weight: bold;
}
2 changes: 0 additions & 2 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { ExportButtonComponent } from "./spindle/export-button/export-button.com
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { TableModule } from "primeng/table";
import { AethelComponent } from "./aethel/aethel.component";
import { HighlightPipe } from "./shared/pipes/highlight.pipe";
import { SpindleAboutComponent } from "./spindle/spindle-about/spindle-about.component";
import { SpindleNotationComponent } from "./spindle/spindle-notation/spindle-notation.component";
import { ReferencesComponent } from "./references/references.component";
Expand All @@ -39,7 +38,6 @@ import { SampleComponent } from "./sample/sample.component";
SpindleNotationComponent,
ReferencesComponent,
AethelComponent,
HighlightPipe,
ProofPipe,
SampleComponent,
],
Expand Down
57 changes: 0 additions & 57 deletions frontend/src/app/shared/pipes/highlight.pipe.spec.ts

This file was deleted.

15 changes: 0 additions & 15 deletions frontend/src/app/shared/pipes/highlight.pipe.ts

This file was deleted.

14 changes: 7 additions & 7 deletions frontend/src/app/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ export interface SpindleReturn {
lexical_phrases: LexicalPhrase[];
proof: Record<string, unknown> | null;
}

export interface AethelSample {
name: string;
sentence: string;
}

export interface AethelListReturnItem {
lemma: string;
word: string;
type: string;
samples: AethelSample[];
samples: {
name: string;
phrases: {
display: string;
highlight: boolean;
}[];
}[];
}

export interface AethelListReturn {
Expand Down

0 comments on commit 06e5d95

Please sign in to comment.