feat: assessments module

This commit is contained in:
Thea Schöbl
2022-03-17 09:59:52 +00:00
parent eea8d6d339
commit e68d1b73f9
51 changed files with 3372 additions and 222 deletions

View File

@@ -1,19 +1,20 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Component, Input} from '@angular/core';
import {Component, Input, TemplateRef} from '@angular/core';
import {SCThings} from '@openstapps/core';
import {DataListContext} from '../list/data-list.component';
/**
* TODO
@@ -28,4 +29,6 @@ export class DataDetailContentComponent {
* TODO
*/
@Input() item: SCThings;
@Input() contentTemplateRef?: TemplateRef<DataListContext<SCThings>>;
}

View File

@@ -1,86 +1,99 @@
<stapps-title-card [item]="item"> </stapps-title-card>
<div [ngSwitch]="item.type">
<stapps-article-detail-content
[item]="item"
*ngSwitchCase="'article'"
></stapps-article-detail-content>
<stapps-catalog-detail-content
[item]="item"
*ngSwitchCase="'catalog'"
></stapps-catalog-detail-content>
<stapps-date-series-detail-content
[item]="item"
*ngSwitchCase="'date series'"
></stapps-date-series-detail-content>
<stapps-dish-detail-content
[item]="item"
*ngSwitchCase="'dish'"
></stapps-dish-detail-content>
<stapps-event-detail-content
[item]="item"
*ngSwitchCase="'academic event'"
></stapps-event-detail-content>
<stapps-event-detail-content
[item]="item"
*ngSwitchCase="'sport course'"
></stapps-event-detail-content>
<stapps-favorite-detail-content
[item]="item"
*ngSwitchCase="'favorite'"
></stapps-favorite-detail-content>
<stapps-message-detail-content
[item]="item"
*ngSwitchCase="'message'"
></stapps-message-detail-content>
<stapps-person-detail-content
[item]="item"
*ngSwitchCase="'person'"
></stapps-person-detail-content>
<stapps-place-detail-content
[item]="item"
*ngSwitchCase="'building'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="item"
*ngSwitchCase="'floor'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="item"
*ngSwitchCase="'point of interest'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="item"
*ngSwitchCase="'room'"
></stapps-place-detail-content>
<stapps-semester-detail-content
[item]="item"
*ngSwitchCase="'semester'"
></stapps-semester-detail-content>
<stapps-video-detail-content
[item]="item"
*ngSwitchCase="'video'"
></stapps-video-detail-content>
<ng-container *ngSwitchDefault>
<ion-item class="ion-text-wrap" lines="inset">
<ion-thumbnail slot="start" class="ion-margin-end">
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
</ion-thumbnail>
<ion-grid>
<ion-row>
<ion-col>
<div class="ion-text-wrap">
<h2 class="name">{{ item.name }}</h2>
<ion-note>{{ item.type }}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<stapps-simple-card
*ngIf="item.description"
[title]="'description' | propertyNameTranslate: item | titlecase"
[content]="'description' | thingTranslate: item"
></stapps-simple-card>
</ng-container>
</div>
<ng-container
*ngTemplateOutlet="
contentTemplateRef || defaultContent;
context: {$implicit: item}
"
>
</ng-container>
<stapps-origin-detail [origin]="item.origin"></stapps-origin-detail>
<ng-template #defaultContent>
<div [ngSwitch]="item.type">
<stapps-article-detail-content
[item]="$any(item)"
*ngSwitchCase="'article'"
></stapps-article-detail-content>
<stapps-catalog-detail-content
[item]="$any(item)"
*ngSwitchCase="'catalog'"
></stapps-catalog-detail-content>
<stapps-date-series-detail-content
[item]="$any(item)"
*ngSwitchCase="'date series'"
></stapps-date-series-detail-content>
<stapps-dish-detail-content
[item]="$any(item)"
*ngSwitchCase="'dish'"
></stapps-dish-detail-content>
<stapps-event-detail-content
[item]="$any(item)"
*ngSwitchCase="'academic event'"
></stapps-event-detail-content>
<stapps-event-detail-content
[item]="$any(item)"
*ngSwitchCase="'sport course'"
></stapps-event-detail-content>
<stapps-favorite-detail-content
[item]="$any(item)"
*ngSwitchCase="'favorite'"
></stapps-favorite-detail-content>
<stapps-message-detail-content
[item]="$any(item)"
*ngSwitchCase="'message'"
></stapps-message-detail-content>
<stapps-person-detail-content
[item]="$any(item)"
*ngSwitchCase="'person'"
></stapps-person-detail-content>
<stapps-place-detail-content
[item]="$any(item)"
*ngSwitchCase="'building'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="$any(item)"
*ngSwitchCase="'floor'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="$any(item)"
*ngSwitchCase="'point of interest'"
></stapps-place-detail-content>
<stapps-place-detail-content
[item]="$any(item)"
*ngSwitchCase="'room'"
></stapps-place-detail-content>
<stapps-semester-detail-content
[item]="$any(item)"
*ngSwitchCase="'semester'"
></stapps-semester-detail-content>
<stapps-video-detail-content
[item]="$any(item)"
*ngSwitchCase="'video'"
></stapps-video-detail-content>
<ng-container *ngSwitchDefault>
<ion-item class="ion-text-wrap" lines="inset">
<ion-thumbnail slot="start" class="ion-margin-end">
<ion-icon
color="medium"
[attr.name]="item.type | dataIcon"
></ion-icon>
</ion-thumbnail>
<ion-grid>
<ion-row>
<ion-col>
<div class="ion-text-wrap">
<h2 class="name">{{ item.name }}</h2>
<ion-note>{{ item.type }}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
<stapps-simple-card
*ngIf="item.description"
[title]="$any('description' | propertyNameTranslate: item) | titlecase"
[content]="'description' | thingTranslate: item"
></stapps-simple-card>
</ng-container>
</div>
</ng-template>

