mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-20 08:33:11 +00:00
feat: revamp dashboard mensa section
This commit is contained in:
committed by
Rainer Killinger
parent
1318cbca7f
commit
33a74d96ae
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -49,6 +49,7 @@
|
||||
|
||||
ion-content {
|
||||
--background: var(--ion-color-light);
|
||||
--padding-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.schedule {
|
||||
@@ -140,75 +141,3 @@ ion-content {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: var(--spacing-md);
|
||||
|
||||
&.section-extended {
|
||||
padding-right: 0;
|
||||
|
||||
ion-icon[name='edit'] {
|
||||
margin-right: var(--spacing-md);
|
||||
}
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
padding-top: var(--spacing-lg);
|
||||
}
|
||||
|
||||
& > ion-label:first-child {
|
||||
font-family: var(--headline-font-family);
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semi-bold);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: var(--spacing-md);
|
||||
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: revert;
|
||||
justify-content: space-between;
|
||||
|
||||
ion-icon {
|
||||
color: var(--ion-color-medium-shade);
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
background-color: var(--ion-color-primary-contrast);
|
||||
border-radius: var(--border-radius-default);
|
||||
padding: var(--spacing-lg);
|
||||
width: 28%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
ion-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
}
|
||||
|
||||
ion-searchbar {
|
||||
padding: 0;
|
||||
--background: var(--ion-color-primary-contrast);
|
||||
|
||||
::ng-deep .searchbar-input-container {
|
||||
height: 100%;
|
||||
|
||||
input {
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
|
||||
ion-icon {
|
||||
left: auto;
|
||||
right: var(--spacing-lg);
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -34,6 +34,7 @@ import {FavoritesSectionComponent} from './sections/favorites-section/favorites-
|
||||
import {ThingTranslateModule} from '../../translation/thing-translate.module';
|
||||
import {UtilModule} from '../../util/util.module';
|
||||
import {IonIconModule} from '../../util/ion-icon/ion-icon.module';
|
||||
import {NewsModule} from '../news/news.module';
|
||||
|
||||
const catalogRoutes: Routes = [
|
||||
{
|
||||
@@ -69,6 +70,7 @@ const catalogRoutes: Routes = [
|
||||
SwiperModule,
|
||||
ThingTranslateModule.forChild(),
|
||||
UtilModule,
|
||||
NewsModule,
|
||||
],
|
||||
providers: [SettingsProvider, TranslatePipe],
|
||||
exports: [EditModalComponent],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 StApps
|
||||
~ Copyright (C) 2023 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,16 +12,46 @@
|
||||
~ You should have received a copy of the GNU General Public License along with
|
||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<a *ngIf="item; else titleTemplate" [routerLink]="['/data-detail', item.uid]">
|
||||
<ng-container *ngTemplateOutlet="titleTemplate"></ng-container>
|
||||
</a>
|
||||
|
||||
<ion-label class="section-headline"
|
||||
>{{ title }}
|
||||
<ion-icon
|
||||
size="25"
|
||||
class="icon-margin-right"
|
||||
*ngIf="isEditable"
|
||||
(click)="onEditClick()"
|
||||
name="edit_square"
|
||||
></ion-icon>
|
||||
<ion-icon size="25" *ngIf="customIcon" (click)="onEditClick()" [name]="customIcon"></ion-icon>
|
||||
</ion-label>
|
||||
<ng-content></ng-content>
|
||||
<ng-template #titleTemplate>
|
||||
<ion-label class="section-headline">{{ title }} </ion-label>
|
||||
<ng-content select="[slot=subtitle]"></ng-content>
|
||||
</ng-template>
|
||||
</ion-col>
|
||||
|
||||
<ng-container *ngIf="swiper">
|
||||
<ion-col size="auto" class="swiper-button">
|
||||
<ion-button fill="clear" color="medium" (click)="slidePrev()" [disabled]="false">
|
||||
<ion-icon size="24" slot="icon-only" name="chevron_left"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
<ion-col size="auto" class="swiper-button">
|
||||
<ion-button fill="clear" color="medium" (click)="slideNext()" [disabled]="false">
|
||||
<ion-icon size="24" slot="icon-only" name="chevron_right"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
</ng-container>
|
||||
|
||||
<ion-col size="auto" *ngIf="isEditable">
|
||||
<ion-button fill="clear" color="medium" (click)="onEditClick()">
|
||||
<ion-icon size="24" slot="icon-only" name="edit_square"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
<ion-col size="auto" *ngIf="customIcon">
|
||||
<ion-button fill="clear" color="medium" (click)="onEditClick()">
|
||||
<ion-icon slot="icon-only" size="24" [name]="customIcon"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col #content>
|
||||
<ng-content></ng-content>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
@@ -1,58 +1,67 @@
|
||||
/*!
|
||||
* 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.
|
||||
* Copyright (C) 2023 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 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/>.
|
||||
* 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 '../../../../theme/util/mixins';
|
||||
|
||||
a {
|
||||
display: contents;
|
||||
color: unset;
|
||||
text-decoration: unset;
|
||||
}
|
||||
|
||||
ion-grid {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ion-label {
|
||||
font-family: var(--headline-font-family);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
&:only-child {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
ion-grid {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ion-col {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ion-button::part(native) {
|
||||
padding-inline: var(--spacing-sm);
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
.swiper-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm);
|
||||
--swiper-scroll-padding: var(--spacing-md);
|
||||
--swiper-gap: var(--spacing-sm);
|
||||
|
||||
@include ion-md-up {
|
||||
padding: var(--spacing-lg) var(--spacing-xxl) var(--spacing-sm);
|
||||
}
|
||||
|
||||
&.is-editable ::ng-deep {
|
||||
.swiper-button-prev {
|
||||
right: 65px;
|
||||
}
|
||||
|
||||
.swiper-button-next {
|
||||
right: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-extended {
|
||||
padding-right: 0;
|
||||
.icon-margin-right {
|
||||
margin-right: var(--spacing-md);
|
||||
}
|
||||
}
|
||||
|
||||
& > ion-label:first-child {
|
||||
font-family: var(--headline-font-family);
|
||||
font-weight: var(--font-weight-bold);
|
||||
|
||||
ion-icon {
|
||||
color: var(--ion-color-medium-shade);
|
||||
position: relative;
|
||||
margin-block: auto;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover ::ng-deep stapps-icon {
|
||||
--fill: 1;
|
||||
}
|
||||
}
|
||||
--swiper-scroll-padding: var(--spacing-xxl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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,7 +12,18 @@
|
||||
* 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, EventEmitter, HostBinding, Input, OnInit, Output} from '@angular/core';
|
||||
import {
|
||||
AfterContentInit,
|
||||
Component,
|
||||
EventEmitter,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import {SCThings} from '@openstapps/core';
|
||||
|
||||
/**
|
||||
* Shows a horizontal list of action chips
|
||||
@@ -22,7 +33,7 @@ import {Component, EventEmitter, HostBinding, Input, OnInit, Output} from '@angu
|
||||
templateUrl: 'section.component.html',
|
||||
styleUrls: ['section.component.scss'],
|
||||
})
|
||||
export class SectionComponent implements OnInit {
|
||||
export class SectionComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
@HostBinding('class.is-extended') isExtendedClass = false;
|
||||
|
||||
@HostBinding('class.is-editable') isEditableClass = false;
|
||||
@@ -35,18 +46,61 @@ export class SectionComponent implements OnInit {
|
||||
|
||||
@Input() customIcon?: string = undefined;
|
||||
|
||||
@Input() item?: SCThings;
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
||||
@Output() onEdit = new EventEmitter<void>();
|
||||
|
||||
mutationObserver: MutationObserver;
|
||||
|
||||
swiper?: HTMLElement;
|
||||
|
||||
constructor(readonly viewContainerRef: ViewContainerRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.isExtendedClass = this.isSectionExtended;
|
||||
this.isEditableClass = this.isEditable;
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.mutationObserver = new MutationObserver(() => {
|
||||
const simpleSwiper = this.viewContainerRef.element.nativeElement.querySelector('simple-swiper');
|
||||
if (!simpleSwiper) return;
|
||||
|
||||
this.swiper = simpleSwiper;
|
||||
});
|
||||
this.mutationObserver.observe(this.viewContainerRef.element.nativeElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
}
|
||||
|
||||
slideNext() {
|
||||
if (this.swiper) {
|
||||
this.swiper.scrollBy({
|
||||
left: this.swiper.offsetWidth,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
slidePrev() {
|
||||
if (this.swiper) {
|
||||
this.swiper.scrollBy({
|
||||
left: -this.swiper.offsetWidth,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action when edit is clicked
|
||||
*/
|
||||
onEditClick() {
|
||||
this.onEdit.emit();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.mutationObserver.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 StApps
|
||||
~ Copyright (C) 2023 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.
|
||||
@@ -18,23 +18,22 @@
|
||||
[isEditable]="true"
|
||||
(onEdit)="onSectionEdit()"
|
||||
>
|
||||
<div *ngIf="(items | async)?.length" class="container">
|
||||
<div *ngFor="let item of items | async" class="card clickable" (click)="notifySelect(item)">
|
||||
<ion-thumbnail class="ion-margin-end">
|
||||
<ion-icon color="dark" [attr.name]="item.type | dataIcon"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
{{ 'name' | thingTranslate: item }}
|
||||
</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="!(items | async)?.length">
|
||||
<div class="card">
|
||||
<ion-label>
|
||||
<simple-swiper *ngIf="(items | async)?.length; else noItems">
|
||||
<stapps-data-list-item
|
||||
*ngFor="let item of items | async"
|
||||
[hideThumbnail]="true"
|
||||
[favoriteButton]="false"
|
||||
[item]="item"
|
||||
appearance="square"
|
||||
></stapps-data-list-item>
|
||||
</simple-swiper>
|
||||
<ng-template #noItems>
|
||||
<ion-item class="nothing-selected" lines="none">
|
||||
<ion-label class="ion-text-wrap">
|
||||
{{ 'dashboard.favorites.no_favorite_prefix' | translate }}
|
||||
<a (click)="onSectionEdit()">{{ 'dashboard.favorites.no_favorite_link' | translate }}</a>
|
||||
{{ 'dashboard.favorites.no_favorite_suffix' | translate }}
|
||||
</ion-label>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ion-item>
|
||||
</ng-template>
|
||||
</stapps-section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -13,39 +13,11 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: var(--spacing-sm);
|
||||
--size: 60px;
|
||||
|
||||
& > * {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
min-height: var(--size);
|
||||
margin-bottom: var(--spacing-sm);
|
||||
|
||||
ion-thumbnail {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
transform: translate(10%, 20%);
|
||||
margin: 0 auto var(--spacing-xs);
|
||||
--size: 60px;
|
||||
|
||||
ion-icon {
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
margin: auto;
|
||||
--ion-color-base: var(--ion-color-light-icon) !important;
|
||||
}
|
||||
}
|
||||
ion-label {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
.nothing-selected::part(native) {
|
||||
background: none;
|
||||
color: var(--ion-color-medium-shade);
|
||||
}
|
||||
|
||||
simple-swiper {
|
||||
--swiper-slide-width: 180px;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
<swiper
|
||||
[config]="sliderOptions"
|
||||
[navigation]="true"
|
||||
class="mensa-swiper card-swiper"
|
||||
*ngIf="dishes && dishes.length > 0"
|
||||
>
|
||||
<ng-template swiperSlide *ngFor="let dish of dishes">
|
||||
<a [routerLink]="'/data-detail/' + dish.uid" class="card">
|
||||
<ion-label>{{ 'name' | thingTranslate: dish }}</ion-label>
|
||||
</a>
|
||||
</ng-template>
|
||||
</swiper>
|
||||
<div class="card" *ngIf="!dishes || dishes.length === 0">
|
||||
<ion-label>
|
||||
{{ 'dashboard.canteens.no_dishes_available' | translate }}
|
||||
</ion-label>
|
||||
</div>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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/>.
|
||||
-->
|
||||
|
||||
<ng-container *ngIf="dishes | async as dishes; else loading">
|
||||
<simple-swiper *ngIf="dishes.length > 0" @fade>
|
||||
<stapps-data-list-item
|
||||
*ngFor="let dish of dishes"
|
||||
[hideThumbnail]="true"
|
||||
[favoriteButton]="false"
|
||||
[item]="dish"
|
||||
appearance="square"
|
||||
></stapps-data-list-item>
|
||||
</simple-swiper>
|
||||
<ion-item class="no-dishes" *ngIf="!dishes || dishes.length === 0" lines="none">
|
||||
<ion-label>
|
||||
{{ 'dashboard.canteens.no_dishes_available' | translate }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ng-template #loading>
|
||||
<div class="placeholder"></div>
|
||||
</ng-template>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* Copyright (C) 2023 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/>.
|
||||
*/
|
||||
|
||||
.no-dishes::part(native) {
|
||||
background: none;
|
||||
color: var(--ion-color-medium-shade);
|
||||
}
|
||||
|
||||
simple-swiper {
|
||||
--swiper-slide-width: 180px;
|
||||
}
|
||||
|
||||
.placeholder,
|
||||
stapps-data-list-item {
|
||||
height: 140px;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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,9 +12,11 @@
|
||||
* 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, OnChanges, SimpleChanges} from '@angular/core';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {SCDish, SCPlace, SCThings} from '@openstapps/core';
|
||||
import {PlaceMensaService} from '../../../data/types/place/special/mensa/place-mensa-service';
|
||||
import {animate, style, transition, trigger} from '@angular/animations';
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* Shows a section with meals of the chosen mensa
|
||||
@@ -22,50 +24,29 @@ import {PlaceMensaService} from '../../../data/types/place/special/mensa/place-m
|
||||
@Component({
|
||||
selector: 'stapps-mensa-section-content',
|
||||
templateUrl: 'mensa-section-content.component.html',
|
||||
styleUrls: ['mensa-section.component.scss'],
|
||||
styleUrls: ['mensa-section-content.component.scss'],
|
||||
animations: [
|
||||
trigger('fade', [
|
||||
transition(':enter', [style({opacity: '0'}), animate('500ms ease', style({opacity: '1'}))]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class MensaSectionContentComponent implements OnInit, OnChanges {
|
||||
/**
|
||||
* Slider options
|
||||
*/
|
||||
sliderOptions = {
|
||||
spaceBetween: 12,
|
||||
freeMode: {
|
||||
enabled: true,
|
||||
sticky: true,
|
||||
},
|
||||
width: 120,
|
||||
};
|
||||
|
||||
export class MensaSectionContentComponent {
|
||||
/**
|
||||
* Map of dishes for each day
|
||||
*/
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
dishes: SCDish[] | null = [];
|
||||
dishes: Promise<SCDish[]>;
|
||||
|
||||
@Input() items: SCThings[];
|
||||
@Input() set item(value: SCThings) {
|
||||
if (!value) return;
|
||||
this.dishes = this.mensaService.getAllDishes(value as SCPlace, 1).then(it => {
|
||||
const closestDayWithDishes = Object.keys(it)
|
||||
.filter(key => it[key].length > 0)
|
||||
.find(key => moment(key).isSame(moment(), 'day'));
|
||||
return closestDayWithDishes ? it[closestDayWithDishes] : [];
|
||||
});
|
||||
}
|
||||
|
||||
constructor(private readonly mensaService: PlaceMensaService) {}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.getDishes();
|
||||
}
|
||||
|
||||
async ngOnChanges(changes: SimpleChanges) {
|
||||
if (typeof changes.items !== 'undefined') {
|
||||
await this.getDishes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request dishes
|
||||
*/
|
||||
async getDishes() {
|
||||
if (this.items) {
|
||||
for (const item of this.items) {
|
||||
const dishes = await this.mensaService.getAllDishes(item as SCPlace, 1);
|
||||
this.dishes?.push(...dishes[Object.keys(dishes)[0]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 StApps
|
||||
~ Copyright (C) 2023 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.
|
||||
@@ -13,21 +13,34 @@
|
||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<stapps-section
|
||||
[title]="'dashboard.canteens.title' | translate"
|
||||
[isEditable]="true"
|
||||
(onEdit)="onSectionEdit()"
|
||||
>
|
||||
<ng-container *ngIf="(items | async)?.length">
|
||||
<stapps-mensa-section-content [items]="items | async"></stapps-mensa-section-content>
|
||||
<ng-container *ngIf="items | async as items">
|
||||
<ng-container *ngIf="items.length !== 0; else nothingSelected">
|
||||
<ng-container *ngFor="let item of items">
|
||||
<stapps-section
|
||||
@fade
|
||||
[item]="item"
|
||||
[title]="'name' | thingTranslate: item"
|
||||
[isEditable]="true"
|
||||
(onEdit)="onSectionEdit()"
|
||||
>
|
||||
<stapps-opening-hours slot="subtitle" [openingHours]="item.openingHours"></stapps-opening-hours>
|
||||
<stapps-mensa-section-content [item]="item"></stapps-mensa-section-content>
|
||||
</stapps-section>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!(items | async)?.length">
|
||||
<div class="card">
|
||||
<ion-label>
|
||||
{{ 'dashboard.canteens.no_favorite_prefix' | translate }}
|
||||
<a (click)="onSectionEdit()">{{ 'dashboard.canteens.no_favorite_link' | translate }}</a>
|
||||
{{ 'dashboard.canteens.no_favorite_suffix' | translate }}
|
||||
</ion-label>
|
||||
</div>
|
||||
</ng-container>
|
||||
</stapps-section>
|
||||
<ng-template #nothingSelected>
|
||||
<stapps-section
|
||||
[title]="'dashboard.canteens.title' | translate"
|
||||
[isEditable]="true"
|
||||
(onEdit)="onSectionEdit()"
|
||||
>
|
||||
<ion-item class="nothing-selected" lines="none">
|
||||
<ion-label class="ion-text-wrap">
|
||||
{{ 'dashboard.canteens.no_favorite_prefix' | translate }}
|
||||
<a (click)="onSectionEdit()">{{ 'dashboard.canteens.no_favorite_link' | translate }}</a>
|
||||
{{ 'dashboard.canteens.no_favorite_suffix' | translate }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</stapps-section>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* Copyright (C) 2023 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/>.
|
||||
*/
|
||||
|
||||
stapps-mensa-section-content {
|
||||
display: block;
|
||||
margin-block-start: var(--spacing-md);
|
||||
}
|
||||
|
||||
.nothing-selected::part(native) {
|
||||
background: none;
|
||||
color: var(--ion-color-medium-shade);
|
||||
}
|
||||
|
||||
:host {
|
||||
transition: height 150ms ease;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {SettingsProvider} from '../../../settings/settings.provider';
|
||||
import {FavoritesService} from '../../../favorites/favorites.service';
|
||||
import {ContextMenuService} from '../../../menu/context/context-menu.service';
|
||||
import {ConfigProvider} from '../../../config/config.provider';
|
||||
import {animate, style, transition, trigger} from '@angular/animations';
|
||||
|
||||
/**
|
||||
* Shows a section with meals of the chosen mensa
|
||||
@@ -36,6 +37,9 @@ import {ConfigProvider} from '../../../config/config.provider';
|
||||
selector: 'stapps-mensa-section',
|
||||
templateUrl: 'mensa-section.component.html',
|
||||
styleUrls: ['mensa-section.component.scss'],
|
||||
animations: [
|
||||
trigger('fade', [transition(':enter', [style({opacity: '0'}), animate(250, style({opacity: '1'}))])]),
|
||||
],
|
||||
})
|
||||
export class MensaSectionComponent extends FoodDataListComponent {
|
||||
sub: Subscription;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
~ Copyright (C) 2022 StApps
|
||||
~ Copyright (C) 2023 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.
|
||||
@@ -20,26 +20,13 @@
|
||||
class="is-editable"
|
||||
(onEdit)="onMoreNewsClicked()"
|
||||
>
|
||||
<swiper
|
||||
[config]="sliderOptions"
|
||||
slidesPerView="auto"
|
||||
[navigation]="true"
|
||||
*ngIf="news.length > 0"
|
||||
class="news-swiper card-swiper"
|
||||
>
|
||||
<ng-template swiperSlide *ngFor="let newsItem of news">
|
||||
<a [routerLink]="['/data-detail', newsItem.uid]" class="card">
|
||||
<ion-img [src]="newsItem.image"></ion-img>
|
||||
<ion-label>{{ newsItem.name }}</ion-label>
|
||||
</a>
|
||||
</ng-template>
|
||||
<ng-template swiperSlide>
|
||||
<a [routerLink]="['/news']" class="card more-news">
|
||||
<ion-label>{{ 'dashboard.news.moreNews' | translate | titlecase }}</ion-label>
|
||||
<ion-thumbnail class="ion-margin-end">
|
||||
<ion-icon color="dark" name="read_more" size="128"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
</a>
|
||||
</ng-template>
|
||||
</swiper>
|
||||
<simple-swiper class="news-swiper card-swiper" *ngIf="news" @fade>
|
||||
<stapps-news-item *ngFor="let newsItem of news" [item]="newsItem"> </stapps-news-item>
|
||||
<ion-item [routerLink]="['/news']" class="more-news" lines="none">
|
||||
<ion-label>{{ 'dashboard.news.moreNews' | translate | titlecase }}</ion-label>
|
||||
<ion-thumbnail class="ion-margin-end">
|
||||
<ion-icon color="medium" name="read_more" size="150"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
</ion-item>
|
||||
</simple-swiper>
|
||||
</stapps-section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -13,50 +13,33 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.news-swiper.swiper {
|
||||
.swiper-slide {
|
||||
padding: 0;
|
||||
simple-swiper {
|
||||
--swiper-slide-width: 256px;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 0;
|
||||
.more-news {
|
||||
width: 128px;
|
||||
font-size: var(--font-size-xl);
|
||||
--color: var(--ion-color-medium-tint);
|
||||
|
||||
ion-img {
|
||||
border-radius: var(--border-radius-default) var(--border-radius-default) 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
&::part(native) {
|
||||
height: 100%;
|
||||
background: none;
|
||||
border-radius: var(--border-radius-default);
|
||||
}
|
||||
|
||||
ion-label {
|
||||
margin: var(--spacing-lg);
|
||||
text-align: left;
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-bold);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
ion-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.more-news {
|
||||
ion-label {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
margin: 0 auto var(--spacing-xs);
|
||||
--size: 160px;
|
||||
|
||||
ion-icon {
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
margin: auto;
|
||||
--ion-color-base: var(--ion-color-light-icon) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ion-thumbnail {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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,7 +12,7 @@
|
||||
* 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, OnInit, ViewEncapsulation} from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {Router} from '@angular/router';
|
||||
import {NewsPageComponent} from '../../../news/page/news-page.component';
|
||||
import {NewsProvider} from '../../../news/news.provider';
|
||||
@@ -20,6 +20,7 @@ import {SettingsProvider} from '../../../settings/settings.provider';
|
||||
import {newsFilterSettingsFieldsMapping, NewsFilterSettingsNames} from '../../../news/news-filter-settings';
|
||||
import {DataProvider} from '../../../data/data.provider';
|
||||
import {SCSearchValueFilter} from '@openstapps/core';
|
||||
import {animate, style, transition, trigger} from '@angular/animations';
|
||||
|
||||
/**
|
||||
* Shows a section with news
|
||||
@@ -28,26 +29,16 @@ import {SCSearchValueFilter} from '@openstapps/core';
|
||||
selector: 'stapps-news-section',
|
||||
templateUrl: 'news-section.component.html',
|
||||
styleUrls: ['news-section.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
animations: [
|
||||
trigger('fade', [
|
||||
transition(':enter', [
|
||||
style({opacity: '0', transform: 'translateX(100px)'}),
|
||||
animate('250ms ease', style({opacity: '1', transform: 'translateX(0)'})),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class NewsSectionComponent extends NewsPageComponent implements OnInit {
|
||||
/**
|
||||
* Slider options
|
||||
*/
|
||||
sliderOptions = {
|
||||
spaceBetween: 12,
|
||||
freeMode: {
|
||||
enabled: true,
|
||||
sticky: true,
|
||||
},
|
||||
width: 300,
|
||||
breakpoints: {
|
||||
768: {
|
||||
width: 380,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pageSize = 5;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<!--
|
||||
~ 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.
|
||||
~ Copyright (C) 2023 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 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/>.
|
||||
~ You should have received a copy of the GNU General Public License along with
|
||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<div>
|
||||
@@ -24,7 +24,7 @@
|
||||
{{ 'data.detail.offers.sold_out' | translate }}
|
||||
</h2>
|
||||
</ion-text>
|
||||
<p *ngIf="_offers[0].inPlace && !soldOut">
|
||||
<p *ngIf="_offers[0].inPlace && !soldOut" class="place">
|
||||
<ion-icon name="pin_drop"></ion-icon>{{ _offers[0].inPlace.name
|
||||
}}<span *ngIf="_offers.length > 1">...</span>
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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,7 +12,7 @@
|
||||
* 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, ContentChild, Input, TemplateRef} from '@angular/core';
|
||||
import {Component, ContentChild, HostBinding, Input, TemplateRef} from '@angular/core';
|
||||
import {SCThings} from '@openstapps/core';
|
||||
import {DataRoutingService} from '../data-routing.service';
|
||||
import {DataListContext} from './data-list.component';
|
||||
@@ -40,8 +40,14 @@ export class DataListItemComponent {
|
||||
|
||||
@Input() lines = 'inset';
|
||||
|
||||
@Input() appearance: 'normal' | 'square' = 'normal';
|
||||
|
||||
@ContentChild(TemplateRef) contentTemplateRef: TemplateRef<DataListContext<SCThings>>;
|
||||
|
||||
@HostBinding('class.square') get square() {
|
||||
return this.appearance === 'square';
|
||||
}
|
||||
|
||||
constructor(private readonly dataRoutingService: DataRoutingService) {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,7 +112,11 @@
|
||||
></stapps-long-inline-text>
|
||||
</p>
|
||||
</div>
|
||||
<stapps-action-chip-list slot="end" [item]="item"></stapps-action-chip-list>
|
||||
<stapps-action-chip-list
|
||||
*ngIf="appearance !== 'square'"
|
||||
slot="end"
|
||||
[item]="item"
|
||||
></stapps-action-chip-list>
|
||||
</div>
|
||||
</ion-label>
|
||||
</ng-template>
|
||||
|
||||
@@ -41,3 +41,43 @@ ion-item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:host.square ::ng-deep {
|
||||
ion-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ion-row {
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
ion-col {
|
||||
flex-grow: 0;
|
||||
flex-basis: min-content;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: -webkit-box;
|
||||
white-space: break-spaces;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-sub {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// fix for Safari
|
||||
stapps-offers-in-list {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
stapps-offers-in-list .place {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* Copyright (C) 2022 StApps
|
||||
* Copyright (C) 2023 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.
|
||||
@@ -33,6 +33,10 @@ ion-card::part(native) {
|
||||
}
|
||||
|
||||
ion-card-title {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
font-size: var(--font-size-xl);
|
||||
--color: var(--ion-color-dark-contrast);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright (C) 2023 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 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/>.
|
||||
* 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 {CommonModule} from '@angular/common';
|
||||
import {NgModule} from '@angular/core';
|
||||
@@ -57,5 +57,6 @@ const newsRoutes: Routes = [{path: 'news', component: NewsPageComponent}];
|
||||
UtilModule,
|
||||
],
|
||||
providers: [SettingsProvider],
|
||||
exports: [NewsItemComponent],
|
||||
})
|
||||
export class NewsModule {}
|
||||
|
||||
Reference in New Issue
Block a user