Skip to content

Commit 11ba834

Browse files
authored
Merge branch 'develop' into feature/image-image-component
2 parents 477c9a0 + 74b9320 commit 11ba834

34 files changed

+762
-74
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- Updated to Angular 9
1111

1212
### Added
13+
- Apparatus entry inline visualization
14+
- Support for viewer information extracted from xml
1315
- Tags declaration visualization
1416
- Namespace declaration visualization
1517
- Rendition declaration visualization

src/app/app.config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,22 @@ export interface EditionConfig {
9696
verseNumberPrinter: number;
9797
}
9898

99+
export type EditionImagesSources = 'manifest' | 'graphics';
100+
99101
export interface FileConfig {
100102
editionUrls: string[];
101-
manifestURL: string;
103+
editionImagesSource: {
104+
[T in EditionImagesSources]: EditionImagesConfig;
105+
};
102106
logoUrl?: string;
103107
imagesFolderUrl?: string;
104108
}
105109

110+
export interface EditionImagesConfig {
111+
value: string;
112+
enabled: boolean;
113+
}
114+
106115
export interface NamedEntitiesListsConfig {
107116
defaultLabel: string;
108117
enabled: boolean;

src/app/app.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { AppConfig } from './app.config';
2424

2525
import { AdditionComponent } from './components/addition/addition.component';
2626
import { AdditionalComponent } from './components/additional/additional.component';
27+
import { ApparatusEntryDetailComponent } from './components/apparatus-entry/apparatus-entry-detail/apparatus-entry-detail.component';
28+
import { ApparatusEntryReadingsComponent } from './components/apparatus-entry/apparatus-entry-readings/apparatus-entry-readings.component';
2729
import { ApparatusEntryComponent } from './components/apparatus-entry/apparatus-entry.component';
2830
import { CharComponent } from './components/char/char.component';
2931
import { ChoiceComponent } from './components/choice/choice.component';
@@ -132,6 +134,8 @@ export function initializeApp(appConfig: AppConfig) {
132134
AdditionalComponent,
133135
AnnotatorDirective,
134136
ApparatusEntryComponent,
137+
ApparatusEntryDetailComponent,
138+
ApparatusEntryReadingsComponent,
135139
AppComponent,
136140
CharComponent,
137141
ChoiceComponent,
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<div class="card app-detail-container">
2+
<div class="card-body app-detail-content">
3+
<span>
4+
<evt-apparatus-entry-readings class="app-detail-readings" [data]="data" [template]="nestedAppsReadingsTemplate" [rdgHasCounter]="true"></evt-apparatus-entry-readings>
5+
<div *ngIf="data.nestedAppsIDs.length > 0" class="app-detail-nested-readings-container">
6+
<span *ngFor="let nesApp of nestedApps; let i = index" class="app-detail-nested-readings">
7+
<sup>{{ i + 1 }} </sup>
8+
<evt-apparatus-entry-readings [data]="nesApp" [template]="nestedAppsReadingsTemplate" [rdgHasCounter]="false"></evt-apparatus-entry-readings>
9+
</span>
10+
</div>
11+
</span>
12+
<evt-pinner [item]="data" renderer="ApparatusEntryReadings" pinType="ApparatusEntry"></evt-pinner>
13+
</div>
14+
<div class="card-footer app-detail-tabs">
15+
<ul ngbNav #appEntryTab="ngbNav" class="nav-pills">
16+
<li ngbNavItem="criticalNotes" *ngIf="data.notes.length > 0">
17+
<a class="app-detail-btn" ngbNavLink>{{'criticalNotes' | translate}}</a>
18+
<ng-template ngbNavContent>
19+
<evt-note *ngFor="let note of data.notes" [data]="note"></evt-note>
20+
</ng-template>
21+
</li>
22+
<li ngbNavItem="notSignificantRdg" *ngIf="notSignificantRdg.length > 0">
23+
<a class="app-detail-btn" ngbNavLink>{{'ortographicVariants' | translate}}</a>
24+
<ng-template ngbNavContent>
25+
<span class="d-block" *ngFor="let el of notSignificantRdg">
26+
<evt-reading [data]="el"></evt-reading>
27+
<span *ngFor="let witID of el.witIDs" class="font-italic"> {{ witID }} </span>
28+
</span>
29+
</ng-template>
30+
</li>
31+
<li ngbNavItem="info">
32+
<a class="app-detail-btn" ngbNavLink>{{'info' | translate}}</a>
33+
<ng-template ngbNavContent>
34+
<div class="info-lemma-wrapper" *ngIf="data.lemma">
35+
<span>{{'metadataForLemma' | translate}} </span>
36+
<evt-reading *ngIf="data.nestedAppsIDs.length === 0" class="info-rdg" [data]="data.lemma"></evt-reading>
37+
<span *ngIf="data.nestedAppsIDs.length > 0" class="info-rdg">
38+
<ng-container *ngTemplateOutlet="nestedAppsReadingsTemplate; context: { rdgHasCounter: rdgHasCounter }"></ng-container>
39+
</span>
40+
<span class="d-block ml-2" *ngFor="let metadata of rdgMetadata | keyvalue">
41+
<span class="info-label" *ngIf="metadata.key !== 'id'">{{ metadata.key }}:</span> {{ metadata.value }}
42+
</span>
43+
<span class="d-block ml-2" *ngIf="(rdgMetadata | keyvalue).length === 0">
44+
<span class="font-italic">{{'noDataAvailable' | translate}}</span>
45+
</span>
46+
</div>
47+
<div>
48+
<span class="more-info-label">{{'moreInfoAboutApp' | translate}}</span>
49+
<ng-container *ngFor="let rdg of readings">
50+
<div *ngIf="(rdg.attributes | keyvalue).length !== 0" class="mb-2">
51+
<span>{{'metadataFor' | translate}} </span>
52+
<ng-container *ngIf="rdg.content.length !== 0">
53+
<evt-reading *ngIf="data.nestedAppsIDs.length === 0" class="info-rdg" [data]="rdg"></evt-reading>
54+
<ng-container *ngIf="data.nestedAppsIDs.length > 0">
55+
<ng-container *ngFor="let c of rdg.content">
56+
<evt-content-viewer class="info-rdg" *ngIf="!isAppEntry(c)" [content]="c"></evt-content-viewer>
57+
<evt-reading class="info-rdg" *ngIf="isAppEntry(c)" [data]="c.lemma"></evt-reading>
58+
</ng-container>
59+
</ng-container>
60+
</ng-container>
61+
<span *ngIf="rdg.content.length === 0" class="font-italic info-rdg">{{'omit' | translate}}</span>
62+
<span *ngIf="rdg.attributes.wit" class="d-block ml-2">
63+
<span class="info-label">{{'wit' | translate}}</span> {{rdg.attributes.wit}}
64+
</span>
65+
<ng-container *ngFor="let metadata of rdgMetadata | keyvalue">
66+
<span class="d-block ml-2" *ngIf="metadata.key !== 'wit'">
67+
<span class="info-label">{{ metadata.key }}:</span> {{ metadata.value }}
68+
</span>
69+
</ng-container>
70+
</div>
71+
</ng-container>
72+
</div>
73+
</ng-template>
74+
</li>
75+
<li ngbNavItem="xml">
76+
<a class="app-detail-btn" ngbNavLink>{{'xml' | translate}}</a>
77+
<ng-template ngbNavContent>
78+
<pre>{{ data.originalEncoding | xmlBeautify }}</pre>
79+
</ng-template>
80+
</li>
81+
</ul>
82+
<div [ngbNavOutlet]="appEntryTab" class="tab-content"></div>
83+
</div>
84+
</div>
85+
86+
<ng-template #nestedAppsReadingsTemplate let-rdgHasCounter="rdgHasCounter">
87+
<ng-container *ngFor="let c of data.lemma.content">
88+
<evt-content-viewer *ngIf="!isAppEntry(c)" class="{{ data.class }}" [content]="c"></evt-content-viewer>
89+
90+
<ng-container *ngIf="isAppEntry(c)">
91+
<!-- Handle reading of nested app with no further nesting -->
92+
<evt-reading [data]="c.lemma"></evt-reading>
93+
<sup *ngIf="rdgHasCounter">{{ getNestedAppPos(c.id) + 1 }} </sup>
94+
95+
<!-- Handle reading of nested app with further nesting -->
96+
<ng-container *ngIf="c.nestedAppsIDs.length > 0">
97+
<ng-container *ngFor="let nesID of c.nestedAppsIDs; let i = index">
98+
<evt-reading [data]="getNestedAppLemma(nesID)"></evt-reading>
99+
<sup *ngIf="rdgHasCounter">{{ getNestedAppPos(nesID) + 1 }}</sup>
100+
</ng-container>
101+
</ng-container>
102+
</ng-container>
103+
</ng-container>
104+
</ng-template>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
@import "../../../../assets/scss/themes";
2+
3+
.app-detail-container {
4+
top: -0.063rem;
5+
z-index: 0;
6+
border-radius: 0;
7+
cursor: auto;
8+
@include themify($themes) {
9+
background-color: themed("appEntryBoxBackground");
10+
}
11+
}
12+
13+
.app-detail-content,
14+
.app-detail-tabs {
15+
background-color: transparent;
16+
font-size: 1.063rem;
17+
}
18+
19+
.app-detail-content {
20+
display: flex;
21+
justify-content: space-between;
22+
padding: 0.313rem;
23+
}
24+
25+
.app-detail-readings {
26+
display: block;
27+
}
28+
29+
.app-detail-nested-readings {
30+
display: block;
31+
margin-left: 0.938rem;
32+
font-size: 1rem;
33+
}
34+
35+
.app-detail-tabs {
36+
font-size: 1rem;
37+
margin: 0 0.313rem 0 0.313rem;
38+
padding: 0.313rem 0 0 0;
39+
.nav-link {
40+
background-color: transparent;
41+
color: #000000;
42+
line-height: 1;
43+
padding: 0.25rem 0.375rem;
44+
cursor: pointer;
45+
border-radius: 0;
46+
&.active {
47+
color: #000000;
48+
}
49+
}
50+
.nav-pills,
51+
.tab-content {
52+
margin-right: -0.313rem;
53+
margin-left: -0.313rem;
54+
}
55+
.nav-link.active,
56+
.tab-content {
57+
@include themify($themes) {
58+
background-color: themed("appEntryBoxActiveTabBg");
59+
}
60+
}
61+
.tab-content {
62+
padding: 0.625rem 0.813rem;
63+
max-height: 12.5rem;
64+
overflow: auto;
65+
.info-lemma-wrapper {
66+
@include themify($themes) {
67+
border-bottom: 1px solid themed("baseBorder");
68+
}
69+
padding-bottom: 0.438rem;
70+
margin-bottom: 0.625rem;
71+
}
72+
.info-rdg {
73+
font-style: italic;
74+
font-weight: 600;
75+
font-size: 1.063rem;
76+
}
77+
.info-label {
78+
font-size: 0.813rem;
79+
text-transform: uppercase;
80+
font-weight: 600;
81+
}
82+
.more-info-label {
83+
display: block;
84+
font-size: 0.813rem;
85+
font-weight: 600;
86+
text-transform: uppercase;
87+
margin-bottom: 0.25rem;
88+
}
89+
pre {
90+
white-space: pre-wrap;
91+
font-size: 75%;
92+
margin-bottom: 0;
93+
margin-top: -1rem;
94+
}
95+
}
96+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { ApparatusEntryDetailComponent } from './apparatus-entry-detail.component';
4+
5+
describe('ApparatusEntryDetailComponent', () => {
6+
let component: ApparatusEntryDetailComponent;
7+
let fixture: ComponentFixture<ApparatusEntryDetailComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [ ApparatusEntryDetailComponent ]
12+
})
13+
.compileComponents();
14+
});
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(ApparatusEntryDetailComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
2+
import { ApparatusEntry, GenericElement, Reading } from '../../../models/evt-models';
3+
import { register } from '../../../services/component-register.service';
4+
import { EVTModelService } from '../../../services/evt-model.service';
5+
@Component({
6+
selector: 'evt-apparatus-entry-detail',
7+
templateUrl: './apparatus-entry-detail.component.html',
8+
styleUrls: ['./apparatus-entry-detail.component.scss'],
9+
changeDetection: ChangeDetectionStrategy.OnPush,
10+
})
11+
12+
@register(ApparatusEntryDetailComponent)
13+
export class ApparatusEntryDetailComponent implements OnInit {
14+
@Input() data: ApparatusEntry;
15+
nestedApps: ApparatusEntry[] = [];
16+
rdgHasCounter = false;
17+
18+
get significantRdg(): Reading[] {
19+
return this.data.readings.filter((rdg) => rdg.significant);
20+
}
21+
22+
get notSignificantRdg(): Reading[] {
23+
return this.data.readings.filter((rdg) => !rdg.significant);
24+
}
25+
26+
get readings(): Reading[] {
27+
return [this.data.lemma, ...this.significantRdg, ...this.notSignificantRdg]
28+
}
29+
30+
get rdgMetadata() {
31+
return Object.keys(this.data.attributes).filter((key) => key !== 'id')
32+
.reduce((obj, key) => ({
33+
...obj,
34+
[key]: this.data.attributes[key],
35+
}), {});
36+
}
37+
38+
constructor(
39+
public evtModelService: EVTModelService,
40+
) {
41+
}
42+
43+
ngOnInit() {
44+
if (this.data.nestedAppsIDs.length > 0) {
45+
this.recoverNestedApps(this.data);
46+
}
47+
}
48+
49+
recoverNestedApps(app: ApparatusEntry) {
50+
const nesApps = app.lemma.content.filter((c: ApparatusEntry | GenericElement) => c.type === ApparatusEntry);
51+
nesApps.forEach((nesApp: ApparatusEntry) => {
52+
this.nestedApps = this.nestedApps.concat(nesApp);
53+
if (nesApp.nestedAppsIDs.length > 0) {
54+
this.recoverNestedApps(nesApp);
55+
}
56+
});
57+
}
58+
59+
isAppEntry(item: GenericElement | ApparatusEntry): boolean {
60+
return item.type === ApparatusEntry;
61+
}
62+
63+
getNestedAppLemma(appId: string): Reading {
64+
return this.nestedApps.find((c) => c.id === appId).lemma;
65+
}
66+
67+
getNestedAppPos(appId: string): number {
68+
return this.nestedApps.findIndex((nesApp) => nesApp.id === appId);
69+
}
70+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<span class="app-entry-reading">
2+
<!--
3+
It's necessary to handle both readings with and without nested apps, because nested apps inside app-entry-detail have different behaviour,
4+
so we can't use apparatus-entry-component to render them.
5+
-->
6+
<evt-reading *ngIf="data.nestedAppsIDs.length === 0" [data]="data.lemma"></evt-reading>
7+
8+
<ng-container *ngIf="data.nestedAppsIDs.length > 0">
9+
<ng-container *ngTemplateOutlet="template context: { rdgHasCounter: rdgHasCounter }"></ng-container>
10+
</ng-container>
11+
12+
<ng-container *ngIf="data.lemma.content.length > 0">
13+
<span *ngFor="let witID of data.lemma.witIDs"> {{ witID }}</span>
14+
</ng-container>
15+
<span>] </span>
16+
</span>
17+
18+
<span class="app-entry-reading" *ngFor="let el of significantRdg">
19+
<evt-reading *ngIf="el.content.length !== 0" [data]="el"></evt-reading>
20+
<span class="font-italic" *ngIf="el.content.length === 0">omit.</span>
21+
<!-- TODO: handle lacunastart and lacunaend -->
22+
<ng-container *ngFor="let witID of el.witIDs">
23+
<span *ngFor="let wit of getWits$(witID) | async" class="font-italic"> {{ wit }} </span>
24+
</ng-container>
25+
</span>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.app-entry-reading {
2+
display: inline-block;
3+
padding-right: 0.5rem;
4+
line-height: 1;
5+
}

0 commit comments

Comments
 (0)