Skip to content

Commit

Permalink
Fix expand resources (hyperledger-archives#1242)
Browse files Browse the repository at this point in the history
Fixed animation
Fixed problem with only showing first 1000px of height
  • Loading branch information
cazfletch authored Jun 12, 2017
1 parent 84061ac commit f9913c4
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/* tslint:disable:no-unused-variable */
/* tslint:disable:no-unused-expression */
/* tslint:disable:no-var-requires */
/* tslint:disable:max-classes-per-file */
import { ComponentFixture, TestBed, async, fakeAsync, tick, inject } from '@angular/core/testing';
import { Component, Renderer, } from '@angular/core';
import { By } from '@angular/platform-browser';

import * as sinon from 'sinon';
import * as chai from 'chai';
import { CheckOverFlowDirective } from './check-overflow.directive';

let should = chai.should();

@Component({
selector: 'test',
template: `
<div checkOverFlow [changed]="changed"
[expanded]="expanded" (hasOverFlow)=hasOverFlow($event)>
<pre #resourcedata>bob</pre>
</div>`
})

class TestComponent {

changed: boolean = false;
expanded: boolean = false;

overflow: boolean = false;

hasOverFlow(overflow: boolean) {
this.overflow = overflow;
}

}

describe('CheckOverFlowDirective', () => {

let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestComponent, CheckOverFlowDirective],
providers: [Renderer]
})

.compileComponents();
}));

it('should create the directive', async(fakeAsync(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();

tick();

component.should.be.ok;
})));

describe('checkOverFlow', () => {
it('should set max height to be 100px when not expanded', async(fakeAsync(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();

let de = fixture.debugElement.query(By.css('pre'));
let el = de.nativeElement;
el.style.maxHeight.should.equal('100px');

tick();

component.overflow.should.equal(false);
})));

it('should set max height to be scroll height when expanded', async(fakeAsync(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
component.expanded = true;
fixture.detectChanges();

let de = fixture.debugElement.query(By.css('pre'));
let el = de.nativeElement;

el.style.maxHeight.should.equal(el.scrollHeight + 'px');

tick();

component.overflow.should.equal(true);
})));
});

describe('inputs', () => {
it('should update when content changes', async(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
let directiveEl = fixture.debugElement.query(By.directive(CheckOverFlowDirective));
let directiveInstance = directiveEl.injector.get(CheckOverFlowDirective);

let checkOverFlowMock = sinon.stub(directiveInstance, 'checkOverFlow');

component.changed = true;

fixture.detectChanges();

checkOverFlowMock.should.have.been.called;
}));

it('should update when expanded changes', async(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
let directiveEl = fixture.debugElement.query(By.directive(CheckOverFlowDirective));
let directiveInstance = directiveEl.injector.get(CheckOverFlowDirective);

let checkOverFlowMock = sinon.stub(directiveInstance, 'checkOverFlow');

component.expanded = true;

fixture.detectChanges();

checkOverFlowMock.should.have.been.called;
}));
});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Directive, ElementRef, EventEmitter, Output, Input } from '@angular/core';
import {
Directive,
ElementRef,
EventEmitter,
Output,
Input,
Renderer,
ContentChild,
AfterViewInit
} from '@angular/core';

@Directive({
selector: '[checkOverFlow]',
})

