refactor: use expandable title card for all data details

Closes #150
This commit is contained in:
Jovan Krunić
2021-10-26 10:54:01 +02:00
committed by Rainer Killinger
parent 88684f068a
commit e29a68bb03
10 changed files with 170 additions and 127 deletions

View File

@@ -82,6 +82,7 @@ import {CoordinatedSearchProvider} from './coordinated-search.provider';
import {Geolocation} from '@ionic-native/geolocation/ngx';
import {FavoriteButtonComponent} from './elements/favorite-button.component';
import {SimpleDataListComponent} from './list/simple-data-list.component';
import {TitleCardComponent} from './elements/title-card.component';
/**
* Module for handling data
@@ -137,6 +138,7 @@ import {SimpleDataListComponent} from './list/simple-data-list.component';
VideoDetailContentComponent,
VideoListItemComponent,
SimpleDataListComponent,
TitleCardComponent,
],
entryComponents: [DataListComponent, SimpleDataListComponent],
imports: [

View File

@@ -1,3 +1,4 @@
<stapps-title-card [item]="item"> </stapps-title-card>
<div [ngSwitch]="item.type">
<stapps-article-detail-content
[item]="item"

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
.text-accordion {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}

View File

@@ -0,0 +1,41 @@
<!--
~ Copyright (C) 2021 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
~
~ This program is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
~ more details.
~
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<ion-card>
<ion-card-content>
<ion-text color="dark">
<h1>
{{ 'name' | thingTranslate: item }}
</h1>
</ion-text>
<div *ngIf="item.description">
<br />
<div
class="text-accordion"
[style.-webkit-line-clamp]="descriptionLinesToDisplay"
#accordionTextArea
>
{{ 'description' | thingTranslate: item }}
</div>
</div>
</ion-card-content>
</ion-card>
<ion-button
expand="full"
fill="clear"
*ngIf="item.description && buttonShown"
(click)="toggleDescriptionAccordion()"
>
<ion-icon [name]="buttonState" size="large"></ion-icon>
</ion-button>

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
Component,
ElementRef,
HostListener,
Input,
OnChanges,
OnInit,
ViewChild,
} from '@angular/core';
import {SCThings} from '@openstapps/core';
enum AccordionButtonState {
collapsed = 'chevron-down',
expanded = 'chevron-up',
}
@Component({
selector: 'stapps-title-card',
templateUrl: './title-card.component.html',
styleUrls: ['./title-card.component.css'],
})
export class TitleCardComponent implements OnInit, OnChanges {
/**
* The item whose title (and description) to display
*/
@Input() item: SCThings;
@ViewChild('accordionTextArea') accordionTextArea: ElementRef;
buttonState = AccordionButtonState.collapsed;
buttonShown = true;
descriptionLinesShown: number;
descriptionLinesTotal: number;
descriptionPreviewLines = 3;
descriptionLinesToDisplay = 0;
ngOnInit(): void {
if (this.item.description) {
this.descriptionLinesToDisplay = this.descriptionPreviewLines;
setTimeout(() => this.checkTextElipsis(), 0);
}
}
ngOnChanges() {
this.checkTextElipsis();
}
@HostListener('window:resize', ['$event'])
checkTextElipsis() {
if (typeof this.accordionTextArea === 'undefined') {
return;
}
const element = this.accordionTextArea.nativeElement as HTMLElement;
const lineHeight = Number.parseInt(
getComputedStyle(element).getPropertyValue('line-height'),
);
this.descriptionLinesTotal = element?.scrollHeight / lineHeight;
this.descriptionLinesShown = element?.offsetHeight / lineHeight;
if (this.buttonState === AccordionButtonState.expanded) {
this.descriptionLinesToDisplay = this.descriptionLinesTotal;
}
const isElipsed = element?.offsetHeight < element?.scrollHeight;
this.buttonShown =
(isElipsed && this.buttonState === AccordionButtonState.collapsed) ||
(!isElipsed && this.buttonState === AccordionButtonState.expanded);
}
toggleDescriptionAccordion() {
if (this.descriptionLinesToDisplay > 0) {
this.descriptionLinesToDisplay =
this.descriptionLinesToDisplay === this.descriptionPreviewLines
? this.descriptionLinesTotal
: this.descriptionPreviewLines;
}
this.buttonState =
this.buttonState === AccordionButtonState.collapsed
? AccordionButtonState.expanded
: AccordionButtonState.collapsed;
setTimeout(() => this.checkTextElipsis(), 0);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 StApps
* Copyright (C) 2019-2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -12,24 +12,10 @@
* 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,
ViewChild,
ElementRef,
HostListener,
OnDestroy,
OnChanges,
} from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
import {SCCatalog, SCSearchBooleanFilter, SCDucetSort} from '@openstapps/core';
import {SearchPageComponent} from '../../list/search-page.component';
enum AccordionButtonState {
collapsed = 'chevron-down',
expanded = 'chevron-up',
}
@Component({
selector: 'stapps-catalog-detail-content',
templateUrl: 'catalog-detail-content.html',
@@ -37,37 +23,15 @@ enum AccordionButtonState {
})
export class CatalogDetailContentComponent
extends SearchPageComponent
implements OnInit, OnDestroy, OnChanges
implements OnInit
{
/**
* SCCatalog to display
*/
@Input() item: SCCatalog;
@ViewChild('accordionTextArea') accordionTextArea: ElementRef;
buttonState = AccordionButtonState.collapsed;
buttonShown = true;
descriptionLinesShown: number;
descriptionLinesTotal: number;
descriptionPreviewLines = 3;
descriptionLinesToDisplay = 0;
ngOnInit() {
super.ngOnInit();
if (this.item.description) {
this.descriptionLinesToDisplay = this.descriptionPreviewLines;
setTimeout(() => this.checkTextElipsis(), 0);
}
}
ngOnChanges() {
this.checkTextElipsis();
}
initialize() {
@@ -141,39 +105,4 @@ export class CatalogDetailContentComponent
type: 'boolean',
};
}
@HostListener('window:resize', ['$event'])
checkTextElipsis() {
if (typeof this.accordionTextArea === 'undefined') {
return;
}
const element = this.accordionTextArea.nativeElement as HTMLElement;
const lineHeight = Number.parseInt(
getComputedStyle(element).getPropertyValue('line-height'),
);
this.descriptionLinesTotal = element?.scrollHeight / lineHeight;
this.descriptionLinesShown = element?.offsetHeight / lineHeight;
if (this.buttonState === AccordionButtonState.expanded) {
this.descriptionLinesToDisplay = this.descriptionLinesTotal;
}
const isElipsed = element?.offsetHeight < element?.scrollHeight;
this.buttonShown =
(isElipsed && this.buttonState === AccordionButtonState.collapsed) ||
(!isElipsed && this.buttonState === AccordionButtonState.expanded);
}
toggleDescriptionAccordion() {
if (this.descriptionLinesToDisplay > 0) {
this.descriptionLinesToDisplay =
this.descriptionLinesToDisplay === this.descriptionPreviewLines
? this.descriptionLinesTotal
: this.descriptionPreviewLines;
}
this.buttonState =
this.buttonState === AccordionButtonState.collapsed
? AccordionButtonState.expanded
: AccordionButtonState.collapsed;
setTimeout(() => this.checkTextElipsis(), 0);
}
}

