feat: add not found screen

This commit is contained in:
Wieland Schöbl
2021-01-19 15:17:47 +01:00
parent 0641ab12c8
commit e3d9ef40cc
11 changed files with 23964 additions and 59 deletions

View File

@@ -16,6 +16,7 @@ import {CommonModule} from '@angular/common';
import {HttpClientModule} from '@angular/common/http';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {Network} from '@ionic-native/network/ngx';
import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core';
import {MarkdownModule} from 'ngx-markdown';
@@ -135,6 +136,7 @@ import {VideoListItem} from './types/video/video-list-item.component';
providers: [
DataProvider,
DataFacetsProvider,
Network,
StAppsWebHttpClient,
],
})

View File

@@ -12,43 +12,53 @@
* 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, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Network} from '@ionic-native/network/ngx';
import {IonRefresher} from '@ionic/angular';
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import {SCLanguageCode, SCThing, SCUuid} from '@openstapps/core';
import {SCLanguageCode, SCSaveableThing, SCThings, SCUuid} from '@openstapps/core';
import {DataProvider, DataScope} from '../data.provider';
/**
* TODO
* A Component to display an SCThing detailed
*/
@Component({
selector: 'stapps-data-detail',
styleUrls: ['data-detail.scss'],
templateUrl: 'data-detail.html',
})
export class DataDetailComponent {
export class DataDetailComponent implements OnInit {
/**
* TODO
* The associated item
*
* undefined if not loaded, null when unavailable
*/
dataProvider: DataProvider;
item?: SCThings | null = undefined;
/**
* TODO
*/
item: SCThing;
/**
* TODO
* The language of the item
*/
language: SCLanguageCode;
/**
*
* @param route TODO
* @param dataProvider TODO
* @param translateService TODO
* Type guard for SCSavableThing
*/
constructor(private readonly route: ActivatedRoute, dataProvider: DataProvider, translateService: TranslateService) {
this.dataProvider = dataProvider;
static isSCSavableThing(thing: SCThings | SCSaveableThing<SCThings>): thing is SCSaveableThing<SCThings> {
return typeof (thing as SCSaveableThing<SCThings>).data !== 'undefined';
}
/**
*
* @param route the route the page was accessed from
* @param dataProvider the data provider
* @param network the network provider
* @param translateService the translation service
*/
constructor(private readonly route: ActivatedRoute,
private readonly dataProvider: DataProvider,
private readonly network: Network,
translateService: TranslateService) {
this.language = translateService.currentLang as SCLanguageCode;
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
this.language = event.lang as SCLanguageCode;
@@ -60,19 +70,27 @@ export class DataDetailComponent {
*
* @param uid Unique identifier of a thing
*/
async getItem(uid: SCUuid): Promise<void> {
await this.dataProvider.get(uid, DataScope.Remote)
.then((data) => {
this.item = data;
});
async getItem(uid: SCUuid) {
try {
const item = await this.dataProvider.get(uid, DataScope.Remote);
this.item = DataDetailComponent.isSCSavableThing(item) ? item.data : item;
} catch (_) {
this.item = null;
}
}
/**
* TODO
* Check if we have internet
*/
isDisconnected(): boolean {
return this.network.type === this.network.Connection.NONE;
}
/**
* Initialize
*/
// tslint:disable-next-line:prefer-function-over-method
ngOnInit() {
this.getItem(this.route.snapshot.paramMap.get('uid') || '');
void this.getItem(this.route.snapshot.paramMap.get('uid') ?? '');
}
/**
@@ -81,7 +99,7 @@ export class DataDetailComponent {
* @param refresher Refresher component that triggers the update
*/
async refresh(refresher: IonRefresher) {
await this.getItem(this.item.uid);
refresher.complete();
await this.getItem(this.item?.uid ?? this.route.snapshot.paramMap.get('uid') ?? '');
await refresher.complete();
}
}

View File

@@ -13,12 +13,32 @@
refreshingText="{{'data.REFRESHING' | translate}}">
</ion-refresher-content>
</ion-refresher>
<ng-container *ngIf="!item">
<stapps-skeleton-list-item></stapps-skeleton-list-item>
<stapps-skeleton-simple-card></stapps-skeleton-simple-card>
</ng-container>
<ng-container *ngIf="item">
<stapps-data-list-item [item]="item"></stapps-data-list-item>
<stapps-data-detail-content [item]="item"></stapps-data-detail-content>
</ng-container>
<div [ngSwitch]="true">
<ng-container *ngSwitchCase='!item && isDisconnected()'>
<div class='notFoundContainer'>
<ion-icon name='no-connection'>
</ion-icon>
<ion-label>
{{ 'data.detail.COULD_NOT_CONNECT' | translate }}
</ion-label>
</div>
</ng-container>
<ng-container *ngSwitchCase="item === null">
<div class="notFoundContainer">
<ion-icon name="broken-link">
</ion-icon>
<ion-label>
{{ 'data.detail.NOT_FOUND' | translate }}
</ion-label>
</div>
</ng-container>
<ng-container *ngSwitchCase="!item && item !== null">
<stapps-skeleton-list-item></stapps-skeleton-list-item>
<stapps-skeleton-simple-card></stapps-skeleton-simple-card>
</ng-container>
<ng-container *ngSwitchDefault>
<stapps-data-list-item [item]="item"></stapps-data-list-item>
<stapps-data-detail-content [item]="item"></stapps-data-detail-content>
</ng-container>
</div>
</ion-content>

View File

@@ -11,3 +11,20 @@
}
}
}
.notFoundContainer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 50vh;
ion-icon {
font-size: 64px;
}
ion-label {
font-size: x-large;
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
<g transform="matrix(1,0,0,1,-600,0)">
<rect id="Artboard2" x="600" y="0" width="500" height="500" style="fill:none;"/>
<g id="Artboard21" serif:id="Artboard2">
<g transform="matrix(0.448766,-0.893649,0.893649,0.448766,469.063,342.066)">
<path d="M172.406,353.651L144,352C91.336,352 48,308.664 48,256C48,203.336 91.336,160 144,160L208,160" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
<g transform="matrix(0.998306,-0.0581818,0.0581818,0.998306,578.658,-36.4373)">
<path d="M304,160L368,160C420.664,160 464,203.336 464,256C464,308.664 420.664,352 368,352L344.108,351.046" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
<g transform="matrix(0.835467,-0.54954,0.54954,0.835467,485.54,168.526)">
<path d="M313.991,245.837L367.731,276.894" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
<g transform="matrix(0.835467,-0.54954,-0.54954,-0.835467,642.903,689.819)">
<path d="M308.423,242.423L368.097,273.154" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
<g transform="matrix(0.835467,-0.54954,-0.54954,-0.835467,611.794,572.634)">
<path d="M343.592,241L328.795,281" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
<g transform="matrix(0.835467,-0.54954,0.54954,0.835467,397.953,88.4905)">
<path d="M343.592,241L328.795,281" style="fill:none;fill-rule:nonzero;stroke:currentColor;stroke-width:36px;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-miterlimit:10;">
<path d="M74.216,154.839C57.516,184.784 48,219.281 48,256C48,370.87 141.13,464 256,464C293.515,464 328.711,454.067 359.102,436.688" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M437.104,358.371C454.225,328.147 464,293.215 464,256C464,141.13 370.87,48 256,48C218.643,48 183.586,57.849 153.283,75.093" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M367.788,281.198C368.369,272.938 368.67,264.529 368.67,256C368.67,141.13 314.07,48 256,48C229.248,48 203.232,67.766 182.951,100.317" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M144.485,227.192C143.725,236.608 143.33,246.225 143.33,256C143.33,370.87 197.93,464 256,464C282.923,464 309.099,443.982 329.435,411.06" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M238.57,160.066C244.322,160.466 250.135,160.67 256,160.67C308.29,160.67 356.43,144.48 394.67,117.33M276.68,352.181C269.87,351.618 262.972,351.33 256,351.33C203.71,351.33 155.57,367.52 117.33,394.67" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;stroke-linejoin:round;stroke-miterlimit:4;"/>
<path d="M256,48L256,176.215M464,256L332.18,256" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M256,335.311L256,464" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M180.214,256L48,256" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
<path d="M448,448L64,64" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:32px;"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -3,7 +3,9 @@
"REFRESH_ACTION": "Aktualisieren",
"REFRESHING": "Aktualisierung läuft...",
"detail": {
"TITLE": "Detailansicht"
"TITLE": "Detailansicht",
"NOT_FOUND": "Nicht gefunden",
"COULD_NOT_CONNECT": "Verbindung fehlgeschlagen"
},
"types": {
"dish": {

View File

@@ -3,7 +3,9 @@
"REFRESH_ACTION": "Refresh",
"REFRESHING": "Refreshing...",
"detail": {
"TITLE": "Details"
"TITLE": "Details",
"NOT_FOUND": "Not found",
"COULD_NOT_CONNECT": "Couldn't connect"
},
"types": {
"dish": {