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:
parent
a05a81b1b2
commit
c49ea53ab1
@ -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",
|
||||
|
@ -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>
|
||||
<ng-container *ngTemplateOutlet="content"></ng-container>
|
||||
<!-- 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>
|
||||
|
@ -1,30 +1,72 @@
|
||||
.meta-text-block {
|
||||
padding: 0px;
|
||||
margin: 20px 0;
|
||||
min-width: 200px;
|
||||
@import '~@angular/material/theming';
|
||||
|
||||
mat-card-header {
|
||||
display: inherit;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
@mixin os-meta-text-block-style($theme) {
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.mat-card-header-text {
|
||||
margin: 0 10px;
|
||||
.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-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
|
||||
.title-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
mat-card-header {
|
||||
display: inherit;
|
||||
margin: 0;
|
||||
|
||||
.mat-card-header-text {
|
||||
margin: 0 10px;
|
||||
}
|
||||
mat-card-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
|
||||
.title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.action-row {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat-card-content {
|
||||
padding: 15px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 },
|
||||
|
@ -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">
|
||||
|
@ -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"> ({{ pollIndex + 1 }})</span>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user