feat: revamp dashboard mensa section

This commit is contained in:
Thea Schöbl
2023-02-27 14:44:20 +00:00
committed by Rainer Killinger
parent 1318cbca7f
commit 33a74d96ae
27 changed files with 578 additions and 385 deletions

View File

@@ -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;
}
}
}

View File

@@ -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],

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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]]);
}
}
}
}

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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;
/**

View File

@@ -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>

View File

@@ -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) {}
/**

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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 {}