View File

@@ -1,18 +1,19 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any */
/*
* Copyright (C) 2018, 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* eslint-disable @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-explicit-any */
import {CUSTOM_ELEMENTS_SCHEMA, DebugElement} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {ActivatedRoute, RouterModule} from '@angular/router';
@@ -118,9 +119,10 @@ describe('DataDetailComponent', () => {
});
it('should get a data item', () => {
comp.getItem(sampleThing.uid);
comp.getItem(sampleThing.uid, false);
expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(
sampleThing.uid,
false,
);
});
@@ -128,6 +130,7 @@ describe('DataDetailComponent', () => {
comp.ionViewWillEnter();
expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(
sampleThing.uid,
false,
);
});
@@ -135,6 +138,7 @@ describe('DataDetailComponent', () => {
await comp.refresh(refresher);
expect(DataDetailComponent.prototype.getItem).toHaveBeenCalledWith(
sampleThing.uid,
true,
);
expect(refresher.complete).toHaveBeenCalled();
});

View File

@@ -1,20 +1,27 @@
/*
* Copyright (C) 2018, 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Component} from '@angular/core';
import {
Component,
ContentChild,
EventEmitter,
Input,
Output,
TemplateRef,
} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {IonRefresher} from '@ionic/angular';
import {IonRefresher, ViewWillEnter} from '@ionic/angular';
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import {
SCLanguageCode,
@@ -26,6 +33,13 @@ import {DataProvider, DataScope} from '../data.provider';
import {FavoritesService} from '../../favorites/favorites.service';
import {take} from 'rxjs/operators';
import {Network} from '@capacitor/network';
import {DataListContext} from '../list/data-list.component';
export interface ExternalDataLoadEvent {
uid: SCUuid;
forceReload: boolean;
resolve: (item: SCThings | null | undefined) => void;
}
/**
* A Component to display an SCThing detailed
@@ -35,7 +49,7 @@ import {Network} from '@capacitor/network';
styleUrls: ['data-detail.scss'],
templateUrl: 'data-detail.html',
})
export class DataDetailComponent {
export class DataDetailComponent implements ViewWillEnter {
/**
* The associated item
*
@@ -53,6 +67,25 @@ export class DataDetailComponent {
*/
isDisconnected: Promise<boolean>;
@ContentChild(TemplateRef) contentTemplateRef: TemplateRef<
DataListContext<SCThings>
>;
@Input() externalData = false;
/**
* This is kind of a stupid situation where we would
* like to use the default header in overriding elements
* such as the assessment detail page, however the ionic
* back button will not work if the header is in a subcomponent
* which then means we have to copy and paste the header from
* here into the overriding component.
*/
@Input() defaultHeader = true;
@Output() loadItem: EventEmitter<ExternalDataLoadEvent> =
new EventEmitter<ExternalDataLoadEvent>();
/**
* Type guard for SCSavableThing
*/
@@ -90,11 +123,22 @@ export class DataDetailComponent {
* Provides data item with given UID
*
* @param uid Unique identifier of a thing
* @param forceReload Indicating whether cached data should be ignored
*/
async getItem(uid: SCUuid) {
async getItem(uid: SCUuid, forceReload: boolean) {
try {
const item = await this.dataProvider.get(uid, DataScope.Remote);
this.item = DataDetailComponent.isSCSavableThing(item) ? item.data : item;
const item = await (this.externalData
? new Promise<SCThings | null | undefined>(resolve =>
this.loadItem.emit({uid, forceReload, resolve}),
)
: this.dataProvider.get(uid, DataScope.Remote));
this.item = !item
? // eslint-disable-next-line unicorn/no-null
null
: DataDetailComponent.isSCSavableThing(item)
? item.data
: item;
} catch {
// eslint-disable-next-line unicorn/no-null
this.item = null;
@@ -106,7 +150,7 @@ export class DataDetailComponent {
*/
async ionViewWillEnter() {
const uid = this.route.snapshot.paramMap.get('uid') || '';
await this.getItem(uid ?? '');
await this.getItem(uid ?? '', false);
// fallback to the saved item (from favorites)
if (this.item === null) {
this.favoritesService
@@ -126,7 +170,7 @@ export class DataDetailComponent {
* @param refresher Refresher component that triggers the update
*/
async refresh(refresher: IonRefresher) {
await this.getItem(this.route.snapshot.paramMap.get('uid') ?? '');
await this.getItem(this.route.snapshot.paramMap.get('uid') ?? '', true);
await refresher.complete();
}
}

View File

@@ -1,4 +1,4 @@
<ion-header>
<ion-header *ngIf="defaultHeader">
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
@@ -8,11 +8,12 @@
<ion-buttons slot="primary">
<stapps-favorite-button
*ngIf="item"
[item]="item"
[item]="$any(item)"
></stapps-favorite-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ng-content select="[header]"></ng-content>
<ion-content class="ion-no-padding">
<ion-refresher slot="fixed" (ionRefresh)="refresh($event.target)">
<ion-refresher-content
@@ -44,7 +45,10 @@
<stapps-skeleton-simple-card></stapps-skeleton-simple-card>
</ng-container>
<ng-container *ngSwitchDefault>
<stapps-data-detail-content [item]="item"></stapps-data-detail-content>
<stapps-data-detail-content
[item]="item"
[contentTemplateRef]="contentTemplateRef"
></stapps-data-detail-content>
</ng-container>
</div>
</ion-content>

View File

@@ -1,20 +1,21 @@
/*
* Copyright (C) 2018-2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Component, Input} from '@angular/core';
import {Component, ContentChild, Input, TemplateRef} from '@angular/core';
import {SCThings} from '@openstapps/core';
import {DataRoutingService} from '../data-routing.service';
import {DataListContext} from './data-list.component';
/**
* Shows data items in lists such es search result
@@ -35,6 +36,12 @@ export class DataListItemComponent {
*/
@Input() item: SCThings;
@Input() favoriteButton = true;
@ContentChild(TemplateRef) contentTemplateRef: TemplateRef<
DataListContext<SCThings>
>;
constructor(private readonly dataRoutingService: DataRoutingService) {}
/**

View File

@@ -8,66 +8,83 @@
<ion-thumbnail slot="start" *ngIf="!hideThumbnail" class="ion-margin-end">
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
</ion-thumbnail>
<ng-container *ngIf="contentTemplateRef; else defaultContent">
<ion-label class="ion-text-wrap" [ngSwitch]="true">
<div>
<ng-container
*ngTemplateOutlet="contentTemplateRef; context: {$implicit: item}"
></ng-container>
</div>
</ion-label>
</ng-container>
<stapps-favorite-button
*ngIf="favoriteButton"
[item]="$any(item)"
></stapps-favorite-button>
</ion-item>
<ng-template #defaultContent>
<ion-label class="ion-text-wrap" [ngSwitch]="true">
<div>
<stapps-catalog-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'catalog'"
></stapps-catalog-list-item>
<stapps-date-series-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'date series'"
></stapps-date-series-list-item>
<stapps-dish-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'dish'"
></stapps-dish-list-item>
<stapps-event-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'academic event'"
></stapps-event-list-item>
<stapps-event-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'sport course'"
></stapps-event-list-item>
<stapps-favorite-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'favorite'"
></stapps-favorite-list-item>
<stapps-message-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'message'"
></stapps-message-list-item>
<stapps-organization-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'organization'"
></stapps-organization-list-item>
<stapps-person-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'person'"
></stapps-person-list-item>
<stapps-place-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'building'"
></stapps-place-list-item>
<stapps-place-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'floor'"
></stapps-place-list-item>
<stapps-place-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'point of interest'"
></stapps-place-list-item>
<stapps-place-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'room'"
></stapps-place-list-item>
<stapps-semester-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'semester'"
></stapps-semester-list-item>
<stapps-video-list-item
[item]="item"
[item]="$any(item)"
*ngSwitchCase="item.type === 'video'"
></stapps-video-list-item>
<div *ngSwitchDefault>
@@ -87,5 +104,4 @@
></stapps-action-chip-list>
</div>
</ion-label>
<stapps-favorite-button [item]="item"></stapps-favorite-button>
</ion-item>
</ng-template>

View File

@@ -1,20 +1,21 @@
/*
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {CdkVirtualScrollViewport} from '@angular/cdk/scrolling';
import {
Component,
ContentChild,
EventEmitter,
HostListener,
Input,
@@ -23,11 +24,16 @@ import {
OnInit,
Output,
SimpleChanges,
TemplateRef,
ViewChild,
} from '@angular/core';
import {SCThings} from '@openstapps/core';
import {BehaviorSubject, Observable, Subscription} from 'rxjs';
export interface DataListContext<T> {
$implicit: T;
}
/**
* Shows the list of items
*/
@@ -47,6 +53,10 @@ export class DataListComponent implements OnChanges, OnInit, OnDestroy {
*/
@Input() items?: SCThings[];
@ContentChild(TemplateRef) listItemTemplateRef: TemplateRef<
DataListContext<SCThings>
>;
/**
* Stream of SCThings for virtual scroll to consume
*/

View File

@@ -6,12 +6,16 @@
(scrolledIndexChange)="scrolled($event)"
[style.display]="items && items.length ? 'block' : 'none'"
>
<ng-content select="[header]"></ng-content>
<ion-list>
<stapps-data-list-item
*cdkVirtualFor="let item of items; trackBy: identifyItem"
[item]="item"
[hideThumbnail]="singleType"
></stapps-data-list-item>
<ng-container *cdkVirtualFor="let item of items; trackBy: identifyItem">
<ng-container
*ngTemplateOutlet="
listItemTemplateRef || defaultListItem;
context: {$implicit: item}
"
></ng-container>
</ng-container>
</ion-list>
</cdk-virtual-scroll-viewport>
</ng-container>
@@ -28,3 +32,10 @@
*ngFor="let skeleton of [].constructor(skeletonItems)"
></stapps-skeleton-list-item>
</ion-list>
<ng-template let-item #defaultListItem>
<stapps-data-list-item
[item]="item"
[hideThumbnail]="singleType"
></stapps-data-list-item>
</ng-template>

View File

@@ -1,22 +1,30 @@
/*
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licens for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {
Component,
ContentChild,
Input,
OnDestroy,
OnInit,
TemplateRef,
} from '@angular/core';
import {SCThings} from '@openstapps/core';
import {Subscription} from 'rxjs';
import {Router} from '@angular/router';
import {DataRoutingService} from '../data-routing.service';
import {DataListContext} from './data-list.component';
/**
* Shows the list of items
@@ -30,18 +38,24 @@ export class SimpleDataListComponent implements OnInit, OnDestroy {
/**
* All SCThings to display
*/
@Input() items?: SCThings[];
@Input() items?: Promise<SCThings[] | undefined>;
/**
* Indicates whether or not the list is to display SCThings of a single type
*/
@Input() singleType = false;
@Input() autoRouting = true;
/**
* List header
*/
@Input() listHeader?: string;
@ContentChild(TemplateRef) listItemTemplateRef: TemplateRef<
DataListContext<SCThings>
>;
/**
* Items that display the skeleton list
*/
@@ -58,6 +72,7 @@ export class SimpleDataListComponent implements OnInit, OnDestroy {
) {}
ngOnInit(): void {
if (!this.autoRouting) return;
this.subscriptions.push(
this.dataRoutingService.itemSelectListener().subscribe(item => {
void this.router.navigate(['data-detail', item.uid]);

View File

@@ -1,11 +1,14 @@
<ng-container *ngIf="items | async as items; else loading">
<ion-list>
<ng-container *ngIf="!listHeader; else header"></ng-container>
<stapps-data-list-item
*ngFor="let item of items"
[item]="item"
[hideThumbnail]="singleType"
></stapps-data-list-item>
<ng-container *ngFor="let item of items">
<ng-container
*ngTemplateOutlet="
listItemTemplateRef || defaultListItem;
context: {$implicit: item}
"
></ng-container>
</ng-container>
</ion-list>
</ng-container>
<ng-template #loading>
@@ -26,3 +29,9 @@
</ion-text>
</ion-list-header>
</ng-template>
<ng-template let-item #defaultListItem>
<stapps-data-list-item
[item]="item"
[hideThumbnail]="singleType"
></stapps-data-list-item>
</ng-template>