Checks, if content is too large and hide it in 'meta-text-block'

- Also updates the library 'css-element-queries'.
- Builds a directive to check, if the scroll-height of an element
has changed.
This commit is contained in:
GabrielMeyer 2019-08-21 15:05:03 +02:00
parent a05a81b1b2
commit c49ea53ab1
12 changed files with 307 additions and 50 deletions

View File

@ -51,7 +51,7 @@
"@tinymce/tinymce-angular": "^3.2.0",
"acorn": "^6.1.1",
"core-js": "^3.0.1",
"css-element-queries": "^1.1.1",
"css-element-queries": "^1.2.1",
"exceljs": "1.10.0",
"file-saver": "^2.0.1",
"hammerjs": "^2.0.8",

View File

@ -3,18 +3,29 @@
<mat-card-header>
<mat-card-title>
<div class="title-container">
<div>
<div class="ellipsis-overflow">
<ng-container *ngTemplateOutlet="title"></ng-container>
</div>
<div *ngIf="showActionRow">
<div class="action-row" *ngIf="showActionRow">
<ng-container *ngTemplateOutlet="actionRow"></ng-container>
</div>
</div>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<!-- Content -->
<div
#contentBox
[osHeightResizing]="resizeSubject"
class="content"
[ngClass]="!isExpanded && !disableExpandControl ? 'collapsed' : ''"
>
<ng-container *ngTemplateOutlet="content"></ng-container>
</div>
<!-- Expanding control -->
<div class="small show-entire-text" *ngIf="canExpand && !disableExpandControl">
<a (click)="isExpanded = !isExpanded">{{ isExpanded ? 'Hide more text' : 'Show full text' }}</a>
</div>
</mat-card-content>
</mat-card>
</div>

View File

@ -1,11 +1,20 @@
@import '~@angular/material/theming';
@mixin os-meta-text-block-style($theme) {
$foreground: map-get($theme, foreground);
.meta-text-block {
padding: 0px;
margin: 20px 0;
min-width: 200px;
.mat-icon-button mat-icon {
color: mat-color($foreground, icon);
font-size: 18px;
}
mat-card-header {
display: inherit;
padding-top: 10px;
margin: 0;
.mat-card-header-text {
@ -18,7 +27,12 @@
.title-container {
display: flex;
align-items: center;
justify-content: space-between;
.action-row {
display: flex;
}
}
}
}
@ -26,5 +40,33 @@
mat-card-content {
padding: 15px;
word-wrap: break-word;
.content {
transition: all 1s ease;
&.collapsed {
max-height: 200px;
overflow: hidden;
position: relative;
&::after {
content: '';
position: absolute;
top: 150px;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
}
}
}
.show-entire-text {
text-align: end;
margin-top: 4px;
a {
cursor: pointer;
}
}
}
}
}

View File