export class CheckOverFlowDirective {
export class CheckOverFlowDirective implements AfterViewInit {

@Output()
public hasOverFlow: EventEmitter<boolean> = new EventEmitter<boolean>();
Expand All @@ -17,16 +26,46 @@ export class CheckOverFlowDirective {
}
}

@Input()
set expanded(expanded) {
this._expanded = expanded;
this.checkOverFlow();
}

@ContentChild('resourcedata') preEl: ElementRef;

private _thing = null;
private _expanded = false;

constructor(private el: ElementRef) {
constructor(private el: ElementRef, private renderer: Renderer) {
}

ngAfterViewInit() {
this.checkOverFlow();
}

checkOverFlow() {
let element = this.el;
let preElement = this.preEl;

if (!preElement) {
return;
}

let expanded = this._expanded;

if (expanded) {
let contentHeight = preElement.nativeElement.scrollHeight;
this.renderer.setElementStyle(preElement.nativeElement, 'maxHeight', contentHeight + 'px');
} else {
this.renderer.setElementStyle(preElement.nativeElement, 'maxHeight', '100px');
}

setTimeout(() => {
let overFlowAmount = element.nativeElement.scrollHeight - element.nativeElement.offsetHeight;
if (overFlowAmount > 10) {

let scrollHeight = preElement.nativeElement.scrollHeight;

if (expanded || scrollHeight > 110) {
this.hasOverFlow.emit(true);
} else {
this.hasOverFlow.emit(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,54 @@
<div *ngIf="_registry" class="resource-header">
<div class="resource-header-left">
<h1>{{_registry.name}}</h1>
</div>
<div *ngIf="!isTransactionRegistry()">
<button type="button" class="registry" (click)="openNewResourceModal()">
<span>+ Create New {{_registry.registryType}}</span>
</button>
</div>
<div class="resource-header-left">
<h1>{{_registry.name}}</h1>
</div>
<div *ngIf="!isTransactionRegistry()">
<button type="button" class="registry" (click)="openNewResourceModal()">
<span>+ Create New {{_registry.registryType}}</span>
</button>
</div>
</div>
<div *ngIf="_registry" class="resource-list">
<div class="title" [ngClass]="{'resource-empty' : !resources || resources.length === 0}">
<div class="id">ID</div>
<div class="data">Data</div>
</div>
<div *ngFor="let resource of resources" class="resource-container">
<div class="resource-content" [ngClass]="{'expanded' : resource.getIdentifier() === expandedResource}">
<div class="id">{{resource.getIdentifier()}}</div>
<pre checkOverFlow [changed]="resource.getIdentifier()" (hasOverFlow)=hasOverFlow($event)
[ngClass]="{'gradient' : resource.getIdentifier() !== expandedResource && showExpand, 'tiny-gradient' : resource.getIdentifier() === expandedResource || !showExpand}"
class="data">{{serialize(resource)}}</pre>
<div *ngIf="!isTransactionRegistry()" class="resource-icon">
<button type="button" class="icon" (click)="editResource(resource)">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-edit_32"></use>
</svg>
</button>
</div>
<div *ngIf="!isTransactionRegistry()" class="resource-icon">
<button type="button" class="icon" (click)="openDeleteResourceModal(resource)">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-trash_32"></use>
</svg>
<div class="title" [ngClass]="{'resource-empty' : !resources || resources.length === 0}">
<div class="id">ID</div>
<div class="data">Data</div>
</div>
<div *ngFor="let resource of resources" class="resource-container">
<div checkOverFlow [changed]="resource.getIdentifier()" [expanded]="resource.getIdentifier() === expandedResource" (hasOverFlow)=hasOverFlow($event)
class="resource-content" [ngClass]="{'expanded' : resource.getIdentifier() === expandedResource}">
<div class="id">{{resource.getIdentifier()}}</div>
<pre #resourcedata
[ngClass]="{'gradient' : resource.getIdentifier() !== expandedResource && showExpand, 'tiny-gradient' : resource.getIdentifier() === expandedResource || !showExpand}"
class="data">{{serialize(resource)}}</pre>
<div *ngIf="!isTransactionRegistry()" class="resource-icon">
<button type="button" class="icon" (click)="editResource(resource)">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-edit_32"></use>
</svg>
</button>
</div>
<div *ngIf="!isTransactionRegistry()" class="resource-icon">
<button type="button" class="icon" (click)="openDeleteResourceModal(resource)">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-trash_32"></use>
</svg>
</button>
</div>
</div>
<button *ngIf="showExpand" class="expand" type="button" (click)="expandResource(resource)">
{{resource.getIdentifier() === expandedResource ? 'Collapse' : 'Show All'}}
</button>
</div>
</div>
<button *ngIf="showExpand" class="expand" type="button" (click)="expandResource(resource)">
{{resource.getIdentifier() === expandedResource ? 'Collapse' : 'Show All'}}
</button>
</div>
<div *ngIf="!resources || resources.length === 0" class="no-resources">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-Emptiness"></use>
</svg>
<h3>This registry is empty!</h3>
<p *ngIf="_registry.registryType!='Transaction'">To create resources in this registry click create new at the top of
this page</p>
<p *ngIf="_registry.registryType=='Transaction'">Submit a Transaction via the side menu</p>
</div>


<div *ngIf="!resources || resources.length === 0" class="no-resources">
<svg class="ibm-icon" aria-hidden="true">
<use xlink:href="#icon-Emptiness"></use>
</svg>
<h3>This registry is empty!</h3>
<p *ngIf="_registry.registryType!='Transaction'">To create resources in this registry click create new at the
top of
this page</p>
<p *ngIf="_registry.registryType=='Transaction'">Submit a Transaction via the side menu</p>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ registry {

&.expanded {
pre {
max-height: 999px;
overflow: hidden;

@include transition(all);
Expand All @@ -83,7 +82,6 @@ registry {
pre {
margin: 0;
margin-top: $space-small;
max-height: 100px;
overflow: hidden;

@include transition(all);
Expand Down Expand Up @@ -127,7 +125,7 @@ registry {
button.expand {
position: absolute;
left: 40%;
bottom: 5%;
bottom: 10px;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ let should = chai.should();
class MockCheckOverFlowDirective {
@Output() public hasOverFlow: EventEmitter<boolean> = new EventEmitter<boolean>();
@Input() public changed: boolean;
@Input() public expanded: boolean;
}

describe(`RegistryComponent`, () => {
Expand Down

0 comments on commit f9913c4

Please sign in to comment.