style: improve design and add logo

- show data icons in thumbnails in data list items
- add app logo
- fix various visibility issues
This commit is contained in:
Jovan Krunić
2021-03-23 15:59:58 +00:00
parent 8b0978c7eb
commit 1a8660590f
31 changed files with 233 additions and 121 deletions

View File

@@ -0,0 +1,66 @@
/*
* 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.
*
* 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.
*
* 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 {Pipe, PipeTransform} from '@angular/core';
import {SCThingType} from '@openstapps/core';
/**
* Converts the data type text into the icon name
*/
@Pipe({
name: 'dataIcon',
})
export class DataIconPipe implements PipeTransform {
/**
* Mapping from data types to ionic icons to show
*/
typeIconMap: {[type in SCThingType] : string; };
constructor() {
this.typeIconMap = {
'academic event': 'school',
'article': 'document',
'book': 'book',
'building': 'location',
'catalog': 'folder',
'contact point': 'call',
'course of studies': 'school',
'date series': 'calendar',
'dish': 'restaurant',
'favorite': 'heart',
'floor': 'caret-up-circle',
'message': 'newspaper',
'organization': 'briefcase',
'person': 'person',
'point of interest': 'location',
'room': 'location',
'semester': 'school',
'setting': 'settings',
'sport course': 'football',
'study module': 'school',
'ticket': 'ticket',
'todo': 'checkbox',
'tour': 'help-buoy',
'video': 'videocam',
'diff': 'swap-horizontal',
};
}
/**
* Provide the icon name from the data type
*/
transform(type: SCThingType): string {
return this.typeIconMap[type];
}
}

View File