View File

@@ -1,30 +1,3 @@
<ion-card>
<ion-card-content>
<ion-text color="dark">
<h1>
{{ 'name' | thingTranslate: item }}
</h1>
</ion-text>
<div *ngIf="item.description">
<br />
<div
class="text-accordion"
[style.-webkit-line-clamp]="descriptionLinesToDisplay"
#accordionTextArea
>
{{ 'description' | thingTranslate: item }}
</div>
</div>
</ion-card-content>
</ion-card>
<ion-button
expand="full"
fill="clear"
*ngIf="item.description && buttonShown"
(click)="toggleDescriptionAccordion()"
>
<ion-icon [name]="buttonState" size="large"></ion-icon>
</ion-button>
<stapps-simple-data-list
id="simple-data-list"
[items]="items"

View File

@@ -1,6 +0,0 @@
.text-accordion {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}

View File

@@ -1,13 +1,3 @@
<ion-card>
<ion-card-content>
<ion-text color="dark">
<h1>
{{ 'name' | thingTranslate: item }}
</h1>
</ion-text>
{{ 'description' | thingTranslate: item }}
</ion-card-content>
</ion-card>
<ion-grid>
<ion-row>
<ion-col>

View File

@@ -1,13 +1,3 @@
<ion-card>
<ion-card-content>
<ion-text color="dark">
<h1>
{{ 'name' | thingTranslate: item }}
</h1>
</ion-text>
{{ 'description' | thingTranslate: item }}</ion-card-content
>
</ion-card>
<ng-container>
<div *ngIf="dishes | async as dishes; else loading">
<ion-segment [(ngModel)]="selectedDay" mode="md">