@ -1,7 +1,8 @@
import { Component, Input } from '@angular/core';
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { Subject, Subscription } from 'rxjs';
import { ViewportService } from 'app/core/ui-services/viewport.service';
import { BaseComponent } from '../../../base.component';
@ -14,11 +15,102 @@ import { BaseComponent } from '../../../base.component';
templateUrl: './meta-text-block.component.html',
styleUrls: ['./meta-text-block.component.scss']
})
export class MetaTextBlockComponent extends BaseComponent {
export class MetaTextBlockComponent extends BaseComponent implements OnInit, OnDestroy {
/**
* Indicates, whether the action-row should be shown.
*/
@Input()
public showActionRow: boolean;
public constructor(title: Title, translate: TranslateService, public vp: ViewportService) {
/**
* Indicates, whether the content should be expandable or always expanded.
*
* If `true`, it resets the flag `isExpanded`. This prevents an error -
* when the given element is expanded and the control was disabled, the
* subscription is deleted.
*/
@Input()
public set disableExpandControl(disableControl: boolean) {
this._disableExpandControl = disableControl;
if (disableControl) {
this.isExpanded = false;
this.cd.detectChanges();
}
}
/**
* Returns the flag `disableExpandControl`.
*/
public get disableExpandControl(): boolean {
return this._disableExpandControl;
}
/**
* Boolean, whether the control to expand the element should be disabled or not.
*/
private _disableExpandControl = false;
/**
* Boolean to see, if the content can be expanded.
*/
public canExpand = false;
/**
* Boolean to see, if the content is currently expanded.
*/
public isExpanded = false;
/**
* Subject to listen, whether the height of the given dom-element has changed.
*/
public resizeSubject = new Subject<number>();
/**
* Subscription to resize-change-events for the height of the content.
*/
private contentSubscription: Subscription;
/**
* Default constructor.
*
* @param title
* @param translate
* @param vp
* @param cd
*/
public constructor(
title: Title,
translate: TranslateService,
public vp: ViewportService,
private cd: ChangeDetectorRef
) {
super(title, translate);
}
/**
* Sets the subscription.
*/
public ngOnInit(): void {
this.contentSubscription = this.resizeSubject.subscribe(newHeight => this.resizesContentBox(newHeight));
}
/**
* Deletes and unsubscribes to subscription.
*/
public ngOnDestroy(): void {
if (this.contentSubscription) {
this.contentSubscription.unsubscribe();
this.contentSubscription = null;
}
}
/**
* Function to check, if the new height of the element
* is greater than the limit of `200px`.
*
* @param height The new height as `number` of the linked element.
*/
private resizesContentBox(height: number): void {
this.canExpand = height > 200;
}
}

View File

@ -0,0 +1,8 @@
import { HeightResizingDirective } from './height-resizing.directive';
describe('HeightResizingDirective', () => {
it('should create an instance', () => {
const directive = new HeightResizingDirective(null);
expect(directive).toBeTruthy();
});
});

View File

@ -0,0 +1,69 @@
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
import { ResizeSensor } from 'css-element-queries';
import { Subject } from 'rxjs';
/**
* Directive to check, if the `ScrollHeight` of the underlying element has changed.
*/
@Directive({
selector: '[osHeightResizing]'
})
export class HeightResizingDirective implements OnInit {
/**
* A subject to notify, when the given element changes its `ScrollHeight`.
*/
@Input()
public osHeightResizing: Subject<number>;
/**
* The underlying native-element of the passed element.
*/
private nativeElement: HTMLElement;
/**
* Stores the old height to see, if the height changed.
*/
private oldHeight: number;
/**
* Constructor.
* Initializes the `nativeElement`.
*
* @param element The passed element for this directive.
*/
public constructor(element: ElementRef) {
if (element) {
this.nativeElement = <HTMLElement>element.nativeElement;
}
}
/**
* Initializes the listener for resizing events of the passed element.
*/
public ngOnInit(): void {
// tslint:disable-next-line:no-unused-expression
new ResizeSensor(this.nativeElement, () => {
this.checkElementForChanges();
});
this.checkElementForChanges();
}
/**
* Function to check, if the height of the passed element changed
* and if the new height is different to the old one.
*
* If the new height is different to the old one, the subject gets a new value.
*/
private checkElementForChanges(): void {
if (this.nativeElement.scrollHeight === this.oldHeight) {
return;
}
this.oldHeight = this.nativeElement.scrollHeight;
if (this.osHeightResizing) {
this.osHeightResizing.next(this.nativeElement.scrollHeight);
}
}
}

View File

@ -102,6 +102,7 @@ import { OverlayComponent } from 'app/site/common/components/overlay/overlay.com
import { PreviewComponent } from './components/preview/preview.component';
import { PdfViewerModule } from 'ng2-pdf-viewer';
import { GlobalSpinnerComponent } from 'app/site/common/components/global-spinner/global-spinner.component';
import { HeightResizingDirective } from './directives/height-resizing.directive';
/**
* Share Module for all "dumb" components and pipes.
@ -223,6 +224,7 @@ import { GlobalSpinnerComponent } from 'app/site/common/components/global-spinne
ProjectorButtonComponent,
ProjectionDialogComponent,
ResizedDirective,
HeightResizingDirective,
MetaTextBlockComponent,
ProjectorComponent,
SlideContainerComponent,
@ -290,7 +292,8 @@ import { GlobalSpinnerComponent } from 'app/site/common/components/global-spinne
GlobalSpinnerComponent,
SuperSearchComponent,
OverlayComponent,
PreviewComponent
PreviewComponent,
HeightResizingDirective
],
providers: [
{ provide: DateAdapter, useClass: OpenSlidesDateAdapter },

View File

@ -2,6 +2,7 @@
<os-meta-text-block
*ngIf="sectionVisible(section)"
[showActionRow]="canEditSection(section) || comments[section.id].comment"
[disableExpandControl]="isCommentEdited(section)"
icon="comment"
>
<ng-container class="meta-text-block-title">

View File

@ -1,4 +1,4 @@
<os-meta-text-block showActionRow="true">
<os-meta-text-block showActionRow="true" [disableExpandControl]="true">
<ng-container class="meta-text-block-title">
<span translate>Voting result</span>
<span *ngIf="pollIndex">&nbsp;({{ pollIndex + 1 }})</span>

View File

@ -1,4 +1,4 @@
<os-meta-text-block showActionRow="true" icon="speaker_notes">
<os-meta-text-block showActionRow="true" icon="speaker_notes" [disableExpandControl]="true">
<!-- Title row -->
<ng-container class="meta-text-block-title">
<span translate>Personal note</span>

View File

@ -1,4 +1,4 @@
<os-meta-text-block showActionRow="false" *ngIf="projector">
<os-meta-text-block showActionRow="false" *ngIf="projector" [disableExpandControl]="true">
<ng-container class="meta-text-block-title">
{{ projector.getTitle() | translate }}
</ng-container>
@ -35,7 +35,11 @@
<h3 translate>Resolution and size</h3>
<!-- Aspect ratio field -->
<mat-radio-group formControlName="aspectRatio" [name]="projector.id">
<mat-radio-button *ngFor="let ratio of aspectRatiosKeys" [value]="ratio" (change)="aspectRatioChanged($event)">
<mat-radio-button
*ngFor="let ratio of aspectRatiosKeys"
[value]="ratio"
(change)="aspectRatioChanged($event)"
>
{{ ratio }}
</mat-radio-button>
</mat-radio-group>
@ -53,7 +57,11 @@
<!-- projection defaults -->
<h3 translate>Projection defaults</h3>
<mat-select formControlName="projectiondefaults_id" placeholder="{{ 'Projection defaults' | translate }}" [multiple]="true">
<mat-select
formControlName="projectiondefaults_id"
placeholder="{{ 'Projection defaults' | translate }}"
[multiple]="true"
>
<mat-option *ngFor="let pd of projectionDefaults" [value]="pd.id">
{{ pd.getTitle() | translate }}
</mat-option>
@ -71,7 +79,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('color', '#000000')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('color', '#000000')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -88,7 +100,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('background_color', '#ffffff')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('background_color', '#ffffff')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -105,7 +121,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('header_background_color', '#317796')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('header_background_color', '#317796')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -122,7 +142,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('header_font_color', '#f5f5f5')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('header_font_color', '#f5f5f5')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -139,7 +163,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('header_h1_color', '#317796')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('header_h1_color', '#317796')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -156,7 +184,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('chyron_background_color', '#317796')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('chyron_background_color', '#317796')"
>
<mat-icon>replay</mat-icon>
</button>
</div>
@ -173,7 +205,11 @@
</mat-form-field>
</div>
<div class="reset-button">
<button mat-icon-button matTooltip="{{ 'Reset' | translate }}" (click)="resetField('chyron_font_color', '#ffffff')">
<button
mat-icon-button
matTooltip="{{ 'Reset' | translate }}"
(click)="resetField('chyron_font_color', '#ffffff')"
>
<mat-icon>replay</mat-icon>
</button>
</div>

View File

@ -23,6 +23,7 @@
@import './app/site/mediafiles/components/mediafile-list/mediafile-list.component.scss-theme.scss';
@import './app/site/common/components/super-search/super-search.component.scss';
@import './app/shared/components/rounded-input/rounded-input.component.scss';
@import './app/shared/components/meta-text-block/meta-text-block.component.scss';
/** fonts */
@import './assets/styles/fonts.scss';
@ -46,6 +47,7 @@ $narrow-spacing: (
@include os-mediafile-list-theme($theme);
@include os-super-search-style($theme);
@include os-rounded-input-style($theme);
@include os-meta-text-block-style($theme);
}
/** Load projector specific SCSS values */
@ -546,13 +548,6 @@ button.mat-menu-item.selected {
margin-right: 8px !important;
}
.meta-text-block .mat-icon-button {
margin-top: -12px !important;
}
.meta-text-block .mat-icon-button mat-icon {
font-size: 18px;
}
/** helper classes for margin/padding */
.spacer-top-3 {
margin-top: 3px !important;