@@ -25,6 +25,7 @@ import {ThingTranslateModule} from '../../translation/thing-translate.module';
import {MenuModule} from '../menu/menu.module';
import {StorageModule} from '../storage/storage.module';
import {DataFacetsProvider} from './data-facets.provider';
import { DataIconPipe } from './data-icon.pipe';
import {DataRoutingModule} from './data-routing.module';
import {DataProvider} from './data.provider';
import {DataDetailContentComponent} from './detail/data-detail-content.component';
@@ -114,6 +115,7 @@ import {VideoListItem} from './types/video/video-list-item.component';
SkeletonSegment,
VideoDetailContentComponent,
VideoListItem,
DataIconPipe,
],
entryComponents: [
DataListComponent,

View File

@@ -4,7 +4,7 @@
<ion-back-button></ion-back-button>
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title class="ion-text-center">{{'data.detail.TITLE' | translate}}</ion-title>
<ion-title>{{'data.detail.TITLE' | translate}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
@@ -37,7 +37,21 @@
<stapps-skeleton-simple-card></stapps-skeleton-simple-card>
</ng-container>
<ng-container *ngSwitchDefault>
<stapps-data-list-item [item]="item"></stapps-data-list-item>
<ion-item class="ion-text-wrap" lines="inset">
<ion-thumbnail slot="start">
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
</ion-thumbnail>
<ion-grid *ngSwitchDefault>
<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-data-detail-content [item]="item"></stapps-data-detail-content>
</ng-container>
</div>

View File

@@ -3,7 +3,7 @@
<ion-card-content>
<div *ngFor="let offer of offers">
<p *ngIf="offer.inPlace">
<ion-icon name="pin"></ion-icon>
<ion-icon name="location"></ion-icon>
<a [routerLink]="['/data-detail', offer.inPlace.uid]">{{offer.inPlace.name}}</a>,&nbsp;
<span *ngIf="offer.availabilityStarts">
<ion-icon name="calendar"></ion-icon> {{offer.availabilityStarts | amDateFormat:'ll'}}

View File

@@ -1,6 +1,6 @@
<div>
<h2>{{offers[0].prices.default | currency:'EUR':'symbol':undefined:'de'}}</h2>
<p *ngIf="offers[0].inPlace">
<ion-icon name="pin"></ion-icon> {{offers[0].inPlace.name}} <span *ngIf="offers.length > 1">...</span>
<ion-icon name="location"></ion-icon> {{offers[0].inPlace.name}} <span *ngIf="offers.length > 1">...</span>
</p>
</div>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018, 2019 StApps
* 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.
@@ -12,37 +12,20 @@
* 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, OnInit} from '@angular/core';
import {Component, Input} from '@angular/core';
import {SCThings} from '@openstapps/core';
/**
* TODO
* Shows data items in lists such es search result
*/
@Component({
selector: 'stapps-data-list-item',
styleUrls: ['data-list-item.scss'],
templateUrl: 'data-list-item.html',
})
export class DataListItem implements OnInit {
export class DataListItem {
/**
* TODO
* An item to show
*/
@Input() item: SCThings;
/**
* TODO
*/
constructor() {
// noop
// this.item is not available yet
}
/**
* TODO
*/
// tslint:disable-next-line:prefer-function-over-method
ngOnInit() {
// noop
// this.item is available now - the template is loaded and compiled
}
}

View File

@@ -1,10 +1,9 @@
<ion-item class="ion-text-wrap" button="true" lines="inset" [routerLink]="['/data-detail', item.uid]">
<ion-thumbnail slot="start">
<img class="stapps-{{item.type}}-thumbnail" src="{{item.image}}" onError="this.src='../../assets/imgs/logo.png';" alt="{{item.name}}" />
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
</ion-thumbnail>
<ion-label [ngSwitch]="true">
<div>
<stapps-article-list-item [item]="item" *ngSwitchCase="item.type === 'article'"></stapps-article-list-item>
<stapps-catalog-list-item [item]="item" *ngSwitchCase="item.type === 'catalog'"></stapps-catalog-list-item>
<stapps-date-series-list-item [item]="item" *ngSwitchCase="item.type === 'date series'"></stapps-date-series-list-item>
<stapps-dish-list-item [item]="item" *ngSwitchCase="item.type === 'dish'"></stapps-dish-list-item>
@@ -23,11 +22,13 @@
<ion-grid *ngSwitchDefault>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">
<stapps-long-inline-text [text]="item.description" [size]="80"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">
<stapps-long-inline-text [text]="item.description" [size]="110"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -1,5 +0,0 @@
::ng-deep {
h2.name {
font-weight: bold;
}
}

View File

@@ -3,7 +3,7 @@
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.keywords">
<stapps-long-inline-text [text]="item.keywords.join(', ')" [size]="80"></stapps-long-inline-text>
<stapps-long-inline-text [text]="item.keywords.join(', ')" [size]="110"></stapps-long-inline-text>
</p>
<ion-note>
{{item.type}}

View File

@@ -1,11 +1,13 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">
<stapps-long-inline-text [text]="item.description" [size]="80"></stapps-long-inline-text>
</p>
<p *ngIf="item.academicTerm">{{item.academicTerm.name}}</p>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">
<stapps-long-inline-text [text]="item.description" [size]="110"></stapps-long-inline-text>
</p>
<p *ngIf="item.academicTerm">{{item.academicTerm.name}}</p>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -3,7 +3,7 @@
Place
</ion-card-header>
<ion-card-content>
<ion-icon name="pin"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
<ion-icon name="location"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
<stapps-address-detail *ngIf="item.inPlace.address" [address]="item.inPlace.address"></stapps-address-detail>
</ion-card-content>
</ion-card>

View File

@@ -1,15 +1,17 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p>
<ion-icon name="calendar"></ion-icon>
<span>
{{item.frequency}}, {{item.dates[0] | amDateFormat:'dddd'}}
<span>({{item.dates[0] | amDateFormat:'ll'}} - {{item.dates[item.dates.length - 1] | amDateFormat:'ll'}})</span>
</span>
</p>
<ion-note *ngIf="item.event.type === 'academic event'">{{item.event.categories.join(', ')}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p>
<ion-icon name="calendar"></ion-icon>
<span>
{{item.frequency}}, {{item.dates[0] | amDateFormat:'dddd'}}
<span>({{item.dates[0] | amDateFormat:'ll'}} - {{item.dates[item.dates.length - 1] | amDateFormat:'ll'}})</span>
</span>
</p>
<ion-note *ngIf="item.event.type === 'academic event'">{{item.event.categories.join(', ')}}</ion-note>
</div>
</ion-col>
<ion-col width-20 text-right>
<stapps-offers-in-list *ngIf="item.offers" [offers]="item.offers"></stapps-offers-in-list>

View File

@@ -1,12 +1,16 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{'name' | thingTranslate: item}}</h2>
<p>{{'description' | thingTranslate: item}}</p>
<p>{{'categories' | thingTranslate: item | join: ', '}}</p>
<div class="ion-text-wrap">
<h2 class="name">{{'name' | thingTranslate: item}}</h2>
<p>{{'description' | thingTranslate: item}}</p>
<p>{{'categories' | thingTranslate: item | join: ', '}}</p>
</div>
</ion-col>
<ion-col width-20 text-right>
<stapps-offers-in-list *ngIf="item.offers" [offers]="item.offers"></stapps-offers-in-list>
<ion-col width-10 text-right>
<div class="ion-text-end">
<stapps-offers-in-list *ngIf="item.offers" [offers]="item.offers"></stapps-offers-in-list>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -1,10 +1,12 @@
<ion-grid>
<ion-row *ngIf="item.type === 'academic event'">
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<p *ngIf="item.academicTerms">{{item.academicTerms[0].name}}</p>
<ion-note>{{item.type}} ({{item.categories.join(', ')}})</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<p *ngIf="item.academicTerms">{{item.academicTerms[0].name}}</p>
<ion-note>{{item.type}} ({{item.categories.join(', ')}})</ion-note>
</div>
</ion-col>
</ion-row>
<ion-row *ngIf="item.type === 'sport course'">

View File

@@ -1,11 +1,13 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}: {{item.data.name}}</h2>
<p *ngIf="item.data.description">
<stapps-long-inline-text [text]="item.data.description" [size]="80"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}} ({{item.data.type}})</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}: {{item.data.name}}</h2>
<p *ngIf="item.data.description">
<stapps-long-inline-text [text]="item.data.description" [size]="110"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}} ({{item.data.type}})</ion-note>
</div>
</ion-col>
<ion-col width-20 text-right>
<stapps-origin-in-list [origin]="item.origin"></stapps-origin-in-list>

