feat: update components

This commit is contained in:
2023-11-15 20:43:36 +01:00
parent 4833155721
commit 0a5cf19b8a
137 changed files with 960 additions and 885 deletions

View File

@@ -19,6 +19,6 @@
"test": "npx prettier --config index.json --check \"test/*.js\"" "test": "npx prettier --config index.json --check \"test/*.js\""
}, },
"peerDependencies": { "peerDependencies": {
"prettier": "3.0.3" "prettier": "3.1.0"
} }
} }

View File

@@ -17,11 +17,10 @@ module.exports = {
...require('@openstapps/prettier-config'), ...require('@openstapps/prettier-config'),
overrides: [ overrides: [
{ {
files: 'src/**/*.html', files: ['*.html'],
options: { options: {
parser: 'angular', parser: 'angular',
}, },
}, },
], ],
ignorePath: ['.prettierignore', '../../.gitignore'],
}; };

View File

@@ -184,7 +184,6 @@
"typescript": "5.2.2", "typescript": "5.2.2",
"webpack-bundle-analyzer": "4.7.0" "webpack-bundle-analyzer": "4.7.0"
}, },
"prettier": "@openstapps/prettier-config",
"cordova": { "cordova": {
"plugins": {}, "plugins": {},
"platforms": [ "platforms": [

View File

@@ -49,7 +49,10 @@ export class SharedAxisChoreographer<T> {
*/ */
currentValue: T; currentValue: T;
constructor(initialValue: T, readonly pages?: T[]) { constructor(
initialValue: T,
readonly pages?: T[],
) {
this.currentValue = initialValue; this.currentValue = initialValue;
this.expectedValue = initialValue; this.expectedValue = initialValue;
} }

View File

@@ -14,18 +14,18 @@
--> -->
<div [ngSwitch]="content.type"> <div [ngSwitch]="content.type">
<markdown [data]="'value' | translateSimple : content" *ngSwitchCase="'markdown'"></markdown> <markdown [data]="'value' | translateSimple: content" *ngSwitchCase="'markdown'"></markdown>
<div *ngSwitchCase="'section'"> <div *ngSwitchCase="'section'">
<ion-card *ngIf="content.card; else noCard"> <ion-card *ngIf="content.card; else noCard">
<ion-card-header> <ion-card-header>
<ion-card-title>{{ 'title' | translateSimple : content }}</ion-card-title> <ion-card-title>{{ 'title' | translateSimple: content }}</ion-card-title>
</ion-card-header> </ion-card-header>
<ion-card-content> <ion-card-content>
<about-page-content [content]="content.content"></about-page-content> <about-page-content [content]="content.content"></about-page-content>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<ng-template #noCard> <ng-template #noCard>
<h2>{{ 'title' | translateSimple : content }}</h2> <h2>{{ 'title' | translateSimple: content }}</h2>
<about-page-content [content]="content.content"></about-page-content> <about-page-content [content]="content.content"></about-page-content>
</ng-template> </ng-template>
</div> </div>
@@ -38,6 +38,6 @@
</ion-grid> </ion-grid>
<ion-item *ngSwitchCase="'router link'" [routerLink]="content.link"> <ion-item *ngSwitchCase="'router link'" [routerLink]="content.link">
<ion-icon *ngIf="content.icon" [name]="content.icon" slot="start"></ion-icon> <ion-icon *ngIf="content.icon" [name]="content.icon" slot="start"></ion-icon>
<ion-label>{{ 'title' | translateSimple : content }}</ion-label> <ion-label>{{ 'title' | translateSimple: content }}</ion-label>
</ion-item> </ion-item>
</div> </div>

View File

@@ -31,7 +31,10 @@ export class AboutPageComponent implements OnInit {
version = packageJson.version; version = packageJson.version;
constructor(private readonly route: ActivatedRoute, private readonly configProvider: ConfigProvider) {} constructor(
private readonly route: ActivatedRoute,
private readonly configProvider: ConfigProvider,
) {}
async ngOnInit() { async ngOnInit() {
const route = this.route.snapshot.url.map(it => it.path).join('/'); const route = this.route.snapshot.url.map(it => it.path).join('/');

View File

@@ -18,7 +18,7 @@
<ion-buttons slot="start"> <ion-buttons slot="start">
<ion-back-button></ion-back-button> <ion-back-button></ion-back-button>
</ion-buttons> </ion-buttons>
<ion-title *ngIf="content; else titleLoading">{{ 'title' | translateSimple : content }}</ion-title> <ion-title *ngIf="content; else titleLoading">{{ 'title' | translateSimple: content }}</ion-title>
<ng-template #titleLoading> <ng-template #titleLoading>
<ion-title><ion-skeleton-text animated="true"></ion-skeleton-text></ion-title> <ion-title><ion-skeleton-text animated="true"></ion-skeleton-text></ion-title>
</ng-template> </ng-template>

View File

@@ -36,7 +36,7 @@
class="ion-text-wrap" class="ion-text-wrap"
*ngIf="assessments[key].courseOfStudy | async as course; else defaultLabel" *ngIf="assessments[key].courseOfStudy | async as course; else defaultLabel"
> >
{{ 'name' | thingTranslate : course }} ({{ 'academicDegree' | thingTranslate : course }}) {{ 'name' | thingTranslate: course }} ({{ 'academicDegree' | thingTranslate: course }})
</ion-label> </ion-label>
</div> </div>
<ng-template #defaultLabel> <ng-template #defaultLabel>

View File

@@ -14,8 +14,12 @@
--> -->
<ion-label [color]="passed ? undefined : 'danger'" <ion-label [color]="passed ? undefined : 'danger'"
>{{ (_item.grade | isNumeric) ? (_item.grade | numberLocalized : >{{
'minimumFractionDigits:1,maximumFractionDigits:1') : '' }} {{ 'status' | thingTranslate : _item | titlecase (_item.grade | isNumeric)
}}, {{ 'attempt' | propertyNameTranslate : _item }} {{ _item.attempt }} ? (_item.grade | numberLocalized: 'minimumFractionDigits:1,maximumFractionDigits:1')
: ''
}}
{{ 'status' | thingTranslate: _item | titlecase }}, {{ 'attempt' | propertyNameTranslate: _item }}
{{ _item.attempt }}
</ion-label> </ion-label>
<ion-note> {{ _item.ects }} {{ 'ects' | propertyNameTranslate : _item }}</ion-note> <ion-note> {{ _item.ects }} {{ 'ects' | propertyNameTranslate: _item }}</ion-note>

View File

@@ -16,8 +16,10 @@
<ion-card> <ion-card>
<ion-card-content> <ion-card-content>
<ion-note *ngIf="item.courseOfStudy as courseOfStudy"> <ion-note *ngIf="item.courseOfStudy as courseOfStudy">
{{ $any('courseOfStudy' | propertyNameTranslate : item) | titlecase }}: {{ 'name' | thingTranslate : {{ $any('courseOfStudy' | propertyNameTranslate: item) | titlecase }}:
$any(courseOfStudy) }} ({{ 'academicDegree' | thingTranslate : $any(courseOfStudy) }}) {{ 'name' | thingTranslate: $any(courseOfStudy) }} ({{
'academicDegree' | thingTranslate: $any(courseOfStudy)
}})
</ion-note> </ion-note>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -14,6 +14,6 @@
--> -->
<div class="container"> <div class="container">
<h2 class="name">{{ 'name' | thingTranslate : item }} {{ item.date ? (item.date | amDateFormat) : '' }}</h2> <h2 class="name">{{ 'name' | thingTranslate: item }} {{ item.date ? (item.date | amDateFormat) : '' }}</h2>
<assessment-base-info [item]="item"></assessment-base-info> <assessment-base-info [item]="item"></assessment-base-info>
</div> </div>

View File

@@ -22,7 +22,10 @@ import {AuthHelperService} from './auth-helper.service';
providedIn: 'root', providedIn: 'root',
}) })
export class AuthGuardService implements CanActivate { export class AuthGuardService implements CanActivate {
constructor(private authHelper: AuthHelperService, private router: Router) {} constructor(
private authHelper: AuthHelperService,
private router: Router,
) {}
public async canActivate(route: ActivatedProtectedRouteSnapshot, _state: RouterStateSnapshot) { public async canActivate(route: ActivatedProtectedRouteSnapshot, _state: RouterStateSnapshot) {
if (route.queryParamMap.get('token')) { if (route.queryParamMap.get('token')) {

View File

@@ -134,9 +134,9 @@ export class ScheduleSyncService {
private formatChanges(changes: ChangesOf<SCDateSeries, DateSeriesRelevantData>): string[] { private formatChanges(changes: ChangesOf<SCDateSeries, DateSeriesRelevantData>): string[] {
return changes.changes.map( return changes.changes.map(
change => change =>
`${ `${this.translator.translator.translatedPropertyNames<SCDateSeries>(SCThingType.DateSeries)?.[
this.translator.translator.translatedPropertyNames<SCDateSeries>(SCThingType.DateSeries)?.[change] change
}: ${formatRelevantKeys[change]( ]}: ${formatRelevantKeys[change](
changes.new[change] as never, changes.new[change] as never,
this.dateFormatPipe, this.dateFormatPipe,
this.durationFormatPipe, this.durationFormatPipe,

View File

@@ -34,7 +34,7 @@
<s *ngIf="iCalEvent.cancelled; else date" <s *ngIf="iCalEvent.cancelled; else date"
><ng-container [ngTemplateOutlet]="date"></ng-container> ><ng-container [ngTemplateOutlet]="date"></ng-container>
</s> </s>
<ng-template #date> {{ moment(iCalEvent.start) | amDateFormat : 'll, HH:mm' }} </ng-template> <ng-template #date> {{ moment(iCalEvent.start) | amDateFormat: 'll, HH:mm' }} </ng-template>
</ion-label> </ion-label>
<ion-note *ngIf="iCalEvent.rrule"> <ion-note *ngIf="iCalEvent.rrule">
{{ iCalEvent.rrule.interval }} {{ iCalEvent.rrule.freq | sentencecase }} {{ iCalEvent.rrule.interval }} {{ iCalEvent.rrule.freq | sentencecase }}
@@ -47,9 +47,9 @@
<div class="horizontal-flex"> <div class="horizontal-flex">
<ion-item lines="none"> <ion-item lines="none">
<ion-checkbox [(ngModel)]="includeCancelled" <ion-checkbox [(ngModel)]="includeCancelled">{{
>{{ 'schedule.toCalendar.reviewModal.INCLUDE_CANCELLED' | translate }}</ion-checkbox 'schedule.toCalendar.reviewModal.INCLUDE_CANCELLED' | translate
> }}</ion-checkbox>
</ion-item> </ion-item>
</div> </div>
<div class="horizontal-flex"> <div class="horizontal-flex">

View File

@@ -38,7 +38,10 @@ export class CalendarService {
calendarName = 'StApps'; calendarName = 'StApps';
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
constructor(readonly calendar: Calendar, private readonly configProvider: ConfigProvider) { constructor(
readonly calendar: Calendar,
private readonly configProvider: ConfigProvider,
) {
this.calendarName = (this.configProvider.getValue('name') as string) ?? 'StApps'; this.calendarName = (this.configProvider.getValue('name') as string) ?? 'StApps';
} }

View File

@@ -33,7 +33,7 @@
<ion-label> <ion-label>
{{ {{
nextEvent nextEvent
? (nextEvent!.dates | nextDateInList | amDateFormat : 'll, HH:mm') ? (nextEvent!.dates | nextDateInList | amDateFormat: 'll, HH:mm')
: ('dashboard.schedule.noEvent' | translate) : ('dashboard.schedule.noEvent' | translate)
}} }}
</ion-label> </ion-label>

View File

@@ -16,7 +16,7 @@
<ng-container *ngIf="items | async as items"> <ng-container *ngIf="items | async as items">
<ng-container *ngIf="items.length !== 0; else nothingSelected"> <ng-container *ngIf="items.length !== 0; else nothingSelected">
<ng-container *ngFor="let item of items"> <ng-container *ngFor="let item of items">
<stapps-section @fade [item]="item" [title]="'name' | thingTranslate : item"> <stapps-section @fade [item]="item" [title]="'name' | thingTranslate: item">
<ion-button slot="button-end" fill="clear" color="medium" (click)="favoritesService.delete(item)"> <ion-button slot="button-end" fill="clear" color="medium" (click)="favoritesService.delete(item)">
<ion-icon slot="icon-only" name="delete" size="24"></ion-icon> <ion-icon slot="icon-only" name="delete" size="24"></ion-icon>
</ion-button> </ion-button>

View File

@@ -42,8 +42,8 @@ export class ActionChipListComponent {
const maybeCoords = isInPlace const maybeCoords = isInPlace
? item?.inPlace?.geo.point.coordinates ? item?.inPlace?.geo.point.coordinates
: hasDirectGeo : hasDirectGeo
? item.geo.point.coordinates ? item.geo.point.coordinates
: undefined; : undefined;
const isNullIsland = maybeCoords ? maybeCoords[0] === 0 && maybeCoords[1] === 0 : false; const isNullIsland = maybeCoords ? maybeCoords[0] === 0 && maybeCoords[1] === 0 : false;
this.applicable = { this.applicable = {
locate: false, // TODO: reimplement this at a later date locate: false, // TODO: reimplement this at a later date

View File

@@ -13,7 +13,18 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, DestroyRef, inject, Input, ViewChild} from '@angular/core'; import {Component, DestroyRef, inject, Input, ViewChild} from '@angular/core';
import {IonRouterOutlet, ModalController} from '@ionic/angular/standalone'; import {
IonButton,
IonChip,
IonContent,
IonFooter,
IonIcon,
IonLabel,
IonRouterOutlet,
IonSkeletonText,
IonToolbar,
ModalController,
} from '@ionic/angular/standalone';
import {SCDateSeries, SCThing, SCThingType, SCUuid} from '@openstapps/core'; import {SCDateSeries, SCThing, SCThingType, SCUuid} from '@openstapps/core';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {ScheduleProvider} from '../../../calendar/schedule.provider'; import {ScheduleProvider} from '../../../calendar/schedule.provider';
@@ -26,6 +37,11 @@ import {AddEventStates, AddEventStatesMap} from './add-event-action-chip.config'
import {EditEventSelectionComponent} from '../edit-event-selection.component'; import {EditEventSelectionComponent} from '../edit-event-selection.component';
import {AddEventReviewModalComponent} from '../../../calendar/add-event-review-modal.component'; import {AddEventReviewModalComponent} from '../../../calendar/add-event-review-modal.component';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {AsyncPipe, NgIf, TitleCasePipe} from '@angular/common';
import {DataModule} from '../../data.module';
import {TranslateModule} from '@ngx-translate/core';
import {EditModalComponent} from '../../../../util/edit-modal.component';
import {IonContentParallaxDirective} from '../../../../util/ion-content-parallax.directive';
/** /**
* Shows a horizontal list of action chips * Shows a horizontal list of action chips
@@ -33,8 +49,26 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'stapps-add-event-action-chip', selector: 'stapps-add-event-action-chip',
templateUrl: 'add-event-action-chip.html', templateUrl: 'add-event-action-chip.html',
styleUrls: ['add-event-action-chip.scss'], styleUrl: 'add-event-action-chip.scss',
animations: [chipSkeletonTransition, chipTransition], animations: [chipSkeletonTransition, chipTransition],
standalone: true,
imports: [
IonChip,
AsyncPipe,
NgIf,
DataModule,
IonContent,
IonIcon,
IonLabel,
TranslateModule,
EditModalComponent,
IonFooter,
IonToolbar,
IonButton,
IonSkeletonText,
TitleCasePipe,
IonContentParallaxDirective,
],
}) })
export class AddEventActionChipComponent { export class AddEventActionChipComponent {
/** /**

View File

@@ -14,6 +14,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {Component, Input} from '@angular/core';
import {IonChip, IonIcon} from '@ionic/angular/standalone';
import {SCThing} from '@openstapps/core'; import {SCThing} from '@openstapps/core';
/** /**
@@ -22,6 +23,8 @@ import {SCThing} from '@openstapps/core';
@Component({ @Component({
selector: 'stapps-locate-action-chip', selector: 'stapps-locate-action-chip',
templateUrl: 'locate-action-chip.html', templateUrl: 'locate-action-chip.html',
standalone: true,
imports: [IonChip, IonIcon],
}) })
export class LocateActionChipComponent { export class LocateActionChipComponent {
/** /**

View File

@@ -18,7 +18,8 @@ import {SCPlaceWithoutReferences, SCThings} from '@openstapps/core';
@Component({ @Component({
selector: 'stapps-navigate-action-chip', selector: 'stapps-navigate-action-chip',
templateUrl: 'navigate-action-chip.html', templateUrl: 'navigate-action-chip.html',
styleUrls: ['navigate-action-chip.scss'], styleUrl: 'navigate-action-chip.scss',
standalone: true,
}) })
export class NavigateActionChipComponent { export class NavigateActionChipComponent {
place: SCPlaceWithoutReferences; place: SCPlaceWithoutReferences;

View File

@@ -14,5 +14,5 @@
--> -->
<ion-chip [color]="'primary'" [outline]="true" [geoNavigation]="place"> <ion-chip [color]="'primary'" [outline]="true" [geoNavigation]="place">
<ion-icon name="directions"></ion-icon> <ion-icon name="directions"></ion-icon>
<ion-label>{{'map.directions.TITLE' | translate}}</ion-label> <ion-label>{{ 'map.directions.TITLE' | translate }}</ion-label>
</ion-chip> </ion-chip>

View File

@@ -31,9 +31,11 @@
(ionChange)="modified.emit(); frequency.click()" (ionChange)="modified.emit(); frequency.click()"
> >
<ion-list-header> <ion-list-header>
{{ frequency.children[0].item.repeatFrequency ? (frequency.children[0].item.repeatFrequency | {{
durationLocalized: true | sentencecase) : ('data.chips.add_events.popover.SINGLE' | translate | frequency.children[0].item.repeatFrequency
titlecase) }} ? (frequency.children[0].item.repeatFrequency | durationLocalized: true | sentencecase)
: ('data.chips.add_events.popover.SINGLE' | translate | titlecase)
}}
</ion-list-header> </ion-list-header>
</ion-checkbox> </ion-checkbox>
</ion-item> </ion-item>
@@ -44,13 +46,13 @@
> >
<ng-container *ngIf="date.item.dates.length > 1; else single_event"> <ng-container *ngIf="date.item.dates.length > 1; else single_event">
<ion-text> <ion-text>
{{ date.item.dates[0] | amDateFormat: 'dddd, LT' }} - {{ date.item.dates[0] | amAdd: {{ date.item.dates[0] | amDateFormat: 'dddd, LT' }} -
date.item.duration | amDateFormat: 'LT' }} {{ date.item.dates[0] | amAdd: date.item.duration | amDateFormat: 'LT' }}
</ion-text> </ion-text>
<br /> <br />
<ion-text> <ion-text>
{{ date.item.dates[0] | amDateFormat: 'LL' }} - {{ date.item.dates[date.item.dates.length - 1] | {{ date.item.dates[0] | amDateFormat: 'LL' }} -
amDateFormat: 'LL' }} {{ date.item.dates[date.item.dates.length - 1] | amDateFormat: 'LL' }}
</ion-text> </ion-text>
</ng-container> </ng-container>
<ng-template #single_event> <ng-template #single_event>

View File

@@ -15,7 +15,7 @@
<ion-chip [class.active]="active" (click)="emitToggle(value)"> <ion-chip [class.active]="active" (click)="emitToggle(value)">
@if (active) { @if (active) {
<ion-icon class="ion-color" name="check_circle" fill="true"></ion-icon> <ion-icon class="ion-color" name="check_circle" fill="true"></ion-icon>
} }
<ion-label>{{ displayValue }}</ion-label> <ion-label>{{ displayValue }}</ion-label>
</ion-chip> </ion-chip>

View File

@@ -44,7 +44,10 @@ export class TreeNode<T extends TreeNode<any> | SelectionValue> {
*/ */
parent?: TreeNode<TreeNode<T>>; parent?: TreeNode<TreeNode<T>>;
constructor(readonly children: T[], readonly ref: ChangeDetectorRef) { constructor(
readonly children: T[],
readonly ref: ChangeDetectorRef,
) {
this.updateParents(); this.updateParents();
this.accumulateApplyValues(); this.accumulateApplyValues();
} }
@@ -58,11 +61,11 @@ export class TreeNode<T extends TreeNode<any> | SelectionValue> {
? it.checked ? it.checked
? Selection.ON ? Selection.ON
: it.indeterminate : it.indeterminate
? Selection.PARTIAL ? Selection.PARTIAL
: Selection.OFF : Selection.OFF
: (it as SelectionValue).selected : (it as SelectionValue).selected
? Selection.ON ? Selection.ON
: Selection.OFF, : Selection.OFF,
); );
this.checked = selections.every(it => it === Selection.ON); this.checked = selections.every(it => it === Selection.ON);

View File

@@ -29,10 +29,13 @@ async function delay(ms: number): Promise<void> {
* ['a', 'b', 'c'] => {0: 'a', 1: 'b', 2: 'c'} * ['a', 'b', 'c'] => {0: 'a', 1: 'b', 2: 'c'}
*/ */
export function arrayToIndexMap<T>(array: T[]): Record<number, T> { export function arrayToIndexMap<T>(array: T[]): Record<number, T> {
return array.reduce((previous, current, index) => { return array.reduce(
previous[index] = current; (previous, current, index) => {
return previous; previous[index] = current;
}, {} as Record<number, T>); return previous;
},
{} as Record<number, T>,
);
} }
interface OngoingQuery { interface OngoingQuery {

View File

@@ -231,6 +231,7 @@ import {VideoListItemComponent} from './types/video/video-list-item.component';
BookDetailContentComponent, BookDetailContentComponent,
PeriodicalDetailContentComponent, PeriodicalDetailContentComponent,
TitleCardComponent, TitleCardComponent,
EditEventSelectionComponent,
], ],
}) })
export class DataModule {} export class DataModule {}

View File

@@ -15,7 +15,7 @@
<ion-header *ngIf="showModalHeader" translucent> <ion-header *ngIf="showModalHeader" translucent>
<ion-toolbar color="primary" mode="ios"> <ion-toolbar color="primary" mode="ios">
<ion-title>{{ 'name' | thingTranslate : item }}</ion-title> <ion-title>{{ 'name' | thingTranslate: item }}</ion-title>
<ion-buttons slot="end"> <ion-buttons slot="end">
<ion-button (click)="modalController.dismiss()">{{ 'app.ui.CLOSE' | translate }}</ion-button> <ion-button (click)="modalController.dismiss()">{{ 'app.ui.CLOSE' | translate }}</ion-button>
</ion-buttons> </ion-buttons>
@@ -97,8 +97,8 @@
</ion-item> </ion-item>
<stapps-simple-card <stapps-simple-card
*ngIf="item.description" *ngIf="item.description"
[title]="$any('description' | propertyNameTranslate : item) | titlecase" [title]="$any('description' | propertyNameTranslate: item) | titlecase"
[content]="'description' | thingTranslate : item" [content]="'description' | thingTranslate: item"
></stapps-simple-card> ></stapps-simple-card>
</ng-container> </ng-container>
</div> </div>

View File

@@ -28,13 +28,13 @@
stack.length === 1 stack.length === 1
? '100%' ? '100%'
: stack.length === 2 : stack.length === 2
? '40vw' ? '40vw'
: ($width | async) >= 768 : ($width | async) >= 768
? '30vw' ? '30vw'
: 'calc(100vw - 120px)' : 'calc(100vw - 120px)'
" "
class="crumb-label" class="crumb-label"
>{{ 'name' | thingTranslate : $any(fragment) }}</ion-label >{{ 'name' | thingTranslate: $any(fragment) }}</ion-label
> >
</ion-breadcrumb> </ion-breadcrumb>
</ion-breadcrumbs> </ion-breadcrumbs>

View File

@@ -14,14 +14,14 @@
--> -->
<span class="ion-hide-sm-up"> <span class="ion-hide-sm-up">
{{ text | slice : 0 : size }} {{ text | slice: 0 : size }}
<span *ngIf="text.length > size" class="ion-hide-sm-up"></span> <span *ngIf="text.length > size" class="ion-hide-sm-up"></span>
</span> </span>
<span class="ion-hide-sm-down ion-hide-md-up"> <span class="ion-hide-sm-down ion-hide-md-up">
{{ text | slice : 0 : size * 2 }} {{ text | slice: 0 : size * 2 }}
<span *ngIf="text.length > size * 2" class="ion-hide-sm-down ion-hide-md-up"></span> <span *ngIf="text.length > size * 2" class="ion-hide-sm-down ion-hide-md-up"></span>
</span> </span>
<span class="ion-hide-md-down"> <span class="ion-hide-md-down">
{{ text | slice : 0 : size * 3 }} {{ text | slice: 0 : size * 3 }}
<span *ngIf="text.length > size * 3" class="ion-hide-md-down"></span> <span *ngIf="text.length > size * 3" class="ion-hide-md-down"></span>
</span> </span>

View File

@@ -12,24 +12,48 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core'; import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
import {
IonCard,
IonCardContent,
IonCardHeader,
IonCol,
IonGrid,
IonIcon,
IonRow,
IonText,
} from '@ionic/angular/standalone';
import {RouterLink} from '@angular/router';
import {ThingTranslateModule} from '../../../translation/thing-translate.module';
import {TranslateModule} from '@ngx-translate/core';
import {CurrencyPipe, KeyValuePipe, TitleCasePipe} from '@angular/common';
import {FormatPipeModule, ParseIsoPipeModule} from 'ngx-date-fns';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-offers-detail', selector: 'stapps-offers-detail',
templateUrl: 'offers-detail.html', templateUrl: 'offers-detail.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
IonCard,
IonCardHeader,
IonCardContent,
IonGrid,
IonRow,
IonCol,
IonIcon,
RouterLink,
ThingTranslateModule,
TranslateModule,
TitleCasePipe,
ParseIsoPipeModule,
FormatPipeModule,
IonText,
CurrencyPipe,
KeyValuePipe,
],
}) })
export class OffersDetailComponent { export class OffersDetailComponent {
/**
* TODO
*/
objectKeys = Object.keys;
/**
* TODO
*/
@Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>; @Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>;
} }

View File

@@ -16,43 +16,51 @@
<ion-card> <ion-card>
<ion-card-header>{{ 'data.detail.offers.TITLE' | translate | titlecase }}</ion-card-header> <ion-card-header>{{ 'data.detail.offers.TITLE' | translate | titlecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<div *ngFor="let offer of offers"> @for (offer of offers; track $index) {
<ion-grid> <ion-grid>
<ion-row> <ion-row>
<ion-col> <ion-col>
<ion-icon name="pin_drop"></ion-icon> <ion-icon name="pin_drop"></ion-icon>
<a [routerLink]="['/data-detail', offer.inPlace.uid]"> <a [routerLink]="['/data-detail', offer.inPlace.uid]">
{{ 'name' | thingTranslate : offer.inPlace }} {{ 'name' | thingTranslate: offer.inPlace }}
</a> </a>
</ion-col> </ion-col>
<ion-col> <ion-col>
<span @if (offer.availabilityRange.gt ? offer.availabilityRange.gt : offer.availabilityRange.gt) {
*ngIf="offer.availabilityRange.gt ? offer.availabilityRange.gt : offer.availabilityRange.gte" {{
> (offer.availabilityRange.gt ? offer.availabilityRange.gt : offer.availabilityRange.gte)
{{ (offer.availabilityRange.gt ? offer.availabilityRange.gt : offer.availabilityRange.gte) | | dfnsParseIso
amDateFormat : 'll' }} | dfnsFormat: 'PP'
</span> }}
}
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>
<ion-grid *ngIf="offer.prices && offer.availability !== 'out of stock'"> @if (offer.availability === 'out of stock') {
<ion-row *ngFor="let group of objectKeys(offer.prices)"> <ion-grid>
<ion-col *ngIf="group !== 'default'">{{ 'data.detail.offers.' + group | translate }} </ion-col> <ion-row>
<ion-col *ngIf="group !== 'default'" width-20 text-right> <ion-col></ion-col>
<p>{{ offer.prices[group] | currency : 'EUR' : 'symbol' : undefined : 'de' }}</p> <ion-col width-20 text-right>
</ion-col> <ion-text color="danger">
</ion-row> <p>{{ 'data.detail.offers.sold_out' | translate }}</p>
</ion-grid> </ion-text>
<ion-grid *ngIf="offer.availability === 'out of stock'"> </ion-col>
<ion-row> </ion-row>
<ion-col></ion-col> </ion-grid>
<ion-col width-20 text-right> } @else if (offer.prices) {
<ion-text color="danger"> <ion-grid>
<p>{{ 'data.detail.offers.sold_out' | translate }}</p> @for (group of offer.prices | keyvalue) {
</ion-text> <ion-row>
</ion-col> @if (group[0] !== 'default') {
</ion-row> <ion-col>{{ 'data.detail.offers.' + group[0] | translate }} </ion-col>
</ion-grid> <ion-col width-20 text-right>
</div> <p>{{ offer.prices[group[0]] | currency: 'EUR' : 'symbol' : '' : 'de' }}</p>
</ion-col>
}
</ion-row>
}
</ion-grid>
}
}
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -12,21 +12,21 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core'; import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
import {SettingsProvider} from '../../settings/settings.provider'; import {SettingsProvider} from '../../settings/settings.provider';
import {IonIcon, IonText} from '@ionic/angular/standalone';
import {CurrencyPipe} from '@angular/common';
import {TranslateModule} from '@ngx-translate/core';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-offers-in-list', selector: 'stapps-offers-in-list',
templateUrl: 'offers-in-list.html', templateUrl: 'offers-in-list.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonText, CurrencyPipe, TranslateModule, IonIcon],
}) })
export class OffersInListComponent { export class OffersInListComponent {
/**
* TODO
*/
@Input() set offers(it: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>) { @Input() set offers(it: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>) {
this._offers = it; this._offers = it;
this.price = it[0].prices?.default; this.price = it[0].prices?.default;

View File

@@ -14,15 +14,24 @@
--> -->
<div> <div>
<ion-text *ngIf="price && !soldOut" style="white-space: nowrap"> @if (soldOut) {
<h2>{{ price | currency : 'EUR' : 'symbol' : undefined : 'de' }}</h2> <ion-text color="danger" class="sold-out" [style.white-space]="'nowrap'">
</ion-text> <h2>{{ 'data.detail.offers.sold_out' | translate }}</h2>
<ion-text *ngIf="soldOut" color="danger" class="sold-out" style="white-space: nowrap"> </ion-text>
<h2>{{ 'data.detail.offers.sold_out' | translate }}</h2> } @else {
</ion-text> @if (price) {
<p *ngIf="_offers[0].inPlace && !soldOut" class="place" style="white-space: nowrap"> <ion-text [style.white-space]="'nowrap'">
<ion-icon name="pin_drop"></ion-icon>{{ _offers[0].inPlace.name }}<span *ngIf="_offers.length > 1" <h2>{{ price | currency: 'EUR' : 'symbol' : '' : 'de' }}</h2>
>...</span </ion-text>
> }
</p> @if (_offers[0].inPlace) {
<p class="place" style="white-space: nowrap">
<ion-icon name="pin_drop"></ion-icon>
{{ _offers[0].inPlace.name }}
@if (_offers.length > 1) {
...
}
</p>
}
}
</div> </div>

View File

@@ -12,19 +12,30 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCThingOrigin} from '@openstapps/core'; import {SCThingRemoteOrigin, SCThingUserOrigin} from '@openstapps/core';
import {IonCard, IonCardContent, IonCardHeader} from '@ionic/angular/standalone';
import {RouterLink} from '@angular/router';
import {TranslateModule} from '@ngx-translate/core';
import {TitleCasePipe} from '@angular/common';
import {FormatPipeModule, ParseIsoPipeModule} from 'ngx-date-fns';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-origin-detail', selector: 'stapps-origin-detail',
templateUrl: 'origin-detail.html', templateUrl: 'origin-detail.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
IonCard,
IonCardHeader,
IonCardContent,
RouterLink,
TranslateModule,
TitleCasePipe,
ParseIsoPipeModule,
FormatPipeModule,
],
}) })
export class OriginDetailComponent { export class OriginDetailComponent {
/** @Input() origin: SCThingUserOrigin | SCThingRemoteOrigin;
* TODO
*/
@Input() origin: SCThingOrigin;
} }

View File

@@ -13,54 +13,74 @@
~ this program. If not, see <https://www.gnu.org/licenses/>. ~ this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<ion-card *ngIf="origin.type === 'user'"> @if (origin.type === 'user') {
<ion-card-header <ion-card>
>{{ 'data.types.origin.TITLE' | translate | titlecase }}: {{ 'data.types.origin.USER' | translate | <ion-card-header
titlecase }}</ion-card-header >{{ 'data.types.origin.TITLE' | translate | titlecase }}:
> {{ 'data.types.origin.USER' | translate | titlecase }}</ion-card-header
<ion-card-content> >
<p> <ion-card-content>
{{ 'data.types.origin.detail.CREATED' | translate | titlecase }}: {{ origin.created | amDateFormat : <p>
'll' }} {{ 'data.types.origin.detail.CREATED' | translate | titlecase }}:
</p> {{ origin.created | dfnsParseIso | dfnsFormat: 'PP' }}
<p *ngIf="origin.updated"> </p>
{{ 'data.types.origin.detail.UPDATED' | translate | titlecase }}: {{ origin.updated | amDateFormat : @if (origin.updated) {
'll' }} <p>
</p> {{ 'data.types.origin.detail.UPDATED' | translate | titlecase }}:
<p *ngIf="origin.modified"> {{ origin.updated | dfnsParseIso | dfnsFormat: 'PP' }}
{{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}: {{ origin.modified | amDateFormat : </p>
'll' }} }
</p> @if (origin.modified) {
<p *ngIf="origin.name">{{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }}</p> <p>
<p *ngIf="origin.maintainer"> {{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}:
{{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.modified | dfnsParseIso | dfnsFormat: 'PP' }}
<a [routerLink]="['/data-detail', origin.maintainer.uid]">{{ origin.maintainer.name }}</a> </p>
</p> }
</ion-card-content> @if (origin.name) {
</ion-card> <p>{{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }}</p>
}
<ion-card *ngIf="origin.type === 'remote'"> @if (origin.maintainer) {
<ion-card-header <p>
>{{ 'data.types.origin.TITLE' | translate | titlecase }}: {{ 'data.types.origin.REMOTE' | translate | {{ 'data.types.origin.detail.MAINTAINER' | translate }}:
titlecase }}</ion-card-header <a [routerLink]="['/data-detail', origin.maintainer.uid]">{{ origin.maintainer.name }}</a>
> </p>
<ion-card-content> }
<p> </ion-card-content>
{{ 'data.types.origin.detail.INDEXED' | translate | titlecase }}: {{ origin.indexed | amDateFormat : </ion-card>
'll' }} } @else if (origin.type === 'remote') {
</p> <ion-card>
<p *ngIf="origin.modified"> <ion-card-header
{{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}: {{ origin.modified | amDateFormat : >{{ 'data.types.origin.TITLE' | translate | titlecase }}:
'll' }} {{ 'data.types.origin.REMOTE' | translate | titlecase }}</ion-card-header
</p> >
<p *ngIf="origin.name">{{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }}</p> <ion-card-content>
<p *ngIf="origin.maintainer"> <p>
{{ 'data.types.origin.detail.MAINTAINER' | translate | titlecase }}: {{ 'data.types.origin.detail.INDEXED' | translate | titlecase }}:
<a [routerLink]="['/data-detail', origin.maintainer.uid]">{{ origin.maintainer.name }}</a> {{ origin.indexed | dfnsParseIso | dfnsFormat: 'PP' }}
</p> </p>
<p *ngIf="origin.responsibleEntity"> @if (origin.modified) {
{{ 'data.types.origin.detail.RESPONSIBLE' | translate | titlecase }}: <p>
<a [routerLink]="['/data-detail', origin.responsibleEntity.uid]">{{ origin.responsibleEntity.name }}</a> {{ 'data.types.origin.detail.MODIFIED' | translate | titlecase }}:
</p> {{ origin.modified | dfnsParseIso | dfnsFormat: 'PP' }}
</ion-card-content> </p>
</ion-card> }
@if (origin.name) {
<p>{{ 'data.types.origin.detail.MAINTAINER' | translate }}: {{ origin.name }}</p>
}
@if (origin.maintainer) {
<p>
{{ 'data.types.origin.detail.MAINTAINER' | translate | titlecase }}:
<a [routerLink]="['/data-detail', origin.maintainer.uid]">{{ origin.maintainer.name }}</a>
</p>
}
@if (origin.responsibleEntity) {
<p>
{{ 'data.types.origin.detail.RESPONSIBLE' | translate | titlecase }}:
<a [routerLink]="['/data-detail', origin.responsibleEntity.uid]">{{
origin.responsibleEntity.name
}}</a>
</p>
}
</ion-card-content>
</ion-card>
}

View File

@@ -12,19 +12,17 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCThingOrigin} from '@openstapps/core'; import {SCThingRemoteOrigin, SCThingUserOrigin} from '@openstapps/core';
import {ThingTranslateModule} from '../../../translation/thing-translate.module';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-origin-in-list', selector: 'stapps-origin-in-list',
templateUrl: 'origin-in-list.html', templateUrl: 'origin-in-list.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [ThingTranslateModule],
}) })
export class OriginInListComponent { export class OriginInListComponent {
/** @Input() origin: SCThingUserOrigin | SCThingRemoteOrigin;
* TODO
*/
@Input() origin: SCThingOrigin;
} }

View File

@@ -1,7 +1,7 @@
<div *ngIf="origin.type === 'user'"> <p>
<p>{{ origin.created | dateFormat }}</p> @if (origin.type === 'user') {
</div> {{ origin.created | dateFormat }}
} @else if (origin.type === 'remote') {
<div *ngIf="origin.type === 'remote'"> {{ origin.indexed | dateFormat }}
<p>{{ origin.indexed | dateFormat }}</p> }
</div> </p>

View File

@@ -51,7 +51,10 @@ export class StappsRatingComponent {
this.dish.next(value); this.dish.next(value);
} }
constructor(readonly elementRef: ElementRef, readonly ratingProvider: RatingProvider) {} constructor(
readonly elementRef: ElementRef,
readonly ratingProvider: RatingProvider,
) {}
@HostListener('document:mousedown', ['$event']) @HostListener('document:mousedown', ['$event'])
clickOutside(event: MouseEvent) { clickOutside(event: MouseEvent) {

View File

@@ -12,49 +12,33 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCThingWithoutReferences} from '@openstapps/core'; import {SCThingWithoutReferences} from '@openstapps/core';
import {IonCard, IonCardContent, IonCardHeader} from '@ionic/angular/standalone';
import {MarkdownComponent} from 'ngx-markdown';
import {RouterLink} from '@angular/router';
import {ThingTranslateModule} from '../../../translation/thing-translate.module';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-simple-card', selector: 'stapps-simple-card',
templateUrl: 'simple-card.html', templateUrl: 'simple-card.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonCard, IonCardHeader, IonCardContent, MarkdownComponent, RouterLink, ThingTranslateModule],
}) })
export class SimpleCardComponent { export class SimpleCardComponent {
/**
* TODO
*/
areThings = false; areThings = false;
/**
* TODO
*/
@Input() content: string | string[] | SCThingWithoutReferences[]; @Input() content: string | string[] | SCThingWithoutReferences[];
/**
* TODO
*/
@Input() isMarkdown = false; @Input() isMarkdown = false;
/**
* TODO
*/
@Input() title: string; @Input() title: string;
/**
* TODO
*/
// eslint-disable-next-line class-methods-use-this
isString(data: unknown): data is string { isString(data: unknown): data is string {
return typeof data === 'string'; return typeof data === 'string';
} }
/**
* TODO
*/
// eslint-disable-next-line class-methods-use-this
isThing(something: unknown): something is SCThingWithoutReferences { isThing(something: unknown): something is SCThingWithoutReferences {
// bypass the 'type' field check because of translated values // bypass the 'type' field check because of translated values
return typeof something === 'object'; return typeof something === 'object';

View File

@@ -16,25 +16,25 @@
<ion-card> <ion-card>
<ion-card-header>{{ title }}</ion-card-header> <ion-card-header>{{ title }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ng-container *ngIf="isString(content); then text; else list"> </ng-container> @if (isString(content)) {
<ng-template #text> @if (isMarkdown) {
<ng-container *ngIf="isMarkdown; else plainText">
<markdown [data]="content"></markdown> <markdown [data]="content"></markdown>
</ng-container> } @else {
<ng-template #plainText>
<p>{{ content }}</p> <p>{{ content }}</p>
</ng-template> }
</ng-template> } @else {
<ng-template #list> @if (isThing(content[0])) {
<ng-container *ngIf="isThing(content[0]); then thingList; else textList"> </ng-container> @for (thing of content; track thing) {
<ng-template #thingList> <a [routerLink]="['/data-detail', thing.uid]">
<a [routerLink]="['/data-detail', thing.uid]" *ngFor="let thing of content"> <p>{{ 'name' | thingTranslate: thing }}</p>
<p>{{ 'name' | thingTranslate : thing }}</p> </a>
</a> }
</ng-template> }
<ng-template #textList> }
<p *ngFor="let text of content">{{ text }}</p> @else {
</ng-template> @for (text of content; track text) {
</ng-template> <p>{{ text }}</p>
}
}
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -12,7 +12,16 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {
IonCol,
IonGrid,
IonItem,
IonNote,
IonRow,
IonSkeletonText,
IonThumbnail,
} from '@ionic/angular/standalone';
/** /**
* A placeholder to show when a list item is being loaded * A placeholder to show when a list item is being loaded
@@ -20,7 +29,9 @@ import {Component, Input} from '@angular/core';
@Component({ @Component({
selector: 'stapps-skeleton-list-item', selector: 'stapps-skeleton-list-item',
templateUrl: 'skeleton-list-item.html', templateUrl: 'skeleton-list-item.html',
styleUrls: ['skeleton-list-item.scss'], changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonItem, IonThumbnail, IonSkeletonText, IonGrid, IonRow, IonCol, IonNote],
}) })
export class SkeletonListItemComponent { export class SkeletonListItemComponent {
@Input() hideThumbnail = false; @Input() hideThumbnail = false;

View File

@@ -1,18 +1,20 @@
<ion-item> <ion-item>
<ion-thumbnail *ngIf="!hideThumbnail" slot="start" class="ion-margin-end"> @if (!hideThumbnail) {
<ion-skeleton-text animated></ion-skeleton-text> <ion-thumbnail slot="start" class="ion-margin-end">
</ion-thumbnail> <ion-skeleton-text animated></ion-skeleton-text>
</ion-thumbnail>
}
<ion-grid> <ion-grid>
<ion-row> <ion-row>
<ion-col> <ion-col>
<h2 class="name"> <h2 class="name">
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text> <ion-skeleton-text animated [style.width.%]="80"></ion-skeleton-text>
</h2> </h2>
<p> <p>
<ion-skeleton-text animated style="width: 80%"></ion-skeleton-text> <ion-skeleton-text animated [style.width.%]="80"></ion-skeleton-text>
</p> </p>
<ion-note> <ion-note>
<ion-skeleton-text animated style="width: 20%"></ion-skeleton-text> <ion-skeleton-text animated [style.width.%]="80"></ion-skeleton-text>
</ion-note> </ion-note>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -12,7 +12,8 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component} from '@angular/core'; import {ChangeDetectionStrategy, Component} from '@angular/core';
import {IonSegmentButton, IonSkeletonText} from '@ionic/angular/standalone';
/** /**
* TODO * TODO
@@ -20,5 +21,8 @@ import {Component} from '@angular/core';
@Component({ @Component({
selector: 'stapps-skeleton-segment-button', selector: 'stapps-skeleton-segment-button',
templateUrl: 'skeleton-segment-button.html', templateUrl: 'skeleton-segment-button.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonSegmentButton, IonSkeletonText],
}) })
export class SkeletonSegmentComponent {} export class SkeletonSegmentComponent {}

View File

@@ -1,3 +1,3 @@
<ion-segment-button> <ion-segment-button>
<ion-skeleton-text animated style="width: 85%"></ion-skeleton-text> <ion-skeleton-text animated [style.width.%]="85"></ion-skeleton-text>
</ion-segment-button> </ion-segment-button>

View File

@@ -12,7 +12,8 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {IonCard, IonCardContent, IonCardHeader, IonSkeletonText} from '@ionic/angular/standalone';
/** /**
* A placeholder to show when a simple card is being loaded * A placeholder to show when a simple card is being loaded
@@ -20,6 +21,9 @@ import {Component, Input} from '@angular/core';
@Component({ @Component({
selector: 'stapps-skeleton-simple-card', selector: 'stapps-skeleton-simple-card',
templateUrl: 'skeleton-simple-card.html', templateUrl: 'skeleton-simple-card.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonCard, IonCardHeader, IonSkeletonText, IonCardContent],
}) })
export class SkeletonSimpleCardComponent { export class SkeletonSimpleCardComponent {
/** /**

View File

@@ -1,14 +1,14 @@
<ion-card> <ion-card>
<ion-card-header *ngIf="title"> @if (title) {
<ion-skeleton-text animated style="width: 15%"></ion-skeleton-text> <ion-card-header>
</ion-card-header> <ion-skeleton-text animated [style.width.%]="15"></ion-skeleton-text>
</ion-card-header>
}
<ion-card-content> <ion-card-content>
<p> <p>
<ion-skeleton-text @for (line of [].constructor(lines); track line) {
*ngFor="let line of [].constructor(lines)" <ion-skeleton-text animated [style.width.%]="85"></ion-skeleton-text>
animated }
style="width: 85%"
></ion-skeleton-text>
</p> </p>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -13,9 +13,28 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, ElementRef, HostListener, Input, OnChanges, OnInit, ViewChild} from '@angular/core'; import {
ChangeDetectionStrategy,
Component,
ElementRef,
HostListener,
Input,
OnChanges,
OnInit,
ViewChild,
} from '@angular/core';
import {SCThings} from '@openstapps/core'; import {SCThings} from '@openstapps/core';
import {SCIcon} from '../../../util/ion-icon/icon'; import {SCIcon} from '../../../util/ion-icon/icon';
import {
IonButton,
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonIcon,
} from '@ionic/angular/standalone';
import {OpeningHoursComponent} from '../../../util/opening-hours.component';
import {ThingTranslateModule} from '../../../translation/thing-translate.module';
const AccordionButtonState = { const AccordionButtonState = {
collapsed: SCIcon`expand_more`, collapsed: SCIcon`expand_more`,
@@ -24,8 +43,20 @@ const AccordionButtonState = {
@Component({ @Component({
selector: 'stapps-title-card', selector: 'stapps-title-card',
templateUrl: './title-card.component.html', templateUrl: 'title-card.html',
styleUrls: ['./title-card.component.scss'], styleUrl: 'title-card.scss',
changeDetection: ChangeDetectionStrategy.Default,
standalone: true,
imports: [
IonCard,
IonCardHeader,
IonCardTitle,
IonCardContent,
OpeningHoursComponent,
IonButton,
IonIcon,
ThingTranslateModule,
],
}) })
export class TitleCardComponent implements OnInit, OnChanges { export class TitleCardComponent implements OnInit, OnChanges {
/** /**

View File

@@ -16,34 +16,35 @@
<ion-card-header> <ion-card-header>
<ion-card-title> <ion-card-title>
<h1> <h1>
<ng-container *ngIf="$any(item).honorificPrefix">{{ @if (item.honorificPrefix) {
'honorificPrefix' | thingTranslate : item {{ 'honorificPrefix' | thingTranslate: item }}
}}</ng-container> }
{{ 'name' | thingTranslate : item }} {{ 'name' | thingTranslate: item }}
<ng-container *ngIf="$any(item).honorificSuffix">{{ @if (item.honorificSuffix) {
'honorificSuffix' | thingTranslate : item {{ 'honorificSuffix' | thingTranslate: item }}
}}</ng-container> }
</h1> </h1>
</ion-card-title> </ion-card-title>
</ion-card-header> </ion-card-header>
<ion-card-content> <ion-card-content>
<div *ngIf="$any(item).openingHours" class="opening-hours"> @if (item.openingHours) {
<stapps-opening-hours [openingHours]="item.openingHours"></stapps-opening-hours> <div class="opening-hours">
</div> <stapps-opening-hours [openingHours]="item.openingHours"></stapps-opening-hours>
<!-- TODO obviously this is bad style. Tbd where to put the differentiation. Job Postings always have a description, but it's going to be shown in `stapps-job-posting-detail-content` anyways, no need to repeat here. For this view, I would use other fields of the schema.org JobPosting like the `ThingWithCategory.category` -->
<div *ngIf="item.description && item.type !== 'job posting'" class="description">
<div class="text-accordion" [style.-webkit-line-clamp]="descriptionLinesToDisplay" #accordionTextArea>
{{ 'description' | thingTranslate : item }}
</div> </div>
</div> }
<!-- TODO obviously this is bad style. Tbd where to put the differentiation. Job Postings always have a description, but it's going to be shown in `stapps-job-posting-detail-content` anyways, no need to repeat here. For this view, I would use other fields of the schema.org JobPosting like the `ThingWithCategory.category` -->
@if (item.description && item.type !== 'job posting') {
<div class="description">
<div class="text-accordion" [style.-webkit-line-clamp]="descriptionLinesToDisplay" #accordionTextArea>
{{ 'description' | thingTranslate: item }}
</div>
</div>
}
<!-- TODO see above --> <!-- TODO see above -->
<ion-button @if (item.description && item.type !== 'job posting' && buttonShown) {
expand="full" <ion-button expand="full" fill="clear" (click)="toggleDescriptionAccordion()">
fill="clear" <ion-icon [name]="buttonState" size="large"></ion-icon>
*ngIf="item.description && item.type !== 'job posting' && buttonShown" </ion-button>
(click)="toggleDescriptionAccordion()" }
>
<ion-icon [name]="buttonState" size="large"></ion-icon>
</ion-button>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -13,10 +13,10 @@
~ this program. If not, see <https://www.gnu.org/licenses/>. ~ this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<h2>{{ 'name' | thingTranslate : item }}</h2> <h2>{{ 'name' | thingTranslate: item }}</h2>
<p *ngIf="item.description"> <p *ngIf="item.description">
<stapps-long-inline-text <stapps-long-inline-text
[text]="'description' | thingTranslate : item" [text]="'description' | thingTranslate: item"
[size]="80" [size]="80"
></stapps-long-inline-text> ></stapps-long-inline-text>
</p> </p>

View File

@@ -53,7 +53,10 @@ export class SimpleDataListComponent implements OnInit {
destroy$ = inject(DestroyRef); destroy$ = inject(DestroyRef);
constructor(protected router: Router, private readonly dataRoutingService: DataRoutingService) {} constructor(
protected router: Router,
private readonly dataRoutingService: DataRoutingService,
) {}
ngOnInit(): void { ngOnInit(): void {
if (!this.autoRouting) return; if (!this.autoRouting) return;

View File

@@ -22,9 +22,9 @@
></ng-container> ></ng-container>
</ng-container> </ng-container>
</ion-list> </ion-list>
<ion-label class="empty-list-message" *ngIf="emptyListMessage && items.length === 0" <ion-label class="empty-list-message" *ngIf="emptyListMessage && items.length === 0">{{
>{{ emptyListMessage }}</ion-label emptyListMessage
> }}</ion-label>
</ng-container> </ng-container>
<ng-template #loading> <ng-template #loading>
<ion-list> <ion-list>

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCArticle} from '@openstapps/core'; import {SCArticle} from '@openstapps/core';
/** /**
@@ -21,6 +21,8 @@ import {SCArticle} from '@openstapps/core';
@Component({ @Component({
selector: 'stapps-article-content', selector: 'stapps-article-content',
templateUrl: 'article-content.html', templateUrl: 'article-content.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}) })
export class ArticleContentComponent { export class ArticleContentComponent {
/** /**

View File

@@ -16,14 +16,14 @@
<ion-card *ngIf="item.sameAs"> <ion-card *ngIf="item.sameAs">
<ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header> <ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-external-link [text]="'name' | thingTranslate : item" [link]="item.sameAs"></stapps-external-link> <stapps-external-link [text]="'name' | thingTranslate: item" [link]="item.sameAs"></stapps-external-link>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="!item.sameAs" *ngIf="!item.sameAs"
[title]="'name' | propertyNameTranslate : item | sentencecase" [title]="'name' | propertyNameTranslate: item | sentencecase"
[content]="'name' | thingTranslate : item" [content]="'name' | thingTranslate: item"
> >
</stapps-simple-card> </stapps-simple-card>
@@ -35,14 +35,14 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.sourceOrganization" *ngIf="item.sourceOrganization"
[title]="'sourceOrganization' | propertyNameTranslate : item | sentencecase" [title]="'sourceOrganization' | propertyNameTranslate: item | sentencecase"
[content]="item.sourceOrganization" [content]="item.sourceOrganization"
></stapps-simple-card> ></stapps-simple-card>
<ion-card *ngIf="item.authors && item.authors.length > 0"> <ion-card *ngIf="item.authors && item.authors.length > 0">
<ion-card-header>{{ 'authors' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'authors' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate : author }}</ion-label> <ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate: author }}</ion-label>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
@@ -56,37 +56,37 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.firstPublished && item.lastPublished" *ngIf="item.firstPublished && item.lastPublished"
[title]="'hebisSearch.detail.firstPublished' | translate | sentencecase" [title]="'hebisSearch.detail.firstPublished' | translate | sentencecase"
[content]="[item.firstPublished, item.lastPublished] | join : ' - '" [content]="[item.firstPublished, item.lastPublished] | join: ' - '"
> >
</stapps-simple-card> </stapps-simple-card>
<ion-card *ngIf="item.publications"> <ion-card *ngIf="item.publications">
<ion-card-header>{{ 'publications' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'publications' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<p *ngFor="let publication of item.publications"> <p *ngFor="let publication of item.publications">
{{ publication.locations | join : ', ' }} {{ publication.locations && publication.publisher ? ':' : '' {{ publication.locations | join: ', ' }}
}} {{ publication.publisher }} {{ publication.locations && publication.publisher ? ':' : '' }} {{ publication.publisher }}
</p> </p>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.reference" *ngIf="item.reference"
[title]="'reference' | propertyNameTranslate : item | sentencecase" [title]="'reference' | propertyNameTranslate: item | sentencecase"
[content]="item.reference" [content]="item.reference"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.isPartOf" *ngIf="item.isPartOf"
[title]="'isPartOf' | propertyNameTranslate : item | sentencecase" [title]="'isPartOf' | propertyNameTranslate: item | sentencecase"
[content]="item.isPartOf.name" [content]="item.isPartOf.name"
></stapps-simple-card> ></stapps-simple-card>
<ion-card *ngIf="item.categories"> <ion-card *ngIf="item.categories">
<ion-card-header>{{ 'categories' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'categories' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-chip [color]="'primary'"> <ion-chip [color]="'primary'">
<ion-icon [name]="item.type | dataIcon"></ion-icon> <ion-icon [name]="item.type | dataIcon"></ion-icon>
<ion-label>{{ 'categories' | thingTranslate : item }}</ion-label> <ion-label>{{ 'categories' | thingTranslate: item }}</ion-label>
</ion-chip> </ion-chip>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -12,9 +12,8 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCArticle} from '@openstapps/core'; import {SCArticle} from '@openstapps/core';
import {DataListItemComponent} from '../../list/data-list-item.component';
/** /**
* TODO * TODO
@@ -22,8 +21,10 @@ import {DataListItemComponent} from '../../list/data-list-item.component';
@Component({ @Component({
selector: 'stapps-article-item', selector: 'stapps-article-item',
templateUrl: 'article-list-item.html', templateUrl: 'article-list-item.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}) })
export class ArticleListItemComponent extends DataListItemComponent { export class ArticleListItemComponent {
/** /**
* TODO * TODO
*/ */

View File

@@ -16,20 +16,20 @@
<ion-grid> <ion-grid>
<ion-row> <ion-row>
<ion-col> <ion-col>
<h2 class="name">{{ 'name' | thingTranslate : item }}</h2> <h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
<p> <p>
<ng-container *ngFor="let author of item.authors"> <ng-container *ngFor="let author of item.authors"> {{ 'name' | thingTranslate: author }}</ng-container
{{ 'name' | thingTranslate : author }}</ng-container
><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container> ><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container>
<ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange" <ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange">{{
>{{ item.firstPublished }}</ng-container item.firstPublished
}}</ng-container
><ng-template #dateRange ><ng-template #dateRange
><ng-container *ngIf="item.firstPublished && item.lastPublished" ><ng-container *ngIf="item.firstPublished && item.lastPublished">{{
>{{ [item.firstPublished, item.lastPublished] | join : ' - ' }}</ng-container [item.firstPublished, item.lastPublished] | join: ' - '
></ng-template }}</ng-container></ng-template
> >
</p> </p>
<ion-note> {{ 'categories' | thingTranslate : item }} </ion-note> <ion-note> {{ 'categories' | thingTranslate: item }} </ion-note>
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCBook} from '@openstapps/core'; import {SCBook} from '@openstapps/core';
/** /**
@@ -21,6 +21,8 @@ import {SCBook} from '@openstapps/core';
@Component({ @Component({
selector: 'stapps-book-detail-content', selector: 'stapps-book-detail-content',
templateUrl: 'book-detail-content.html', templateUrl: 'book-detail-content.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}) })
export class BookDetailContentComponent { export class BookDetailContentComponent {
/** /**

View File

@@ -16,21 +16,21 @@
<ion-card *ngIf="item.sameAs"> <ion-card *ngIf="item.sameAs">
<ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header> <ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-external-link [text]="'name' | thingTranslate : item" [link]="item.sameAs"></stapps-external-link> <stapps-external-link [text]="'name' | thingTranslate: item" [link]="item.sameAs"></stapps-external-link>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="!item.sameAs" *ngIf="!item.sameAs"
[title]="'name' | propertyNameTranslate : item | sentencecase" [title]="'name' | propertyNameTranslate: item | sentencecase"
[content]="'name' | thingTranslate : item" [content]="'name' | thingTranslate: item"
> >
</stapps-simple-card> </stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.edition" *ngIf="item.edition"
[title]="'edition' | propertyNameTranslate : item | sentencecase" [title]="'edition' | propertyNameTranslate: item | sentencecase"
[content]="'edition' | thingTranslate : item" [content]="'edition' | thingTranslate: item"
> >
</stapps-simple-card> </stapps-simple-card>
@@ -42,20 +42,20 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.sourceOrganization" *ngIf="item.sourceOrganization"
[title]="'sourceOrganization' | propertyNameTranslate : item | sentencecase" [title]="'sourceOrganization' | propertyNameTranslate: item | sentencecase"
[content]="item.sourceOrganization" [content]="item.sourceOrganization"
></stapps-simple-card> ></stapps-simple-card>
<ion-card *ngIf="item.authors && item.authors.length > 0"> <ion-card *ngIf="item.authors && item.authors.length > 0">
<ion-card-header>{{ 'authors' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'authors' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate : author }}</ion-label> <ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate: author }}</ion-label>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.ISBNs" *ngIf="item.ISBNs"
[title]="'ISBNs' | propertyNameTranslate : item | sentencecase" [title]="'ISBNs' | propertyNameTranslate: item | sentencecase"
[content]="item.ISBNs" [content]="item.ISBNs"
> >
</stapps-simple-card> </stapps-simple-card>
@@ -68,24 +68,24 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.firstPublished && item.lastPublished" *ngIf="item.firstPublished && item.lastPublished"
[title]="'hebisSearch.detail.firstPublished' | translate | sentencecase" [title]="'hebisSearch.detail.firstPublished' | translate | sentencecase"
[content]="[item.firstPublished, item.lastPublished] | join : ' - '" [content]="[item.firstPublished, item.lastPublished] | join: ' - '"
> >
</stapps-simple-card> </stapps-simple-card>
<ion-card *ngIf="item.publications"> <ion-card *ngIf="item.publications">
<ion-card-header>{{ 'publications' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'publications' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<p *ngFor="let publication of item.publications"> <p *ngFor="let publication of item.publications">
{{ publication.locations | join : ', ' }} {{ publication.locations && publication.publisher ? ':' : '' {{ publication.locations | join: ', ' }}
}} {{ publication.publisher }} {{ publication.locations && publication.publisher ? ':' : '' }} {{ publication.publisher }}
</p> </p>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<ion-card *ngIf="item.categories"> <ion-card *ngIf="item.categories">
<ion-card-header>{{ 'categories' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'categories' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-chip [color]="'primary'"> <ion-chip [color]="'primary'">
<ion-icon [name]="item.type | dataIcon"></ion-icon> <ion-icon [name]="item.type | dataIcon"></ion-icon>
<ion-label>{{ 'categories' | thingTranslate : item }}</ion-label> <ion-label>{{ 'categories' | thingTranslate: item }}</ion-label>
</ion-chip> </ion-chip>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>

View File

@@ -12,9 +12,8 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCBook} from '@openstapps/core'; import {SCBook} from '@openstapps/core';
import {DataListItemComponent} from '../../list/data-list-item.component';
/** /**
* TODO * TODO
@@ -22,8 +21,10 @@ import {DataListItemComponent} from '../../list/data-list-item.component';
@Component({ @Component({
selector: 'stapps-book-list-item', selector: 'stapps-book-list-item',
templateUrl: 'book-list-item.html', templateUrl: 'book-list-item.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}) })
export class BookListItemComponent extends DataListItemComponent { export class BookListItemComponent {
/** /**
* TODO * TODO
*/ */

View File

@@ -16,20 +16,20 @@
<ion-grid> <ion-grid>
<ion-row> <ion-row>
<ion-col> <ion-col>
<h2 class="name">{{ 'name' | thingTranslate : item }}</h2> <h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
<p> <p>
<ng-container *ngFor="let author of item.authors"> <ng-container *ngFor="let author of item.authors"> {{ 'name' | thingTranslate: author }}</ng-container
{{ 'name' | thingTranslate : author }}</ng-container
><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container> ><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container>
<ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange" <ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange">{{
>{{ item.firstPublished }}</ng-container item.firstPublished
}}</ng-container
><ng-template #dateRange ><ng-template #dateRange
><ng-container *ngIf="item.firstPublished && item.lastPublished" ><ng-container *ngIf="item.firstPublished && item.lastPublished">{{
>{{ [item.firstPublished, item.lastPublished] | join : ' - ' }}</ng-container [item.firstPublished, item.lastPublished] | join: ' - '
></ng-template }}</ng-container></ng-template
> >
</p> </p>
<ion-note> {{ 'categories' | thingTranslate : item }} </ion-note> <ion-note> {{ 'categories' | thingTranslate: item }} </ion-note>
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>

View File

@@ -12,19 +12,18 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input, OnInit} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input, OnInit} from '@angular/core';
import {SCCatalog, SCThings} from '@openstapps/core'; import {SCCatalog, SCThings} from '@openstapps/core';
import {DataProvider} from '../../data.provider'; import {DataProvider} from '../../data.provider';
@Component({ @Component({
selector: 'stapps-catalog-detail-content', selector: 'stapps-catalog-detail-content',
templateUrl: 'catalog-detail-content.html', templateUrl: 'catalog-detail-content.html',
styleUrls: ['catalog-detail-content.scss'], styleUrl: 'catalog-detail-content.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
}) })
export class CatalogDetailContentComponent implements OnInit { export class CatalogDetailContentComponent implements OnInit {
/**
* SCCatalog to display
*/
@Input() item: SCCatalog; @Input() item: SCCatalog;
items: Promise<SCThings[]>; items: Promise<SCThings[]>;

View File

@@ -17,6 +17,6 @@
id="simple-data-list" id="simple-data-list"
[items]="items" [items]="items"
[singleType]="true" [singleType]="true"
[listHeader]="'type' | thingTranslate : item | titlecase" [listHeader]="'type' | thingTranslate: item | titlecase"
[emptyListMessage]="'catalog.detail.EMPTY_CATALOG' | translate" [emptyListMessage]="'catalog.detail.EMPTY_CATALOG' | translate"
></stapps-simple-data-list> ></stapps-simple-data-list>

View File

@@ -12,9 +12,11 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {SCCatalog} from '@openstapps/core'; import {SCCatalog} from '@openstapps/core';
import {DataListItemComponent} from '../../list/data-list-item.component'; import {DataListItemComponent} from '../../list/data-list-item.component';
import {IonCol, IonGrid, IonLabel, IonRow} from '@ionic/angular/standalone';
import {ThingTranslateModule} from '../../../../translation/thing-translate.module';
/** /**
* TODO * TODO
@@ -22,6 +24,9 @@ import {DataListItemComponent} from '../../list/data-list-item.component';
@Component({ @Component({
selector: 'stapps-catalog-list-item', selector: 'stapps-catalog-list-item',
templateUrl: 'catalog-list-item.html', templateUrl: 'catalog-list-item.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [IonGrid, IonRow, IonCol, IonLabel, ThingTranslateModule],
}) })
export class CatalogListItemComponent extends DataListItemComponent { export class CatalogListItemComponent extends DataListItemComponent {
/** /**

View File

@@ -2,8 +2,10 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title"> {{ 'name' | thingTranslate : item }} </ion-label> <ion-label class="title"> {{ 'name' | thingTranslate: item }}</ion-label>
<p *ngIf="item.academicTerm" class="title-sub">{{ item.academicTerm.name }}</p> @if (item.academicTerm) {
<p class="title-sub">{{ item.academicTerm.name }}</p>
}
</div> </div>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -20,11 +20,32 @@ import {map} from 'rxjs/operators';
import {DataRoutingService} from '../../data-routing.service'; import {DataRoutingService} from '../../data-routing.service';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {AsyncPipe, TitleCasePipe} from '@angular/common';
import {IonCard, IonCardContent, IonCardHeader, IonChip, IonIcon, IonLabel} from '@ionic/angular/standalone';
import {TranslateModule} from '@ngx-translate/core';
import {ThingTranslateModule} from '../../../../translation/thing-translate.module';
import {MomentModule} from 'ngx-moment';
import {MapWidgetComponent} from '../../../map/widget/map-widget.component';
@Component({ @Component({
selector: 'stapps-date-series-detail-content', selector: 'stapps-date-series-detail-content',
templateUrl: 'date-series-detail-content.html', templateUrl: 'date-series-detail-content.html',
styleUrls: ['date-series-detail-content.scss'], styleUrl: 'date-series-detail-content.scss',
standalone: true,
imports: [
AsyncPipe,
IonChip,
IonIcon,
IonLabel,
TranslateModule,
ThingTranslateModule,
TitleCasePipe,
MomentModule,
MapWidgetComponent,
IonCardHeader,
IonCardContent,
IonCard,
],
}) })
export class DateSeriesDetailContentComponent implements OnInit { export class DateSeriesDetailContentComponent implements OnInit {
@Input() item: SCDateSeries; @Input() item: SCDateSeries;

View File

@@ -15,52 +15,54 @@
<ng-container *ngIf="isInCalendar | async; else add"> <ng-container *ngIf="isInCalendar | async; else add">
<ion-chip outline="true" color="success" (click)="removeFromCalendar()"> <ion-chip outline="true" color="success" (click)="removeFromCalendar()">
<ion-icon name="event_available" fill="true"></ion-icon> <ion-icon name="event_available" fill="true"></ion-icon>
<ion-label>{{'chips.addEvent.addedToEvents' | translate}}</ion-label> <ion-label>{{ 'chips.addEvent.addedToEvents' | translate }}</ion-label>
</ion-chip> </ion-chip>
</ng-container> </ng-container>
<ng-template #add> <ng-template #add>
<ion-chip outline="true" color="primary" (click)="addToCalendar()"> <ion-chip outline="true" color="primary" (click)="addToCalendar()">
<ion-icon name="calendar_today"></ion-icon> <ion-icon name="calendar_today"></ion-icon>
<ion-label>{{'chips.addEvent.addEvent' | translate}}</ion-label> <ion-label>{{ 'chips.addEvent.addEvent' | translate }}</ion-label>
</ion-chip> </ion-chip>
</ng-template> </ng-template>
<stapps-simple-card <stapps-simple-card
title="{{ 'duration' | propertyNameTranslate : item | titlecase }}" title="{{ 'duration' | propertyNameTranslate: item | titlecase }}"
[content]="[item.duration | amDuration : 'minutes']" [content]="[item.duration | amDuration: 'minutes']"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.dates.length > 1; else single_event" *ngIf="item.dates.length > 1; else single_event"
title="{{ 'dates' | propertyNameTranslate : item | titlecase }}" title="{{ 'dates' | propertyNameTranslate: item | titlecase }}"
content="{{ 'data.chips.add_events.popover.AT' | translate | titlecase }} {{ content="{{ 'data.chips.add_events.popover.AT' | translate | titlecase }} {{
item.dates[0] | amDateFormat : 'HH:mm ddd' item.dates[0] | amDateFormat: 'HH:mm ddd'
}} {{ 'data.chips.add_events.popover.UNTIL' | translate }} {{ }} {{ 'data.chips.add_events.popover.UNTIL' | translate }} {{
item.dates[item.dates.length - 1] | amDateFormat : 'll' item.dates[item.dates.length - 1] | amDateFormat: 'll'
}}" }}"
></stapps-simple-card> ></stapps-simple-card>
<ng-template #single_event> <ng-template #single_event>
<stapps-simple-card <stapps-simple-card
title="{{ 'dates' | propertyNameTranslate : item | titlecase }}" title="{{ 'dates' | propertyNameTranslate: item | titlecase }}"
content="{{ 'data.chips.add_events.popover.AT' | translate | titlecase }} {{ content="{{ 'data.chips.add_events.popover.AT' | translate | titlecase }} {{
item.dates[item.dates.length - 1] | amDateFormat : 'll, HH:mm' item.dates[item.dates.length - 1] | amDateFormat: 'll, HH:mm'
}}" }}"
></stapps-simple-card> ></stapps-simple-card>
</ng-template> </ng-template>
<stapps-simple-card <stapps-simple-card
*ngIf="item.performers" *ngIf="item.performers"
[title]="'performers' | propertyNameTranslate : item.performers | titlecase" [title]="'performers' | propertyNameTranslate: item.performers | titlecase"
[content]="item.performers" [content]="item.performers"
></stapps-simple-card> ></stapps-simple-card>
<stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail> <stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail>
<ion-card> <ion-card>
<ion-card-header> {{ 'event' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-card-header> {{ 'event' | propertyNameTranslate: item | titlecase }} </ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-data-list-item [item]="$any(item.event)"></stapps-data-list-item> <stapps-data-list-item [item]="$any(item.event)"></stapps-data-list-item>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<ion-card *ngIf="item.inPlace"> @if (item.inPlace) {
<ion-card-header> {{ 'inPlace' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-card>
<ion-card-content> <ion-card-header> {{ 'inPlace' | propertyNameTranslate: item | titlecase }} </ion-card-header>
<stapps-data-list-item [item]="$any(item.inPlace)"></stapps-data-list-item> <ion-card-content>
</ion-card-content> <stapps-data-list-item [item]="$any(item.inPlace)"></stapps-data-list-item>
</ion-card> </ion-card-content>
</ion-card>
}
<stapps-map-widget *ngIf="item.inPlace?.geo" [place]="item.inPlace"></stapps-map-widget> <stapps-map-widget *ngIf="item.inPlace?.geo" [place]="item.inPlace"></stapps-map-widget>

View File

@@ -17,22 +17,22 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title">{{ 'event.name' | thingTranslate : item }}</ion-label> <ion-label class="title">{{ 'event.name' | thingTranslate: item }}</ion-label>
<p> <p>
<ion-icon name="calendar_today"></ion-icon> <ion-icon name="calendar_today"></ion-icon>
<span *ngIf="item.dates[0] && item.dates[item.dates.length - 1]"> <span *ngIf="item.dates[0] && item.dates[item.dates.length - 1]">
<span *ngIf="item.repeatFrequency"> <span *ngIf="item.repeatFrequency">
{{ item.repeatFrequency | durationLocalized : true | sentencecase }}, {{ item.dates[0] | {{ item.repeatFrequency | durationLocalized: true | sentencecase }},
dateFormat : 'weekday:long' }} {{ item.dates[0] | dateFormat: 'weekday:long' }}
</span> </span>
<span> <span>
({{ item.dates[0] | dateFormat }} - {{ item.dates[item.dates.length - 1] | dateFormat }}) ({{ item.dates[0] | dateFormat }} - {{ item.dates[item.dates.length - 1] | dateFormat }})
</span> </span>
</span> </span>
</p> </p>
<ion-note *ngIf="item.event.type === 'academic event'" <ion-note *ngIf="item.event.type === 'academic event'">{{
>{{ 'categories' | thingTranslate : item.event | join : ', ' }}</ion-note 'categories' | thingTranslate: item.event | join: ', '
> }}</ion-note>
</div> </div>
</ion-col> </ion-col>
<ion-col width-20 text-right> <ion-col width-20 text-right>

View File

@@ -15,8 +15,8 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.type === 'academic event' && item.categories" *ngIf="item.type === 'academic event' && item.categories"
[title]="'categories' | propertyNameTranslate : item | titlecase" [title]="'categories' | propertyNameTranslate: item | titlecase"
[content]="'categories' | thingTranslate : item" [content]="'categories' | thingTranslate: item"
> >
</stapps-simple-card> </stapps-simple-card>
@@ -25,23 +25,23 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.performers" *ngIf="item.performers"
[title]="'performers' | propertyNameTranslate : item | titlecase" [title]="'performers' | propertyNameTranslate: item | titlecase"
[content]="item.performers" [content]="item.performers"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.organizers" *ngIf="item.organizers"
[title]="'organizers' | propertyNameTranslate : item | titlecase" [title]="'organizers' | propertyNameTranslate: item | titlecase"
[content]="item.organizers" [content]="item.organizers"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.type === 'academic event' && item.majors | titlecase" *ngIf="item.type === 'academic event' && item.majors | titlecase"
[title]="'majors' | propertyNameTranslate : item" [title]="'majors' | propertyNameTranslate: item"
[content]="item.majors" [content]="item.majors"
></stapps-simple-card> ></stapps-simple-card>
<ion-card *ngIf="item.catalogs"> <ion-card *ngIf="item.catalogs">
<ion-card-header <ion-card-header>{{
>{{ $any('superCatalogs' | propertyNameTranslate : 'catalog') | titlecase }}</ion-card-header $any('superCatalogs' | propertyNameTranslate: 'catalog') | titlecase
> }}</ion-card-header>
<ion-card-content> <ion-card-content>
<event-route-path <event-route-path
*ngFor="let item of item.catalogs" *ngFor="let item of item.catalogs"
@@ -49,7 +49,7 @@
[itemsAfterCollapse]="1" [itemsAfterCollapse]="1"
[itemsBeforeCollapse]="0" [itemsBeforeCollapse]="0"
[items]="[undefined, item]" [items]="[undefined, item]"
[more]="item.uid | lazyThing : 'superCatalogs'" [more]="item.uid | lazyThing: 'superCatalogs'"
> >
</event-route-path> </event-route-path>
</ion-card-content> </ion-card-content>

View File

@@ -20,9 +20,9 @@
[itemsBeforeCollapse]="itemsBeforeCollapse" [itemsBeforeCollapse]="itemsBeforeCollapse"
> >
<ion-breadcrumb *ngFor="let item of items"> <ion-breadcrumb *ngFor="let item of items">
<ion-label class="crumb-label" *ngIf="item" [routerLink]="['/data-detail', item.uid]" <ion-label class="crumb-label" *ngIf="item" [routerLink]="['/data-detail', item.uid]">{{
>{{ 'name' | thingTranslate : $any(item) }}</ion-label 'name' | thingTranslate: $any(item)
> }}</ion-label>
</ion-breadcrumb> </ion-breadcrumb>
</ion-breadcrumbs> </ion-breadcrumbs>
<ion-popover #popover> <ion-popover #popover>
@@ -55,6 +55,6 @@
<ng-template #popoverItem let-item="item"> <ng-template #popoverItem let-item="item">
<ion-item *ngIf="item" [routerLink]="['/data-detail', item.uid]" (click)="popover.dismiss()"> <ion-item *ngIf="item" [routerLink]="['/data-detail', item.uid]" (click)="popover.dismiss()">
{{ 'name' | thingTranslate : $any(item) }} {{ 'name' | thingTranslate: $any(item) }}
</ion-item> </ion-item>
</ng-template> </ng-template>

View File

@@ -18,15 +18,15 @@
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title"> <ion-label class="title">
{{ 'name' | thingTranslate : item }}: {{ 'name' | thingTranslate : item.data }} {{ 'name' | thingTranslate: item }}: {{ 'name' | thingTranslate: item.data }}
</ion-label> </ion-label>
<p *ngIf="item.data.description" class="title-sub"> <p *ngIf="item.data.description" class="title-sub">
<stapps-long-inline-text <stapps-long-inline-text
[text]="'description' | thingTranslate : item.data" [text]="'description' | thingTranslate: item.data"
[size]="80" [size]="80"
></stapps-long-inline-text> ></stapps-long-inline-text>
</p> </p>
<ion-note>{{ 'type' | thingTranslate : item }} ({{ 'type' | thingTranslate : item.data }})</ion-note> <ion-note>{{ 'type' | thingTranslate: item }} ({{ 'type' | thingTranslate: item.data }})</ion-note>
</div> </div>
</ion-col> </ion-col>
<ion-col width-20 text-right> <ion-col width-20 text-right>

View File

@@ -17,7 +17,7 @@
<ion-card-content [innerHtml]="item.description"> </ion-card-content> <ion-card-content [innerHtml]="item.description"> </ion-card-content>
</ion-card> </ion-card>
<ion-card *ngIf="item.sameAs"> <ion-card *ngIf="item.sameAs">
<ion-card-header> {{ 'sameAs' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-card-header> {{ 'sameAs' | propertyNameTranslate: item | titlecase }} </ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-external-link [link]="item.sameAs" [text]="item.name"></stapps-external-link> <stapps-external-link [link]="item.sameAs" [text]="item.name"></stapps-external-link>
</ion-card-content> </ion-card-content>

View File

@@ -15,26 +15,26 @@
<div *ngIf="!item.categories.includes('news'); else news"> <div *ngIf="!item.categories.includes('news'); else news">
<stapps-simple-card <stapps-simple-card
[title]="'messageBody' | propertyNameTranslate : item | titlecase" [title]="'messageBody' | propertyNameTranslate: item | titlecase"
[content]="'messageBody' | thingTranslate : item" [content]="'messageBody' | thingTranslate: item"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
[title]="'audiences' | propertyNameTranslate : item | titlecase" [title]="'audiences' | propertyNameTranslate: item | titlecase"
[content]="'audiences' | thingTranslate : item" [content]="'audiences' | thingTranslate: item"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.datePublished" *ngIf="item.datePublished"
[title]="'datePublished' | propertyNameTranslate : item | titlecase" [title]="'datePublished' | propertyNameTranslate: item | titlecase"
[content]="item.datePublished | amDateFormat : 'll'" [content]="item.datePublished | amDateFormat: 'll'"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.authors" *ngIf="item.authors"
[title]="'authors' | propertyNameTranslate : item | titlecase" [title]="'authors' | propertyNameTranslate: item | titlecase"
[content]="item.authors" [content]="item.authors"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.publishers" *ngIf="item.publishers"
[title]="'publishers' | propertyNameTranslate : item | titlecase" [title]="'publishers' | propertyNameTranslate: item | titlecase"
[content]="item.publishers" [content]="item.publishers"
></stapps-simple-card> ></stapps-simple-card>
</div> </div>
@@ -54,7 +54,7 @@
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card content="{{ item.messageBody }}"></stapps-simple-card> <stapps-simple-card content="{{ item.messageBody }}"></stapps-simple-card>
<ion-card *ngIf="item.sameAs"> <ion-card *ngIf="item.sameAs">
<ion-card-header> {{ 'sameAs' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-card-header> {{ 'sameAs' | propertyNameTranslate: item | titlecase }} </ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-external-link [link]="item.sameAs" [text]="item.name"></stapps-external-link> <stapps-external-link [link]="item.sameAs" [text]="item.name"></stapps-external-link>
</ion-card-content> </ion-card-content>

View File

@@ -17,11 +17,11 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title">{{ 'name' | thingTranslate : item }}</ion-label> <ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
<p *ngIf="item.messageBody"> <p *ngIf="item.messageBody">
<stapps-long-inline-text [text]="item.messageBody" [size]="80"></stapps-long-inline-text> <stapps-long-inline-text [text]="item.messageBody" [size]="80"></stapps-long-inline-text>
</p> </p>
<ion-note>{{ 'type' | thingTranslate : item }}</ion-note> <ion-note>{{ 'type' | thingTranslate: item }}</ion-note>
</div> </div>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -14,10 +14,10 @@
--> -->
<ion-card *ngIf="item.inPlace"> <ion-card *ngIf="item.inPlace">
<ion-card-header> {{ 'inPlace' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-card-header> {{ 'inPlace' | propertyNameTranslate: item | titlecase }} </ion-card-header>
<ion-card-content> <ion-card-content>
<ion-icon name="pin_drop"></ion-icon> <ion-icon name="pin_drop"></ion-icon>
<a [routerLink]="['/data-detail', item.inPlace.uid]">{{ 'name' | thingTranslate : item.inPlace }}</a> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{ 'name' | thingTranslate: item.inPlace }}</a>
<stapps-address-detail <stapps-address-detail
*ngIf="item.inPlace.address" *ngIf="item.inPlace.address"
[address]="item.inPlace.address" [address]="item.inPlace.address"

View File

@@ -17,15 +17,15 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title">{{ 'name' | thingTranslate : item }}</ion-label> <ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
<p *ngIf="item.description" class="title-sub">{{ 'description' | thingTranslate : item }}</p> <p *ngIf="item.description" class="title-sub">{{ 'description' | thingTranslate: item }}</p>
<ion-note>{{ 'type' | thingTranslate : item }}</ion-note> <ion-note>{{ 'type' | thingTranslate: item }}</ion-note>
</div> </div>
</ion-col> </ion-col>
<ion-col width-20 text-right *ngIf="item.inPlace"> <ion-col width-20 text-right *ngIf="item.inPlace">
<span *ngIf="item.inPlace"> <span *ngIf="item.inPlace">
<ion-icon name="pin_drop"></ion-icon> <ion-icon name="pin_drop"></ion-icon>
{{ 'name' | thingTranslate : item.inPlace }} {{ 'name' | thingTranslate: item.inPlace }}
</span> </span>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -16,14 +16,14 @@
<ion-card *ngIf="item.sameAs"> <ion-card *ngIf="item.sameAs">
<ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header> <ion-card-header>{{ 'hebisSearch.detail.title' | translate | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<stapps-external-link [text]="'name' | thingTranslate : item" [link]="item.sameAs"></stapps-external-link> <stapps-external-link [text]="'name' | thingTranslate: item" [link]="item.sameAs"></stapps-external-link>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="!item.sameAs" *ngIf="!item.sameAs"
[title]="'name' | propertyNameTranslate : item | sentencecase" [title]="'name' | propertyNameTranslate: item | sentencecase"
[content]="'name' | thingTranslate : item" [content]="'name' | thingTranslate: item"
> >
</stapps-simple-card> </stapps-simple-card>
@@ -35,14 +35,14 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.sourceOrganization" *ngIf="item.sourceOrganization"
[title]="'sourceOrganization' | propertyNameTranslate : item | sentencecase" [title]="'sourceOrganization' | propertyNameTranslate: item | sentencecase"
[content]="item.sourceOrganization" [content]="item.sourceOrganization"
></stapps-simple-card> ></stapps-simple-card>
<ion-card *ngIf="item.authors && item.authors.length > 0"> <ion-card *ngIf="item.authors && item.authors.length > 0">
<ion-card-header>{{ 'authors' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'authors' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate : author }}</ion-label> <ion-label *ngFor="let author of item.authors">{{ 'name' | thingTranslate: author }}</ion-label>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
@@ -55,30 +55,30 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.firstPublished && item.lastPublished" *ngIf="item.firstPublished && item.lastPublished"
[title]="'hebisSearch.detail.firstPublished' | translate | sentencecase" [title]="'hebisSearch.detail.firstPublished' | translate | sentencecase"
[content]="[item.firstPublished, item.lastPublished] | join : ' - '" [content]="[item.firstPublished, item.lastPublished] | join: ' - '"
> >
</stapps-simple-card> </stapps-simple-card>
<ion-card *ngIf="item.publications"> <ion-card *ngIf="item.publications">
<ion-card-header>{{ 'publications' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'publications' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<p *ngFor="let publication of item.publications"> <p *ngFor="let publication of item.publications">
{{ publication.locations | join : ', ' }} {{ publication.locations && publication.publisher ? ':' : '' {{ publication.locations | join: ', ' }}
}} {{ publication.publisher }} {{ publication.locations && publication.publisher ? ':' : '' }} {{ publication.publisher }}
</p> </p>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<ion-card *ngIf="item.categories"> <ion-card *ngIf="item.categories">
<ion-card-header>{{ 'categories' | propertyNameTranslate : item | sentencecase }}</ion-card-header> <ion-card-header>{{ 'categories' | propertyNameTranslate: item | sentencecase }}</ion-card-header>
<ion-card-content> <ion-card-content>
<ion-chip [color]="'primary'"> <ion-chip [color]="'primary'">
<ion-icon [name]="item.type | dataIcon"></ion-icon> <ion-icon [name]="item.type | dataIcon"></ion-icon>
<ion-label>{{ 'categories' | thingTranslate : item }}</ion-label> <ion-label>{{ 'categories' | thingTranslate: item }}</ion-label>
</ion-chip> </ion-chip>
</ion-card-content> </ion-card-content>
</ion-card> </ion-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.ISSNs" *ngIf="item.ISSNs"
[title]="'ISSNs' | propertyNameTranslate : item | sentencecase" [title]="'ISSNs' | propertyNameTranslate: item | sentencecase"
[content]="item.ISSNs | join : ', '" [content]="item.ISSNs | join: ', '"
> >
</stapps-simple-card> </stapps-simple-card>

View File

@@ -16,20 +16,20 @@
<ion-grid> <ion-grid>
<ion-row> <ion-row>
<ion-col> <ion-col>
<h2 class="name">{{ 'name' | thingTranslate : item }}</h2> <h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
<p> <p>
<ng-container *ngFor="let author of item.authors"> <ng-container *ngFor="let author of item.authors"> {{ 'name' | thingTranslate: author }}</ng-container
{{ 'name' | thingTranslate : author }}</ng-container
><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container> ><ng-container *ngIf="item.authors && item.authors && item.firstPublished">,&nbsp;</ng-container>
<ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange" <ng-container *ngIf="item.firstPublished && !item.lastPublished; else dateRange">{{
>{{ item.firstPublished }}</ng-container item.firstPublished
}}</ng-container
><ng-template #dateRange ><ng-template #dateRange
><ng-container *ngIf="item.firstPublished && item.lastPublished" ><ng-container *ngIf="item.firstPublished && item.lastPublished">{{
>{{ [item.firstPublished, item.lastPublished] | join : ' - ' }}</ng-container [item.firstPublished, item.lastPublished] | join: ' - '
></ng-template }}</ng-container></ng-template
> >
</p> </p>
<ion-note> {{ 'categories' | thingTranslate : item }} </ion-note> <ion-note> {{ 'categories' | thingTranslate: item }} </ion-note>
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>

View File

@@ -17,29 +17,29 @@
<ion-card *ngFor="let contactPoint of contactPoints; let i = index"> <ion-card *ngFor="let contactPoint of contactPoints; let i = index">
<ion-card-header> <ion-card-header>
<ng-container *ngIf="contactPoints.length > 1">{{ i + 1 }}.</ng-container> <ng-container *ngIf="contactPoints.length > 1">{{ i + 1 }}.</ng-container>
{{ 'type' | thingTranslate : contactPoint | titlecase }} {{ 'type' | thingTranslate: contactPoint | titlecase }}
</ion-card-header> </ion-card-header>
<ion-card-content> <ion-card-content>
<p *ngIf="contactPoint.telephone"> <p *ngIf="contactPoint.telephone">
{{ 'telephone' | propertyNameTranslate : contactPoint | titlecase }}: {{ 'telephone' | propertyNameTranslate: contactPoint | titlecase }}:
<a [href]="'tel:' + contactPoint.telephone">{{ contactPoint.telephone }}</a> <a [href]="'tel:' + contactPoint.telephone">{{ contactPoint.telephone }}</a>
</p> </p>
<p *ngIf="contactPoint.email"> <p *ngIf="contactPoint.email">
{{ 'email' | propertyNameTranslate : contactPoint | titlecase }}: {{ 'email' | propertyNameTranslate: contactPoint | titlecase }}:
<a [href]="'mailto:' + contactPoint.email">{{ contactPoint.email }}</a> <a [href]="'mailto:' + contactPoint.email">{{ contactPoint.email }}</a>
</p> </p>
<p *ngIf="contactPoint.faxNumber"> <p *ngIf="contactPoint.faxNumber">
{{ 'faxNumber' | propertyNameTranslate : contactPoint | titlecase }}: {{ contactPoint.faxNumber }} {{ 'faxNumber' | propertyNameTranslate: contactPoint | titlecase }}: {{ contactPoint.faxNumber }}
</p> </p>
<p *ngIf="contactPoint.officeHours"> <p *ngIf="contactPoint.officeHours">
{{ 'officeHours' | propertyNameTranslate : contactPoint | titlecase }}: {{ contactPoint.officeHours }} {{ 'officeHours' | propertyNameTranslate: contactPoint | titlecase }}: {{ contactPoint.officeHours }}
</p> </p>
<p *ngIf="contactPoint.url"> <p *ngIf="contactPoint.url">
{{ 'url' | propertyNameTranslate : contactPoint | titlecase }}: {{ 'url' | propertyNameTranslate: contactPoint | titlecase }}:
<a [href]="contactPoint.url">{{ contactPoint.url }}</a> <a [href]="contactPoint.url">{{ contactPoint.url }}</a>
</p> </p>
<p *ngIf="contactPoint.areaServed"> <p *ngIf="contactPoint.areaServed">
{{ 'areaServed' | propertyNameTranslate : contactPoint | titlecase }}: {{ 'areaServed' | propertyNameTranslate: contactPoint | titlecase }}:
<a [routerLink]="['/data-detail', contactPoint.areaServed.uid]">{{ contactPoint.areaServed.name }}</a> <a [routerLink]="['/data-detail', contactPoint.areaServed.uid]">{{ contactPoint.areaServed.name }}</a>
</p> </p>
</ion-card-content> </ion-card-content>
@@ -47,6 +47,6 @@
</ng-container> </ng-container>
<stapps-simple-card <stapps-simple-card
*ngIf="item.jobTitles?.length > 0" *ngIf="item.jobTitles?.length > 0"
[title]="'jobTitles' | propertyNameTranslate : item | titlecase" [title]="'jobTitles' | propertyNameTranslate: item | titlecase"
[content]="item.jobTitles" [content]="item.jobTitles"
></stapps-simple-card> ></stapps-simple-card>

View File

@@ -18,7 +18,7 @@
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title"> <ion-label class="title">
{{ 'name' | thingTranslate : item }} {{ 'name' | thingTranslate: item }}
<span *ngIf="item.honorificPrefix">, {{ item.honorificPrefix }}</span> <span *ngIf="item.honorificPrefix">, {{ item.honorificPrefix }}</span>
</ion-label> </ion-label>
<p *ngIf="item.telephone || item.email"> <p *ngIf="item.telephone || item.email">

View File

@@ -26,7 +26,10 @@ import {SettingsProvider} from '../../../../../settings/settings.provider';
providedIn: 'root', providedIn: 'root',
}) })
export class PlaceMensaService { export class PlaceMensaService {
constructor(private dataProvider: DataProvider, readonly settingsProvider: SettingsProvider) {} constructor(
private dataProvider: DataProvider,
readonly settingsProvider: SettingsProvider,
) {}
/** /**
* Fetches all dishes for this building * Fetches all dishes for this building
@@ -39,10 +42,13 @@ export class PlaceMensaService {
Array.from({length: days}) Array.from({length: days})
.map((_, i) => i) .map((_, i) => i)
.map(i => moment().add(i, 'days').toISOString()) .map(i => moment().add(i, 'days').toISOString())
.reduce((accumulator, item) => { .reduce(
accumulator[item] = item; (accumulator, item) => {
return accumulator; accumulator[item] = item;
}, {} as Record<SCISO8601Date, SCISO8601Date>), return accumulator;
},
{} as Record<SCISO8601Date, SCISO8601Date>,
),
date => ({ date => ({
filter: { filter: {
arguments: { arguments: {

View File

@@ -18,12 +18,12 @@
<ng-container *ngIf="(dishes | json) !== '{}'; else empty"> <ng-container *ngIf="(dishes | json) !== '{}'; else empty">
<ion-segment [(ngModel)]="selectedDay" mode="md"> <ion-segment [(ngModel)]="selectedDay" mode="md">
<ion-segment-button *ngFor="let day of dishes | keyvalue" [value]="day.key"> <ion-segment-button *ngFor="let day of dishes | keyvalue" [value]="day.key">
<ion-label class="ion-hide-sm-down" <ion-label class="ion-hide-sm-down">{{
>{{ day.key | dateFormat : 'weekday:long,month:numeric,day:numeric' }}</ion-label day.key | dateFormat: 'weekday:long,month:numeric,day:numeric'
> }}</ion-label>
<ion-label class="ion-hide-sm-up" <ion-label class="ion-hide-sm-up">{{
>{{ day.key | dateFormat : 'weekday:short,month:numeric,day:numeric' }}</ion-label day.key | dateFormat: 'weekday:short,month:numeric,day:numeric'
> }}</ion-label>
</ion-segment-button> </ion-segment-button>
</ion-segment> </ion-segment>
<ng-container [ngSwitch]="selectedDay"> <ng-container [ngSwitch]="selectedDay">
@@ -33,8 +33,10 @@
<ng-container *ngFor="let section of date.value | keyvalue"> <ng-container *ngFor="let section of date.value | keyvalue">
<ion-list-header *ngIf="section.value[0].menuSection" lines="inset"> <ion-list-header *ngIf="section.value[0].menuSection" lines="inset">
<ion-label class="title"> <ion-label class="title">
{{ 'data.types.dish.detail.' + section.value[0].menuSection.name | translate | titlecase {{
}} {{ section.value[0].menuSection.servingHours }} 'data.types.dish.detail.' + section.value[0].menuSection.name | translate | titlecase
}}
{{ section.value[0].menuSection.servingHours }}
</ion-label> </ion-label>
</ion-list-header> </ion-list-header>
<ng-container *ngFor="let dish of section.value; index as j"> <ng-container *ngFor="let dish of section.value; index as j">

View File

@@ -16,11 +16,9 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.eventsStartDate && item.eventsEndDate" *ngIf="item.eventsStartDate && item.eventsEndDate"
[title]=" [title]="
('eventsStartDate' | propertyNameTranslate : item | titlecase) + ('eventsStartDate' | propertyNameTranslate: item | titlecase) +
' - ' + ' - ' +
('eventsEndDate' | propertyNameTranslate : item | titlecase) ('eventsEndDate' | propertyNameTranslate: item | titlecase)
"
[content]="
(item.eventsStartDate | amDateFormat : 'll') + ' - ' + (item.eventsEndDate | amDateFormat : 'll')
" "
[content]="(item.eventsStartDate | amDateFormat: 'll') + ' - ' + (item.eventsEndDate | amDateFormat: 'll')"
></stapps-simple-card> ></stapps-simple-card>

View File

@@ -17,12 +17,12 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title">{{ 'name' | thingTranslate : item }}</ion-label> <ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
<p class="title-sub"> <p class="title-sub">
<ion-icon name="calendar_today"></ion-icon> <ion-icon name="calendar_today"></ion-icon>
<span>{{ item.startDate | dateFormat }} - {{ item.endDate | dateFormat }}</span> <span>{{ item.startDate | dateFormat }} - {{ item.endDate | dateFormat }}</span>
</p> </p>
<ion-note>{{ 'type' | thingTranslate : item }}</ion-note> <ion-note>{{ 'type' | thingTranslate: item }}</ion-note>
</div> </div>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -15,18 +15,18 @@
<stapps-simple-card <stapps-simple-card
*ngIf="item.actors" *ngIf="item.actors"
[title]="'actors' | propertyNameTranslate : item | titlecase" [title]="'actors' | propertyNameTranslate: item | titlecase"
[content]="item.actors" [content]="item.actors"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.authors" *ngIf="item.authors"
[title]="'authors' | propertyNameTranslate : item | titlecase" [title]="'authors' | propertyNameTranslate: item | titlecase"
[content]="item.authors" [content]="item.authors"
></stapps-simple-card> ></stapps-simple-card>
<stapps-simple-card <stapps-simple-card
*ngIf="item.datePublished" *ngIf="item.datePublished"
[title]="'datePublished' | propertyNameTranslate : item | titlecase" [title]="'datePublished' | propertyNameTranslate: item | titlecase"
[content]="item.datePublished | amDateFormat : 'll'" [content]="item.datePublished | amDateFormat: 'll'"
> >
</stapps-simple-card> </stapps-simple-card>
<stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail> <stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail>

View File

@@ -2,18 +2,18 @@
<ion-row> <ion-row>
<ion-col> <ion-col>
<div class="ion-text-wrap"> <div class="ion-text-wrap">
<ion-label class="title">{{ 'name' | thingTranslate : item }}</ion-label> <ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
<p *ngIf="item.description" class="title-sub"> <p *ngIf="item.description" class="title-sub">
<stapps-long-inline-text <stapps-long-inline-text
[text]="'description' | thingTranslate : item" [text]="'description' | thingTranslate: item"
[size]="80" [size]="80"
></stapps-long-inline-text> ></stapps-long-inline-text>
</p> </p>
<p *ngIf="item.duration"> <p *ngIf="item.duration">
{{ 'duration' | propertyNameTranslate : item | titlecase }}: {{ item.duration | amDuration : {{ 'duration' | propertyNameTranslate: item | titlecase }}:
'seconds' }} {{ item.duration | amDuration: 'seconds' }}
</p> </p>
<ion-note>{{ 'type' | thingTranslate : item }}</ion-note> <ion-note>{{ 'type' | thingTranslate: item }}</ion-note>
</div> </div>
</ion-col> </ion-col>
</ion-row> </ion-row>

View File

@@ -44,12 +44,12 @@
interface="popover" interface="popover"
required="true" required="true"
> >
<ion-select-option value="Comment" <ion-select-option value="Comment">{{
>{{ 'feedback.form.type.values.comment' | translate }}</ion-select-option 'feedback.form.type.values.comment' | translate
> }}</ion-select-option>
<ion-select-option value="Bug" <ion-select-option value="Bug">{{
>{{ 'feedback.form.type.values.bug' | translate }}</ion-select-option 'feedback.form.type.values.bug' | translate
> }}</ion-select-option>
</ion-select> </ion-select>
</ion-item> </ion-item>
<ion-item> <ion-item>
@@ -91,9 +91,9 @@
</ion-item> </ion-item>
<ion-item lines="none"> <ion-item lines="none">
<ion-label <ion-label
><a style="display: contents" [routerLink]="['/about/privacy']" ><a style="display: contents" [routerLink]="['/about/privacy']">{{
>{{ 'feedback.form.termsAgree.1' | translate }}</a 'feedback.form.termsAgree.1' | translate
></ion-label }}</a></ion-label
> >
</ion-item> </ion-item>
<ion-item> <ion-item>
@@ -110,9 +110,9 @@
<ion-card> <ion-card>
<ion-card-title> <ion-card-title>
<ion-button expand="block" fill="clear" (click)="toggleShowMetaData()"> <ion-button expand="block" fill="clear" (click)="toggleShowMetaData()">
<ng-container *ngIf="!showMetaData; else hide" <ng-container *ngIf="!showMetaData; else hide">{{
>{{ 'feedback.form.protocolData.show' | translate }}</ng-container 'feedback.form.protocolData.show' | translate
> }}</ng-container>
<ng-template #hide>{{ 'feedback.form.protocolData.hide' | translate }}</ng-template> <ng-template #hide>{{ 'feedback.form.protocolData.hide' | translate }}</ng-template>
</ion-button> </ion-button>
</ion-card-title> </ion-card-title>

View File

@@ -67,6 +67,6 @@
</ion-row> </ion-row>
<ion-row *ngIf="holding.dueDate"> <ion-row *ngIf="holding.dueDate">
<ion-col size="3">{{ 'hebisSearch.daia.dueDate' | translate }}</ion-col> <ion-col size="3">{{ 'hebisSearch.daia.dueDate' | translate }}</ion-col>
<ion-col size="9">{{ holding.dueDate | amDateFormat : 'll' }}</ion-col> <ion-col size="9">{{ holding.dueDate | amDateFormat: 'll' }}</ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>

View File

@@ -38,8 +38,8 @@
</ion-item> </ion-item>
<stapps-simple-card <stapps-simple-card
*ngIf="item.description" *ngIf="item.description"
[title]="'description' | propertyNameTranslate : item | titlecase" [title]="'description' | propertyNameTranslate: item | titlecase"
[content]="'description' | thingTranslate : item" [content]="'description' | thingTranslate: item"
></stapps-simple-card> ></stapps-simple-card>
</ng-container> </ng-container>
</div> </div>

View File

@@ -24,26 +24,26 @@
<ion-content> <ion-content>
<p *ngIf="name; else loading"> <p *ngIf="name; else loading">
{{ 'library.account.greeting' | translate }} {{ name | firstLastName }}! {{ {{ 'library.account.greeting' | translate }} {{ name | firstLastName }}!
'library.account.login.success' | translate }} {{ 'library.account.login.success' | translate }}
</p> </p>
<ng-template #loading> <ng-template #loading>
<p><ion-skeleton-text animated style="width: 80%"></ion-skeleton-text></p> <p><ion-skeleton-text animated style="width: 80%"></ion-skeleton-text></p>
</ng-template> </ng-template>
<ion-item [routerLink]="['profile']"> <ion-item [routerLink]="['profile']">
<ion-icon name="account_circle" slot="start"></ion-icon>{{ 'library.account.pages.profile.title' | <ion-icon name="account_circle" slot="start"></ion-icon
translate | titlecase }} >{{ 'library.account.pages.profile.title' | translate | titlecase }}
</ion-item> </ion-item>
<ion-item [routerLink]="['holds']"> <ion-item [routerLink]="['holds']">
<ion-icon name="collections_bookmark" slot="start"></ion-icon>{{ 'library.account.pages.holds.title' | <ion-icon name="collections_bookmark" slot="start"></ion-icon
translate | titlecase }} >{{ 'library.account.pages.holds.title' | translate | titlecase }}
</ion-item> </ion-item>
<ion-item [routerLink]="['checked-out']"> <ion-item [routerLink]="['checked-out']">
<ion-icon name="book" slot="start"></ion-icon>{{ 'library.account.pages.checked_out.title' | translate | <ion-icon name="book" slot="start"></ion-icon
titlecase }} >{{ 'library.account.pages.checked_out.title' | translate | titlecase }}
</ion-item> </ion-item>
<ion-item [routerLink]="['fines']"> <ion-item [routerLink]="['fines']">
<ion-icon name="request_quote" slot="start"></ion-icon>{{ 'library.account.pages.fines.title' | translate <ion-icon name="request_quote" slot="start"></ion-icon
| titlecase }} >{{ 'library.account.pages.fines.title' | translate | titlecase }}
</ion-item> </ion-item>
</ion-content> </ion-content>

View File

@@ -28,7 +28,7 @@
<p *ngIf="fee[property]"> <p *ngIf="fee[property]">
{{ 'library.account.pages.fines.labels' + '.' + property | translate }}: {{ 'library.account.pages.fines.labels' + '.' + property | translate }}:
<ng-container *ngIf="!['date'].includes(property); else date"> {{ fee[property] }} </ng-container> <ng-container *ngIf="!['date'].includes(property); else date"> {{ fee[property] }} </ng-container>
<ng-template #date> {{ fee[property] | amDateFormat : 'll' }} </ng-template> <ng-template #date> {{ fee[property] | amDateFormat: 'll' }} </ng-template>
</p></ng-container </p></ng-container
> >
</ion-label> </ion-label>

View File

@@ -23,7 +23,7 @@
<ng-container *ngIf="!['endtime', 'duedate'].includes(property); else date"> <ng-container *ngIf="!['endtime', 'duedate'].includes(property); else date">
{{ item[property] }} {{ item[property] }}
</ng-container> </ng-container>
<ng-template #date> {{ item[property] | amDateFormat : 'll' }} </ng-template> <ng-template #date> {{ item[property] | amDateFormat: 'll' }} </ng-template>
</p> </p>
</ng-container> </ng-container>
<span class="ion-float-right"> <span class="ion-float-right">

View File

@@ -37,8 +37,9 @@
{{ 'library.account.pages.profile.values.unlimited' | translate }} {{ 'library.account.pages.profile.values.unlimited' | translate }}
</ng-container> </ng-container>
<ng-template #exactDate> <ng-template #exactDate>
{{ 'library.account.pages.profile.values.expires' | translate }}:&nbsp;{{ patron[property] | {{ 'library.account.pages.profile.values.expires' | translate }}:&nbsp;{{
amDateFormat : 'll' }} patron[property] | amDateFormat: 'll'
}}
</ng-template> </ng-template>
</ng-template> </ng-template>
</ion-col> </ion-col>

View File

@@ -402,8 +402,8 @@ export class MapPageComponent implements OnInit {
this.locationStatus?.location === 'denied' this.locationStatus?.location === 'denied'
? location.NOT_ALLOWED ? location.NOT_ALLOWED
: this.locationStatus?.location === 'granted' : this.locationStatus?.location === 'granted'
? unknownError ? unknownError
: location.NOT_ENABLED : location.NOT_ENABLED
}`, }`,
buttons: ['OK'], buttons: ['OK'],
}) })

View File

@@ -21,13 +21,13 @@
[leafletOptions]="options" [leafletOptions]="options"
></div> ></div>
@if (showExpandButton) { @if (showExpandButton) {
<div class="map-buttons"> <div class="map-buttons">
<ion-button color="primary" shape="round" size="small" [geoNavigation]="place"> <ion-button color="primary" shape="round" size="small" [geoNavigation]="place">
<ion-icon name="directions" slot="start"></ion-icon> <ion-icon name="directions" slot="start"></ion-icon>
{{'map.directions.TITLE' | translate}} {{ 'map.directions.TITLE' | translate }}
</ion-button> </ion-button>
<ion-button color="primary" shape="round" size="small" [routerLink]="['/map', place.uid]"> <ion-button color="primary" shape="round" size="small" [routerLink]="['/map', place.uid]">
<ion-icon name="zoom_out_map"></ion-icon> <ion-icon name="zoom_out_map"></ion-icon>
</ion-button> </ion-button>
</div> </div>
} }

View File

@@ -56,7 +56,9 @@
<div> <div>
<ion-list-header class="h3"> <ion-list-header class="h3">
<ion-label> <ion-label>
<span *ngIf="facet.info.onlyOnType"><b>{{ facet.info.onlyOnType | titlecase }}</b> / </span> <span *ngIf="facet.info.onlyOnType"
><b>{{ facet.info.onlyOnType | titlecase }}</b> /
</span>
{{ facet.info.field | titlecase }} {{ facet.info.field | titlecase }}
</ion-label> </ion-label>
</ion-list-header> </ion-list-header>
@@ -78,9 +80,12 @@
}" }"
class="filter-item-label" class="filter-item-label"
> >
({{ bucket.count }}) {{ facet.field === 'type' ? (getTranslatedPropertyValue($any(bucket.key), ({{ bucket.count }})
'type') | titlecase) : (getTranslatedPropertyValue(facet.onlyOnType, facet.field, bucket.key) {{
| titlecase) }} facet.field === 'type'
? (getTranslatedPropertyValue($any(bucket.key), 'type') | titlecase)
: (getTranslatedPropertyValue(facet.onlyOnType, facet.field, bucket.key) | titlecase)
}}
</ion-checkbox> </ion-checkbox>
</ion-item> </ion-item>
<ion-button <ion-button

View File

@@ -25,28 +25,29 @@
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@if (menu) { @if (menu) {
<ion-content> <ion-content>
@for (category of menu; track category; let isFirst = first) { @for (category of menu; track category; let isFirst = first) {
<ion-list> <ion-list>
@if (category.title !== '') { @if (category.title !== '') {
<ion-item <ion-item
[rootLink]="category.route" [rootLink]="category.route"
[redirectedFrom]="isFirst ? '/' : category.route" [redirectedFrom]="isFirst ? '/' : category.route"
lines="none" lines="none"
class="menu-category" class="menu-category"
> >
<ion-icon slot="end" [name]="category.icon"></ion-icon> <ion-icon slot="end" [name]="category.icon"></ion-icon>
<ion-label> {{ category.translations[language].title | titlecase }} </ion-label> <ion-label> {{ category.translations[language].title | titlecase }} </ion-label>
</ion-item> </ion-item>
} @for (item of category.items; track item) { }
<ion-item [rootLink]="item.route" [redirectedFrom]="item.route"> @for (item of category.items; track item) {
<ion-icon slot="end" [name]="item.icon"></ion-icon> <ion-item [rootLink]="item.route" [redirectedFrom]="item.route">
<ion-label> {{ item.translations[language].title | titlecase }} </ion-label> <ion-icon slot="end" [name]="item.icon"></ion-icon>
</ion-item> <ion-label> {{ item.translations[language].title | titlecase }} </ion-label>
</ion-item>
}
</ion-list>
} }
</ion-list> </ion-content>
}
</ion-content>
} }
</ion-menu> </ion-menu>
<ion-router-outlet id="main"></ion-router-outlet> <ion-router-outlet id="main"></ion-router-outlet>

View File

@@ -22,7 +22,10 @@ import {NGXLogger} from 'ngx-logger';
providedIn: 'root', providedIn: 'root',
}) })
export class NavigationService { export class NavigationService {
constructor(private configProvider: ConfigProvider, private logger: NGXLogger) {} constructor(
private configProvider: ConfigProvider,
private logger: NGXLogger,
) {}
async getMenu() { async getMenu() {
let menu: SCAppConfigurationMenuCategory[] = []; let menu: SCAppConfigurationMenuCategory[] = [];

View File

@@ -20,9 +20,9 @@
</ion-tab-button> </ion-tab-button>
</ion-menu-toggle> </ion-menu-toggle>
@for (category of menu; track category) { @for (category of menu; track category) {
<ion-tab-button [rootLink]="category.route" [redirectedFrom]="category.route" [tab]="category.title"> <ion-tab-button [rootLink]="category.route" [redirectedFrom]="category.route" [tab]="category.title">
<ion-icon [name]="category.icon"></ion-icon> <ion-icon [name]="category.icon"></ion-icon>
<ion-label>{{ category.translations[language].title | titlecase }}</ion-label> <ion-label>{{ category.translations[language].title | titlecase }}</ion-label>
</ion-tab-button> </ion-tab-button>
} }
</ion-tab-bar> </ion-tab-bar>

Some files were not shown because too many files have changed in this diff Show More