diff --git a/frontend/src/app/annotate/annotate.component.html b/frontend/src/app/annotate/annotate.component.html index 5c72471..ea0d9b0 100644 --- a/frontend/src/app/annotate/annotate.component.html +++ b/frontend/src/app/annotate/annotate.component.html @@ -62,31 +62,23 @@ }
@if (browsing) { - + buttonStyle="secondary" + fullWidth + i18n-label + /> } @else { - + buttonStyle="secondary" + fullWidth + i18n-label + /> }
diff --git a/frontend/src/app/annotate/annotate.component.ts b/frontend/src/app/annotate/annotate.component.ts index 8d9b34b..2b4c677 100644 --- a/frontend/src/app/annotate/annotate.component.ts +++ b/frontend/src/app/annotate/annotate.component.ts @@ -12,6 +12,7 @@ import { CommonModule } from "@angular/common"; import { Dataset } from "@/types"; import { AppModeService } from "@/services/app-mode.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { IconButtonComponent } from "@/shared/icon-button/icon-button.component"; @Component({ selector: "la-annotate", @@ -23,6 +24,7 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; SearchComponent, FontAwesomeModule, CommonModule, + IconButtonComponent, ], templateUrl: "./annotate.component.html", styleUrl: "./annotate.component.scss", diff --git a/frontend/src/app/annotate/annotation-input/annotation-input.component.html b/frontend/src/app/annotate/annotation-input/annotation-input.component.html index fbb434e..31a969c 100644 --- a/frontend/src/app/annotate/annotation-input/annotation-input.component.html +++ b/frontend/src/app/annotate/annotation-input/annotation-input.component.html @@ -12,45 +12,28 @@
- + i18n-label + /> @if ((viewMode === 'edit' || viewMode === 'add') && userProblem) { - + i18n-label + /> } @else if (userProblem) { - + }
} diff --git a/frontend/src/app/annotate/annotation-input/annotation-input.component.ts b/frontend/src/app/annotate/annotation-input/annotation-input.component.ts index 6b21cfd..7cabc3b 100644 --- a/frontend/src/app/annotate/annotation-input/annotation-input.component.ts +++ b/frontend/src/app/annotate/annotation-input/annotation-input.component.ts @@ -21,6 +21,7 @@ import { ParseService } from "@/services/parse.service"; import { FontAwesomeModule } from "@fortawesome/angular-fontawesome"; import { AppModeService } from "@/services/app-mode.service"; import { ToastService } from "@/services/toast.service"; +import { IconButtonComponent } from "@/shared/icon-button/icon-button.component"; export type ParseInputForm = FormGroup<{ id: FormControl; @@ -49,6 +50,7 @@ export type ParseInput = ReturnType; ReactiveFormsModule, ProblemDetailsComponent, FontAwesomeModule, + IconButtonComponent ], templateUrl: "./annotation-input.component.html", styleUrl: "./annotation-input.component.scss", diff --git a/frontend/src/app/annotate/annotation-input/knowledge-base-form/knowledge-base-form.component.html b/frontend/src/app/annotate/annotation-input/knowledge-base-form/knowledge-base-form.component.html index e3c9e90..43236c7 100644 --- a/frontend/src/app/annotate/annotation-input/knowledge-base-form/knowledge-base-form.component.html +++ b/frontend/src/app/annotate/annotation-input/knowledge-base-form/knowledge-base-form.component.html @@ -8,25 +8,23 @@ > Knowledge base items @if (viewMode === 'add' || viewMode === 'edit') { - + i18n-label + outline + /> }
    - @for (kbItem of kbControls; let i = $index; track `${i}-${kbItem.value.entity1}-${kbItem.value.relationship}-${kbItem.value.entity2}`) { + @for (kbItem of kbControls; let i = $index; track + `${i}-${kbItem.value.entity1}-${kbItem.value.relationship}-${kbItem.value.entity2}`) + {
  • @if (viewMode === 'add' || viewMode === 'edit') {
    @@ -60,7 +58,7 @@ (click)="removeKnowledgeBaseItem(i)" aria-labelledby="remove-kb-item" title="Remove knowledge base item" - title-i18n + i18n-title > = { @Component({ selector: "la-knowledge-base-form", standalone: true, - imports: [CommonModule, ReactiveFormsModule, FontAwesomeModule], + imports: [CommonModule, ReactiveFormsModule, FontAwesomeModule, IconButtonComponent], templateUrl: "./knowledge-base-form.component.html", styleUrls: ["./knowledge-base-form.component.scss"], }) diff --git a/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.html b/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.html index b3aa888..9c1c9f0 100644 --- a/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.html +++ b/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.html @@ -8,24 +8,21 @@ > Premises @if (viewMode === 'add' || viewMode === 'edit') { - + size="sm" + iconPosition="right" + i18n-label + outline + /> }
      - @for (control of premiseControls; let i = $index; track `${i}-${control.value}`) { + @for (control of premiseControls; let i = $index; track + `${i}-${control.value}`) {
    • -

      Each problem must have a hypothesis.

      +

      + Each problem must have a hypothesis. +

      diff --git a/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.ts b/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.ts index e5b1642..3ba9922 100644 --- a/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.ts +++ b/frontend/src/app/annotate/annotation-input/premises-form/premises-form.component.ts @@ -5,6 +5,7 @@ import { FontAwesomeModule } from "@fortawesome/angular-fontawesome"; import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; import { ParseInputForm } from "../annotation-input.component"; import { AppModeService } from "@/services/app-mode.service"; +import { IconButtonComponent } from "@/shared/icon-button/icon-button.component"; export interface Premises { premises: string[]; @@ -14,7 +15,7 @@ export interface Premises { @Component({ selector: "la-premises-form", standalone: true, - imports: [ReactiveFormsModule, CommonModule, FontAwesomeModule], + imports: [ReactiveFormsModule, CommonModule, FontAwesomeModule, IconButtonComponent], templateUrl: "./premises-form.component.html", styleUrl: "./premises-form.component.scss", }) diff --git a/frontend/src/app/annotate/navigator/navigator.component.html b/frontend/src/app/annotate/navigator/navigator.component.html index 0b08cf1..d51b363 100644 --- a/frontend/src/app/annotate/navigator/navigator.component.html +++ b/frontend/src/app/annotate/navigator/navigator.component.html @@ -3,84 +3,63 @@ diff --git a/frontend/src/app/annotate/navigator/navigator.component.ts b/frontend/src/app/annotate/navigator/navigator.component.ts index 59fc445..a599e3a 100644 --- a/frontend/src/app/annotate/navigator/navigator.component.ts +++ b/frontend/src/app/annotate/navigator/navigator.component.ts @@ -10,11 +10,12 @@ import { import { CommonModule } from "@angular/common"; import { Router } from "@angular/router"; import { ProblemService } from "@/services/problem.service"; +import { IconButtonComponent } from "@/shared/icon-button/icon-button.component"; @Component({ selector: "la-navigator", standalone: true, - imports: [FontAwesomeModule, CommonModule], + imports: [FontAwesomeModule, CommonModule, IconButtonComponent], templateUrl: "./navigator.component.html", styleUrl: "./navigator.component.scss", }) diff --git a/frontend/src/app/annotate/search/search.component.html b/frontend/src/app/annotate/search/search.component.html index 9cf6dd5..6435d4b 100644 --- a/frontend/src/app/annotate/search/search.component.html +++ b/frontend/src/app/annotate/search/search.component.html @@ -47,13 +47,17 @@
    - + i18n-label + outline + fullWidth + />
    diff --git a/frontend/src/app/annotate/search/search.component.ts b/frontend/src/app/annotate/search/search.component.ts index cc030e6..96c8b59 100644 --- a/frontend/src/app/annotate/search/search.component.ts +++ b/frontend/src/app/annotate/search/search.component.ts @@ -18,6 +18,7 @@ import { import { datasetLabels, entailmentLabels } from "@/shared/displayTextMappings"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { ActivatedRoute, Params, Router } from "@angular/router"; +import { IconButtonComponent } from "@/shared/icon-button/icon-button.component"; interface SearchParams { dataset: Dataset | null; @@ -39,6 +40,7 @@ type SearchParamsForm = { FontAwesomeModule, ReactiveFormsModule, FilterSelectComponent, + IconButtonComponent ], templateUrl: "./search.component.html", styleUrl: "./search.component.scss", diff --git a/frontend/src/app/shared/icon-button/icon-button.component.html b/frontend/src/app/shared/icon-button/icon-button.component.html new file mode 100644 index 0000000..563e306 --- /dev/null +++ b/frontend/src/app/shared/icon-button/icon-button.component.html @@ -0,0 +1,31 @@ +@let iconValue = icon(); @let position = iconPosition(); + +@if (titleId()) { +{{ buttonTitle() }} +} diff --git a/frontend/src/app/shared/icon-button/icon-button.component.scss b/frontend/src/app/shared/icon-button/icon-button.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/app/shared/icon-button/icon-button.component.spec.ts b/frontend/src/app/shared/icon-button/icon-button.component.spec.ts new file mode 100644 index 0000000..d2a2c30 --- /dev/null +++ b/frontend/src/app/shared/icon-button/icon-button.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { IconButtonComponent } from './icon-button.component'; + +describe('IconButtonComponent', () => { + let component: IconButtonComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [IconButtonComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(IconButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/shared/icon-button/icon-button.component.ts b/frontend/src/app/shared/icon-button/icon-button.component.ts new file mode 100644 index 0000000..2e898eb --- /dev/null +++ b/frontend/src/app/shared/icon-button/icon-button.component.ts @@ -0,0 +1,52 @@ +import { booleanAttribute, Component, computed, input } from '@angular/core'; +import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; +import { IconProp } from '@fortawesome/angular-fontawesome/types'; + +@Component({ + selector: 'la-icon-button', + imports: [FontAwesomeModule], + templateUrl: './icon-button.component.html', + styleUrl: './icon-button.component.scss' +}) +export class IconButtonComponent { + public icon = input(null); + public label = input(null); + public buttonTitle = input(null); + public iconPosition = input<'left' | 'right'>('left'); + public size = input<'sm' | 'md' | 'lg'>('md'); + public buttonType = input<'button' | 'submit' | 'reset'>('button'); + public buttonStyle = input<"primary" | "secondary" | "success" | "danger">("primary"); + public disabled = input(false, { transform: booleanAttribute }); + public outline = input(false, { transform: booleanAttribute }); + public fullWidth = input(false, { transform: booleanAttribute }); + + public buttonClasses = computed(() => { + const classes = ["btn", "d-flex", "align-items-center", "justify-content-center"]; + if (this.outline()) { + classes.push(`btn-outline-${this.buttonStyle()}`); + } else { + classes.push(`btn-${this.buttonStyle()}`); + } + + if (this.size() === 'sm') { + classes.push('btn-sm'); + } else if (this.size() === 'lg') { + classes.push('btn-lg'); + } + + if (this.fullWidth()) { + classes.push('w-100'); + } + + return classes.join(" "); + }); + + public titleId = computed(() => { + const title = this.buttonTitle(); + if (!title) { + return null; + } + return title.replace(/\s+/g, '-').toLowerCase(); + }); + +}