View File

@@ -1,11 +1,13 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.messageBody">
<stapps-long-inline-text [text]="item.messageBody" [size]="80"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.messageBody">
<stapps-long-inline-text [text]="item.messageBody" [size]="110"></stapps-long-inline-text>
</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -3,7 +3,7 @@
Place
</ion-card-header>
<ion-card-content>
<ion-icon name="pin"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
<ion-icon name="location"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
<stapps-address-detail *ngIf="item.inPlace.address" [address]="item.inPlace.address"></stapps-address-detail>
</ion-card-content>
</ion-card>

View File

@@ -1,13 +1,15 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
<ion-col width-20 text-right *ngIf="item.inPlace">
<span *ngIf="item.inPlace">
<ion-icon name="pin"></ion-icon> {{item.inPlace.name}}
<ion-icon name="location"></ion-icon> {{item.inPlace.name}}
</span>
</ion-col>
</ion-row>

View File

@@ -1,13 +1,15 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}} <span *ngIf="item.honorificPrefix">, {{item.honorificPrefix}}</span></h2>
<p *ngIf="item.telephone || item.email"><span *ngIf="item.telephone">
<ion-icon name="call"></ion-icon>&nbsp;{{item.telephone}}&nbsp;
</span><span *ngIf="item.email">
<ion-icon name="mail"></ion-icon>&nbsp;{{item.email}}
</span></p>
<p *ngIf="item.jobTitles">{{item.jobTitles.join(', ') | slice:0:50}}<span *ngIf="item.jobTitles.join(', ').length > 51">...</span></p>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}} <span *ngIf="item.honorificPrefix">, {{item.honorificPrefix}}</span></h2>
<p *ngIf="item.telephone || item.email"><span *ngIf="item.telephone">
<ion-icon name="call"></ion-icon>&nbsp;{{item.telephone}}&nbsp;
</span><span *ngIf="item.email">
<ion-icon name="mail"></ion-icon>&nbsp;{{item.email}}
</span></p>
<p *ngIf="item.jobTitles">{{item.jobTitles.join(', ') | slice:0:50}}<span *ngIf="item.jobTitles.join(', ').length > 51">...</span></p>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -9,8 +9,8 @@
Building:
</ion-card-header>
<ion-card-content>
<ion-icon name="pin"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
<stapps-address-detail *ngIf="item.inPlace.address" [address]="item.inPlace.address"></stapps-address-detail>
<ion-icon name="location"></ion-icon> <a [routerLink]="['/data-detail', item.inPlace.uid]">{{item.inPlace.name}}</a>
</ion-card-content>
</ion-card>
<stapps-address-detail *ngIf="item.inPlace && item.inPlace.address" [address]="item.inPlace.address"></stapps-address-detail>
</ng-container>

