mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-03-14 10:42:40 +00:00
feat: apply new layout overhaul
This commit is contained in:
committed by
Rainer Killinger
parent
f16e5394cc
commit
7bbdba5c0b
@@ -1,5 +1,10 @@
|
||||
:host ::ng-deep ion-skeleton-text {
|
||||
width: 50px;
|
||||
:host {
|
||||
display: block;
|
||||
padding: var(--spacing-sm);
|
||||
|
||||
::ng-deep ion-skeleton-text {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.stack-children {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
[attr.color]="active ? 'primary' : 'medium'"
|
||||
(click)="emitToggle(value)"
|
||||
>
|
||||
<ion-icon name="checkmark-circle" *ngIf="active"></ion-icon>
|
||||
<ion-icon name="circle-check" *ngIf="active"></ion-icon>
|
||||
<ion-label>{{ displayValue }}</ion-label>
|
||||
</ion-chip>
|
||||
|
||||
@@ -30,33 +30,33 @@ export class DataIconPipe implements PipeTransform {
|
||||
constructor() {
|
||||
this.typeIconMap = {
|
||||
'academic event': 'school',
|
||||
'assessment': 'document-text',
|
||||
'article': 'document',
|
||||
'assessment': 'file-text',
|
||||
'article': 'file',
|
||||
'book': 'book',
|
||||
'building': 'location',
|
||||
'catalog': 'folder',
|
||||
'contact point': 'call',
|
||||
'contact point': 'phone',
|
||||
'course of study': 'school',
|
||||
'date series': 'calendar',
|
||||
'dish': 'restaurant',
|
||||
'dish': 'tools-kitchen-2',
|
||||
'favorite': 'heart',
|
||||
'floor': 'caret-up-circle',
|
||||
'message': 'newspaper',
|
||||
'floor': 'arrow-up-circle',
|
||||
'message': 'news',
|
||||
'organization': 'briefcase',
|
||||
'periodical': 'newspaper',
|
||||
'person': 'person',
|
||||
'periodical': 'news',
|
||||
'person': 'user',
|
||||
'point of interest': 'location',
|
||||
'publication event': 'megaphone',
|
||||
'publication event': 'speakerphone',
|
||||
'room': 'location',
|
||||
'semester': 'school',
|
||||
'setting': 'settings',
|
||||
'sport course': 'football',
|
||||
'sport course': 'ball-football',
|
||||
'study module': 'school',
|
||||
'ticket': 'ticket',
|
||||
'todo': 'checkbox',
|
||||
'tour': 'help-buoy',
|
||||
'video': 'videocam',
|
||||
'diff': 'swap-horizontal',
|
||||
'tour': 'lifebuoy',
|
||||
'video': 'video',
|
||||
'diff': 'arrows-left-right',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import {SearchPageComponent} from './list/search-page.component';
|
||||
|
||||
const dataRoutes: Routes = [
|
||||
{path: 'search', component: SearchPageComponent},
|
||||
{path: 'search/:term', component: SearchPageComponent},
|
||||
{path: 'data-detail/:uid', component: DataDetailComponent},
|
||||
{path: 'canteen', component: FoodDataListComponent},
|
||||
];
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import {Component, Input, TemplateRef} from '@angular/core';
|
||||
import {SCThings} from '@openstapps/core';
|
||||
import {DataListContext} from '../list/data-list.component';
|
||||
import {ModalController} from '@ionic/angular';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -31,4 +32,10 @@ export class DataDetailContentComponent {
|
||||
@Input() item: SCThings;
|
||||
|
||||
@Input() contentTemplateRef?: TemplateRef<DataListContext<SCThings>>;
|
||||
|
||||
@Input() openAsModal = false;
|
||||
|
||||
@Input() showModalHeader = false;
|
||||
|
||||
constructor(readonly modalController: ModalController) {}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
<stapps-title-card [item]="item"> </stapps-title-card>
|
||||
<ion-header *ngIf="showModalHeader" translucent>
|
||||
<ion-toolbar color="primary" mode="ios">
|
||||
<ion-title>{{ 'name' | thingTranslate: item }}</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button (click)="modalController.dismiss()">{{
|
||||
'app.ui.CLOSE' | translate
|
||||
}}</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<stapps-title-card *ngIf="!showModalHeader" [item]="item"> </stapps-title-card>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
contentTemplateRef || defaultContent;
|
||||
@@ -60,6 +71,7 @@
|
||||
></stapps-place-detail-content>
|
||||
<stapps-place-detail-content
|
||||
[item]="$any(item)"
|
||||
[openAsModal]="openAsModal"
|
||||
*ngSwitchCase="'room'"
|
||||
></stapps-place-detail-content>
|
||||
<stapps-semester-detail-content
|
||||
@@ -73,10 +85,7 @@
|
||||
<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-icon color="dark" [attr.name]="item.type | dataIcon"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
|
||||
@@ -31,4 +31,22 @@
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
> div {
|
||||
padding: 0 var(--spacing-md);
|
||||
background-color: var(--ion-color-light);
|
||||
|
||||
& > * {
|
||||
display: block;
|
||||
border-radius: var(--border-radius-default);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
top: calc((var(--header-spacing-bottom) - var(--spacing-xl)) * -1);
|
||||
background-color: var(--ion-color-primary-contrast);
|
||||
|
||||
& > ion-thumbnail {
|
||||
background: var(--ion-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ export class DataDetailComponent implements ViewWillEnter {
|
||||
|
||||
this.isDisconnected = new Promise(async resolve => {
|
||||
const isConnected = (await Network.getStatus()).connected;
|
||||
resolve(isConnected);
|
||||
resolve(!isConnected);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ export class DataDetailComponent implements ViewWillEnter {
|
||||
.get(uid)
|
||||
.pipe(take(1))
|
||||
.subscribe(item => {
|
||||
if (typeof item !== undefined) {
|
||||
if (typeof item !== 'undefined') {
|
||||
this.item = item;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -14,18 +14,12 @@
|
||||
-->
|
||||
|
||||
<ion-header *ngIf="defaultHeader">
|
||||
<ion-toolbar color="primary">
|
||||
<ion-toolbar color="primary" mode="ios">
|
||||
<ion-buttons slot="start" *ngIf="!isModal">
|
||||
<ion-back-button
|
||||
[defaultHref]="
|
||||
item?.superCatalog
|
||||
? ['/data-detail', item.superCatalog.uid]
|
||||
: item?.catalogs && item?.catalogs.length === 1
|
||||
? ['/data-detail', item.catalogs[0].uid]
|
||||
: undefined
|
||||
"
|
||||
[defaultHref]="'..'"
|
||||
[text]="'back' | translate | titlecase"
|
||||
></ion-back-button>
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{ 'data.detail.TITLE' | translate }}</ion-title>
|
||||
<ion-buttons [slot]="isModal ? 'start' : 'primary'">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
}}</ng-container>
|
||||
</h1>
|
||||
</ion-text>
|
||||
<div *ngIf="item.description">
|
||||
<div *ngIf="item.description" class="description">
|
||||
<br />
|
||||
<div
|
||||
class="text-accordion"
|
||||
|
||||
@@ -19,3 +19,22 @@
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
|
||||
ion-card {
|
||||
border-radius: 0;
|
||||
--background: var(--ion-color-primary);
|
||||
padding: 0 var(--spacing-md);
|
||||
|
||||
ion-card-content {
|
||||
padding: var(--spacing-sm) 0 var(--header-spacing-bottom);
|
||||
|
||||
h1 {
|
||||
color: var(--ion-color-primary-contrast);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
.description * {
|
||||
color: var(--ion-color-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ enum AccordionButtonState {
|
||||
@Component({
|
||||
selector: 'stapps-title-card',
|
||||
templateUrl: './title-card.component.html',
|
||||
styleUrls: ['./title-card.component.css'],
|
||||
styleUrls: ['./title-card.component.scss'],
|
||||
})
|
||||
export class TitleCardComponent implements OnInit, OnChanges {
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<ion-item
|
||||
class="ion-text-wrap"
|
||||
class="ion-text-wrap ion-margin"
|
||||
button="true"
|
||||
lines="inset"
|
||||
detail="false"
|
||||
(click)="notifySelect()"
|
||||
>
|
||||
<div class="item-height-placeholder"></div>
|
||||
<ion-thumbnail slot="start" *ngIf="!hideThumbnail" class="ion-margin-end">
|
||||
<ion-icon color="medium" [attr.name]="item.type | dataIcon"></ion-icon>
|
||||
<ion-icon color="dark" [attr.name]="item.type | dataIcon"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
<ng-container *ngIf="contentTemplateRef; else defaultContent">
|
||||
<ion-label class="ion-text-wrap" [ngSwitch]="true">
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
:host ::ng-deep {
|
||||
ion-item {
|
||||
--border-color: transparent;
|
||||
border-radius: var(--border-radius-default);
|
||||
overflow: hidden;
|
||||
--inner-padding-end: 0;
|
||||
|
||||
ion-thumbnail {
|
||||
--ion-margin: var(--spacing-xs);
|
||||
}
|
||||
|
||||
ion-label {
|
||||
width: 100%;
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
cdk-virtual-scroll-viewport {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
ion-list {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep {
|
||||
|
||||
@@ -20,8 +20,13 @@ import {SearchPageComponent} from './search-page.component';
|
||||
*/
|
||||
@Component({
|
||||
templateUrl: 'search-page.html',
|
||||
styleUrls: ['../../data/list/search-page.scss'],
|
||||
})
|
||||
export class FoodDataListComponent extends SearchPageComponent {
|
||||
title = 'canteens.title';
|
||||
|
||||
showNavigation = false;
|
||||
|
||||
/**
|
||||
* Sets the forced filter to present only places for eating/drinking
|
||||
*/
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {Component, Input, OnInit, OnDestroy} from '@angular/core';
|
||||
import {Router} from '@angular/router';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {Keyboard} from '@capacitor/keyboard';
|
||||
import {AlertController} from '@ionic/angular';
|
||||
import {
|
||||
SCFacet,
|
||||
SCFeatureConfiguration,
|
||||
SCSearchFilter,
|
||||
SCSearchQuery,
|
||||
SCSearchSort,
|
||||
@@ -31,6 +32,7 @@ import {SettingsProvider} from '../../settings/settings.provider';
|
||||
import {DataRoutingService} from '../data-routing.service';
|
||||
import {DataProvider} from '../data.provider';
|
||||
import {PositionService} from '../../map/position.service';
|
||||
import {ConfigProvider} from '../../config/config.provider';
|
||||
|
||||
/**
|
||||
* SearchPageComponent queries things and shows list of things as search results and filter as context menu
|
||||
@@ -38,14 +40,24 @@ import {PositionService} from '../../map/position.service';
|
||||
@Component({
|
||||
selector: 'stapps-search-page',
|
||||
templateUrl: 'search-page.html',
|
||||
styleUrls: ['search-page.scss'],
|
||||
providers: [ContextMenuService],
|
||||
})
|
||||
export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
title = 'search.title';
|
||||
|
||||
isHebisAvailable = false;
|
||||
|
||||
/**
|
||||
* Signalizes that the data is being loaded
|
||||
*/
|
||||
loading = false;
|
||||
|
||||
/**
|
||||
* Display the navigation between default and library search
|
||||
*/
|
||||
@Input() showNavigation = true;
|
||||
|
||||
/**
|
||||
* Show default data (e.g. when there is user interaction)
|
||||
*/
|
||||
@@ -56,6 +68,11 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
@Input() showDrawer = true;
|
||||
|
||||
/**
|
||||
* Show "universal search" toolbar
|
||||
*/
|
||||
@Input() showTopToolbar = true;
|
||||
|
||||
/**
|
||||
* Api query filter
|
||||
*/
|
||||
@@ -131,7 +148,9 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
* @param logger An angular logger
|
||||
* @param dataRoutingService DataRoutingService
|
||||
* @param router Router
|
||||
* @param route ActivatedRoute
|
||||
* @param positionService PositionService
|
||||
* @param configProvider ConfigProvider
|
||||
*/
|
||||
constructor(
|
||||
protected readonly alertController: AlertController,
|
||||
@@ -141,7 +160,9 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
protected readonly logger: NGXLogger,
|
||||
protected dataRoutingService: DataRoutingService,
|
||||
protected router: Router,
|
||||
private readonly route: ActivatedRoute,
|
||||
protected positionService: PositionService,
|
||||
private readonly configProvider: ConfigProvider,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -314,10 +335,29 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
||||
),
|
||||
this.dataRoutingService.itemSelectListener().subscribe(item => {
|
||||
if (this.itemRouting) {
|
||||
void this.router.navigate(['data-detail', item.uid]);
|
||||
void this.router.navigate(['/data-detail', item.uid]);
|
||||
}
|
||||
}),
|
||||
);
|
||||
try {
|
||||
const features = this.configProvider.getValue(
|
||||
'features',
|
||||
) as SCFeatureConfiguration;
|
||||
this.isHebisAvailable = !!features.plugins?.['hebis-plugin']?.urlPath;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
async ionViewWillEnter() {
|
||||
const term = this.route.snapshot.paramMap.get('term') || undefined;
|
||||
if (term) {
|
||||
this.queryText = term;
|
||||
this.searchStringChanged(term);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -1,29 +1,51 @@
|
||||
<stapps-context contentId="data-list"></stapps-context>
|
||||
<ion-header>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-toolbar color="primary" mode="ios" *ngIf="showDrawer">
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
<ion-menu-button *ngIf="showDrawer"></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-buttons slot="end">
|
||||
<ion-menu-button menu="context" auto-hide="false">
|
||||
<ion-icon name="options"></ion-icon>
|
||||
</ion-menu-button>
|
||||
<ion-back-button
|
||||
[defaultHref]="'..'"
|
||||
[text]="'back' | translate | titlecase"
|
||||
></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>{{ title | translate }}</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-searchbar
|
||||
(ngModelChange)="searchStringChanged($event)"
|
||||
(keyup.enter)="hideKeyboard()"
|
||||
[(ngModel)]="queryText"
|
||||
placeholder="{{ 'search.search_bar.placeholder' | translate }}"
|
||||
showClearButton="always"
|
||||
placeholder="{{ 'search.search_bar.placeholder' | translate }}"
|
||||
mode="md"
|
||||
type="search"
|
||||
enterkeyhint="search"
|
||||
class="filterable"
|
||||
>
|
||||
<ion-menu-button menu="context" auto-hide="false">
|
||||
<ion-icon name="adjustments"></ion-icon>
|
||||
</ion-menu-button>
|
||||
</ion-searchbar>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar
|
||||
color="primary"
|
||||
class="category-tab"
|
||||
*ngIf="showNavigation && isHebisAvailable"
|
||||
>
|
||||
<ion-buttons class="ion-justify-content-between">
|
||||
<ion-button class="button-active" size="large">{{
|
||||
'search.type' | translate
|
||||
}}</ion-button>
|
||||
<ion-button
|
||||
[routerLink]="['/hebis-search/' + (queryText || '')]"
|
||||
fill="outline"
|
||||
size="large"
|
||||
>{{ 'hebisSearch.type' | translate }}
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-content class="content">
|
||||
<div
|
||||
[style.display]="!showDefaultData && !items && !loading ? 'block' : 'none'"
|
||||
>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ion-toolbar:first-of-type {
|
||||
padding: 0 var(--spacing-md) var(--spacing-xs);
|
||||
}
|
||||
|
||||
.category-tab {
|
||||
ion-buttons {
|
||||
gap: var(--spacing-md);
|
||||
|
||||
ion-button {
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-content {
|
||||
--background: var(--ion-color-light);
|
||||
}
|
||||
|
||||
.content > div {
|
||||
height: 100%;
|
||||
|
||||
ion-label.centeredMessageContainer {
|
||||
min-height: unset;
|
||||
height: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export class SimpleDataListComponent implements OnInit, OnDestroy {
|
||||
if (!this.autoRouting) return;
|
||||
this.subscriptions.push(
|
||||
this.dataRoutingService.itemSelectListener().subscribe(item => {
|
||||
void this.router.navigate(['data-detail', item.uid]);
|
||||
void this.router.navigate(['/data-detail', item.uid]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p *ngIf="item.keywords">
|
||||
<stapps-long-inline-text
|
||||
[text]="item.keywords.join(', ')"
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h2>
|
||||
{{ 'name' | thingTranslate: item }}
|
||||
</h2>
|
||||
<ion-label class="title">
|
||||
{{ 'name' | thingTranslate: item }}
|
||||
</ion-label>
|
||||
<ion-note *ngIf="item.academicTerm">{{
|
||||
item.academicTerm.name
|
||||
}}</ion-note>
|
||||
<p *ngIf="item.academicTerm" class="title-sub">
|
||||
{{ item.academicTerm.name }}
|
||||
</p>
|
||||
</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p>
|
||||
<ion-icon name="calendar"></ion-icon>
|
||||
<span *ngIf="item.dates[0] && item.dates[item.dates.length - 1]">
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<p class="ion-hide-sm-down">
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p class="title-sub ion-hide-sm-down">
|
||||
{{ 'description' | thingTranslate: item }}
|
||||
</p>
|
||||
<p>{{ 'categories' | thingTranslate: item | join: ', ' }}</p>
|
||||
|
||||
@@ -2,18 +2,22 @@
|
||||
<ion-row *ngIf="item.type === 'academic event'">
|
||||
<ion-col>
|
||||
<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-label class="title">{{ item.name }}</ion-label>
|
||||
<p *ngIf="item.description" class="title-sub">{{ item.description }}</p>
|
||||
<p *ngIf="item.academicTerms" class="title-sub">
|
||||
{{ 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'">
|
||||
<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-label class="title">{{ item.name }}</ion-label>
|
||||
<p *ngIf="item.description" class="title-sub">{{ item.description }}</p>
|
||||
<p *ngIf="item.academicTerms" class="title-sub">
|
||||
{{ item.academicTerms[0].name }}
|
||||
</p>
|
||||
<ion-note>{{ item.type }}</ion-note>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">
|
||||
<ion-label class="title">
|
||||
{{ 'name' | thingTranslate: item }}:
|
||||
{{ 'name' | thingTranslate: item.data }}
|
||||
</h2>
|
||||
<p *ngIf="item.data.description">
|
||||
</ion-label>
|
||||
<p *ngIf="item.data.description" class="title-sub">
|
||||
<stapps-long-inline-text
|
||||
[text]="'description' | thingTranslate: item.data"
|
||||
[size]="80"
|
||||
|
||||
@@ -35,7 +35,10 @@
|
||||
</ion-thumbnail>
|
||||
<stapps-simple-card
|
||||
*ngIf="item.datePublished"
|
||||
content="{{ item.datePublished | amCalendar | sentencecase }}"
|
||||
class="date-published"
|
||||
content="{{ 'news.publishedOn' | translate | titlecase }} {{
|
||||
item.datePublished | amCalendar | sentencecase
|
||||
}}"
|
||||
></stapps-simple-card>
|
||||
<stapps-simple-card content="{{ item.messageBody }}"></stapps-simple-card>
|
||||
<ion-card *ngIf="item.sameAs">
|
||||
@@ -44,7 +47,7 @@
|
||||
</ion-card-header>
|
||||
<ion-card-content>
|
||||
<a (click)="onLinkClick(item.sameAs)"
|
||||
>{{ item.name }}<ion-icon name="open-outline"></ion-icon>
|
||||
>{{ item.name }}<ion-icon name="external-link"></ion-icon>
|
||||
</a>
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
@@ -36,4 +36,10 @@
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.date-published {
|
||||
--ion-card-color: var(--ion-color-medium-shade);
|
||||
text-transform: uppercase;
|
||||
font-weight: var(--font-weight-semi-bold);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p *ngIf="item.messageBody">
|
||||
<stapps-long-inline-text
|
||||
[text]="item.messageBody"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<p *ngIf="item.description">
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p *ngIf="item.description" class="title-sub">
|
||||
{{ 'description' | thingTranslate: item }}
|
||||
</p>
|
||||
<ion-note>{{ 'type' | thingTranslate: item }}</ion-note>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">
|
||||
<ion-label class="title">
|
||||
{{ 'name' | thingTranslate: item }}
|
||||
<span *ngIf="item.honorificPrefix">, {{ item.honorificPrefix }}</span>
|
||||
</h2>
|
||||
</ion-label>
|
||||
<p *ngIf="item.telephone || item.email">
|
||||
<span *ngIf="item.telephone">
|
||||
<ion-icon name="call"></ion-icon> {{
|
||||
|
||||
@@ -38,6 +38,8 @@ export class PlaceDetailContentComponent implements OnInit {
|
||||
*/
|
||||
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
|
||||
|
||||
@Input() openAsModal = false;
|
||||
|
||||
/**
|
||||
* Does it have valid location or not (for showing in in a map widget)
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<stapps-place-mensa-detail-content
|
||||
[item]="item"
|
||||
[openAsModal]="openAsModal"
|
||||
*ngIf="isMensaThing(item)"
|
||||
></stapps-place-mensa-detail-content>
|
||||
<ng-container *ngIf="item.type !== 'floor'">
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<ion-label>{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<ng-container *ngIf="item.type !== 'floor'">
|
||||
<p>
|
||||
<ion-note *ngIf="item.openingHours">
|
||||
{{ item.openingHours | openingHours }}
|
||||
</ion-note>
|
||||
<p class="title-sub" *ngIf="item.openingHours">
|
||||
{{ item.openingHours | openingHours }}
|
||||
</p>
|
||||
<p>
|
||||
<ion-note
|
||||
|
||||
@@ -18,9 +18,10 @@ import moment, {Moment} from 'moment';
|
||||
import {AfterViewInit, Component, Input, OnDestroy} from '@angular/core';
|
||||
import {SCDish, SCISO8601Date, SCPlace} from '@openstapps/core';
|
||||
import {PlaceMensaService} from './place-mensa-service';
|
||||
import {DataRoutingService} from '../../../../data-routing.service';
|
||||
import {Router} from '@angular/router';
|
||||
import {Subscription} from 'rxjs';
|
||||
import {IonRouterOutlet} from '@ionic/angular';
|
||||
import {DataRoutingService} from '../../../../data-routing.service';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -48,6 +49,8 @@ export class PlaceMensaDetailComponent implements AfterViewInit, OnDestroy {
|
||||
*/
|
||||
@Input() item: SCPlace;
|
||||
|
||||
@Input() openAsModal = false;
|
||||
|
||||
/**
|
||||
* The currently selected day
|
||||
*/
|
||||
@@ -66,6 +69,7 @@ export class PlaceMensaDetailComponent implements AfterViewInit, OnDestroy {
|
||||
constructor(
|
||||
private readonly mensaService: PlaceMensaService,
|
||||
protected router: Router,
|
||||
readonly routerOutlet: IonRouterOutlet,
|
||||
private readonly dataRoutingService: DataRoutingService,
|
||||
) {
|
||||
this.startingDay = moment().startOf('day');
|
||||
@@ -84,11 +88,13 @@ export class PlaceMensaDetailComponent implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
this.selectedDay = Object.keys(result)[0];
|
||||
});
|
||||
this.subscriptions.push(
|
||||
this.dataRoutingService.itemSelectListener().subscribe(item => {
|
||||
void this.router.navigate(['data-detail', item.uid]);
|
||||
}),
|
||||
);
|
||||
if (!this.openAsModal) {
|
||||
this.subscriptions.push(
|
||||
this.dataRoutingService.itemSelectListener().subscribe(item => {
|
||||
void this.router.navigate(['/data-detail', item.uid]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,10 +16,27 @@
|
||||
<div [ngSwitch]="selectedDay">
|
||||
<div *ngFor="let date of dishes | keyvalue">
|
||||
<ion-list *ngSwitchCase="date.key">
|
||||
<stapps-data-list-item
|
||||
[item]="dish"
|
||||
*ngFor="let dish of date.value"
|
||||
></stapps-data-list-item>
|
||||
<ng-container *ngFor="let dish of date.value; index as i">
|
||||
<stapps-data-list-item
|
||||
[item]="dish"
|
||||
[hideThumbnail]="true"
|
||||
[id]="'show-dish-in-modal-' + i"
|
||||
></stapps-data-list-item>
|
||||
<ion-modal
|
||||
*ngIf="openAsModal"
|
||||
[trigger]="'show-dish-in-modal-' + i"
|
||||
swipe-to-close="true"
|
||||
[presentingElement]="routerOutlet.nativeEl"
|
||||
class="modal-large"
|
||||
>
|
||||
<ng-template>
|
||||
<stapps-data-detail-content
|
||||
[item]="dish"
|
||||
[showModalHeader]="true"
|
||||
></stapps-data-detail-content>
|
||||
</ng-template>
|
||||
</ion-modal>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<p>
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p class="title-sub">
|
||||
<ion-icon name="calendar"></ion-icon>
|
||||
<span
|
||||
>{{ item.startDate | dateFormat }} -
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<div class="ion-text-wrap">
|
||||
<h2 class="name">{{ 'name' | thingTranslate: item }}</h2>
|
||||
<p *ngIf="item.description">
|
||||
<ion-label class="title">{{ 'name' | thingTranslate: item }}</ion-label>
|
||||
<p *ngIf="item.description" class="title-sub">
|
||||
<stapps-long-inline-text
|
||||
[text]="'description' | thingTranslate: item"
|
||||
[size]="80"
|
||||
|
||||
Reference in New Issue
Block a user