View File

@@ -1,13 +1,15 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description">{{item.description}}</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
<ion-col width-20 text-right *ngIf="item.type !== 'building'">
<span *ngIf="item.inPlace">
<ion-icon name="pin"></ion-icon> {{item.inPlace.name}}
<ion-icon name="location"></ion-icon> {{item.inPlace.name}}
</span>
</ion-col>
</ion-row>

View File

@@ -1,12 +1,14 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p>
<ion-icon name="calendar"></ion-icon>
<span>{{item.startDate | amDateFormat: 'll'}} - {{item.endDate | amDateFormat:'ll'}}</span>
</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p>
<ion-icon name="calendar"></ion-icon>
<span>{{item.startDate | amDateFormat: 'll'}} - {{item.endDate | amDateFormat:'ll'}}</span>
</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -1,10 +1,12 @@
<ion-grid>
<ion-row>
<ion-col>
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description"><stapps-long-inline-text [text]="item.description" [size]="80"></stapps-long-inline-text></p>
<p *ngIf="item.duration">Duration: {{item.duration | amDuration:'seconds'}}</p>
<ion-note>{{item.type}}</ion-note>
<div class="ion-text-wrap">
<h2 class="name">{{item.name}}</h2>
<p *ngIf="item.description"><stapps-long-inline-text [text]="item.description" [size]="110"></stapps-long-inline-text></p>
<p *ngIf="item.duration">Duration: {{item.duration | amDuration:'seconds'}}</p>
<ion-note>{{item.type}}</ion-note>
</div>
</ion-col>
</ion-row>
</ion-grid>

View File

@@ -5,7 +5,10 @@
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>StApps</ion-title>
<ion-title>
<img src="assets/imgs/logo.png" />
<span class="text">StApps</span>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
@@ -25,7 +28,7 @@
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-content>
</ion-menu>
<ion-router-outlet id="main"></ion-router-outlet>
</ion-split-pane>

View File

@@ -1,3 +1,11 @@
stapps-navigation {
ion-title {
span.text {
vertical-align: middle;
font-size: 20px;
padding-left: 5px;
}
img {
height: 25px;
vertical-align: middle
}
}

View File

@@ -2,14 +2,14 @@
<span *ngIf="item.url; else imageNoUrl">
<a href="{{item.url}}">
<ion-thumbnail>
<img src="{{item.image}}" onerror="this.style.display = 'none'" />
<img src="{{item.image}}" onerror="this.style.display = 'none'; this.nextSibling.style.display='block'" />
<ion-icon name="newspaper-outline"></ion-icon>
</ion-thumbnail>
</a>
</span>
<ng-template #imageNoUrl>
<ion-thumbnail>
<img src="{{item.image}}" onerror="this.style.display = 'none'" />
<img src="{{item.image}}" onerror="this.style.display = 'none'; this.nextSibling.style.display='block'" />
<ion-icon name="newspaper-outline"></ion-icon>
</ion-thumbnail>
</ng-template>

View File

@@ -7,24 +7,18 @@ ion-card-header a {
padding-left: 4px;
}
}
ion-card ion-thumbnail img {
width: 100%;
z-index: 1;
position: absolute;
}
ion-card ion-thumbnail {
position: relative;
background: var(--placeholder-gray);
width: 100%;
min-height: 400px;
align-items: center;
margin: 0;
ion-icon {
position: absolute;
width: 100%;
height: 100%;
color: white;
height: auto;
img {
display: block;
}
ion-icon {
width: 100%;
height: 250px;
color: white;
display: none;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -10,3 +10,24 @@
@import "~@ionic/angular/css/text-transformation.css";
@import "~@ionic/angular/css/flex-utils.css";
/* StApps */
ion-item {
h2.name {
font-weight: bold;
}
ion-thumbnail {
background: var(--placeholder-gray);
--size: 36px;
display: flex;
align-items: center;
padding: 10px;
margin: 0;
ion-icon {
width: 100%;
height: 100%;
color: white;
display: block;
}
}
}

View File

@@ -77,4 +77,5 @@
/** StApps **/
--placeholder-gray: #F1F0ED;
/** Change the colors of the toolbar and the toolbar text here **/
}