Implement expanding subschemas (fixes #56)

This commit is contained in:
Roman Hotsiy 2016-06-29 18:02:19 +03:00
parent 9e1d7768d7
commit 0b0f28cd4a
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
6 changed files with 71 additions and 40 deletions

View File

@ -11,16 +11,6 @@ $param-name-height: 20px;
$sub-schema-offset: ($bullet-size/2) + $bullet-margin; $sub-schema-offset: ($bullet-size/2) + $bullet-margin;
/*
.param-schema {
padding-left: $sub-schema-offset - $lines-width;
border-left: $line-border;
}
.param-wrap {
position: relative;
}*/
.param-name { .param-name {
font-size: 0.929em; font-size: 0.929em;
@ -34,7 +24,7 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin;
vertical-align: top; vertical-align: top;
} }
.param-name-content { .param-name-wrap {
padding-right: $cell-spacing; padding-right: $cell-spacing;
display: inline-block; display: inline-block;
font-family: $headers-font, $headers-font-family; font-family: $headers-font, $headers-font-family;
@ -45,6 +35,7 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
width: 75%; width: 75%;
line-height: 1em;
} }
.param-range { .param-range {

View File

@ -1,8 +1,8 @@
'use strict'; 'use strict';
import { Component, ElementRef, ViewContainerRef, OnDestroy, AfterViewInit } from '@angular/core'; import { Component, ElementRef, ViewContainerRef, OnDestroy, Input,
AfterViewInit, ComponentResolver, Renderer } from '@angular/core';
import { CORE_DIRECTIVES } from '@angular/common'; import { CORE_DIRECTIVES } from '@angular/common';
import { DynamicComponentLoader, Input } from '@angular/core';
import { JsonSchema } from './json-schema'; import { JsonSchema } from './json-schema';
import { OptionsService } from '../../services/options.service'; import { OptionsService } from '../../services/options.service';
@ -19,9 +19,13 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit {
@Input() pointer: string; @Input() pointer: string;
@Input() auto: boolean; @Input() auto: boolean;
@Input() isRequestSchema: boolean; @Input() isRequestSchema: boolean;
@Input() final: boolean = false;
@Input() nestOdd: boolean;
@Input() childFor: string;
@Input() isArray: boolean;
loaded: boolean = false; loaded: boolean = false;
constructor(private specMgr:SpecManager, private viewRef:ViewContainerRef, private elementRef:ElementRef, constructor(private specMgr:SpecManager, private location:ViewContainerRef, private elementRef:ElementRef,
private dcl:DynamicComponentLoader, private optionsService:OptionsService) { private resolver:ComponentResolver, private optionsService:OptionsService, private _renderer: Renderer) {
} }
normalizePointer() { normalizePointer() {
@ -31,13 +35,15 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit {
_loadAfterSelf() { _loadAfterSelf() {
// FIXME: get rid of DynamicComponentLoader as it is deprecated // FIXME: get rid of DynamicComponentLoader as it is deprecated
return this.dcl.loadNextToLocation(JsonSchema, this.viewRef).then(compRef => { return this.resolver.resolveComponent(JsonSchema).then(componentFactory => {
this.initComponent(compRef); let contextInjector = this.location.parentInjector;
if (compRef.changeDetectorRef) { let compRef = this.location.createComponent(
compRef.changeDetectorRef.detectChanges(); componentFactory, null, contextInjector, null);
} this.initComponent(compRef.instance);
this._renderer.setElementAttribute(compRef.location.nativeElement, 'class', this.location.element.nativeElement.className);
compRef.changeDetectorRef.markForCheck();
return compRef; return compRef;
}, err => { }).catch(err => {
console.log(err); console.log(err);
throw err; throw err;
}); });
@ -74,9 +80,8 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit {
} }
} }
initComponent(compRef) { initComponent(instance:JsonSchema) {
compRef.instance.pointer = this.pointer; Object.assign(instance, this);
compRef.instance.isRequestSchema = this.isRequestSchema;
} }
ngAfterViewInit() { ngAfterViewInit() {

View File

@ -19,14 +19,20 @@
</span> </span>
<table *ngIf="!schema.isTrivial" class="params-wrap" [ngClass]="{'params-array': schema._isArray}"> <table *ngIf="!schema.isTrivial" class="params-wrap" [ngClass]="{'params-array': schema._isArray}">
<!-- <caption> {{_displayType}} </caption> --> <!-- <caption> {{_displayType}} </caption> -->
<template ngFor [ngForOf]="schema._properties" let-prop="$implicit" let-last="last"> <template ngFor [ngForOf]="schema._properties" let-prop="$implicit" let-last="last" [ngForTrackBy]="trackByName">
<tr class="param" [ngClass]="{'last': last, <tr class="param" [ngClass]="{'last': last,
'discriminator': hasDescendants && !activeDescendant.empty, 'discriminator': prop.isDiscriminator,
'complex': prop._pointer, 'complex': prop._pointer,
'additional': prop._additional 'additional': prop._additional,
'expanded': subSchema.visible
}"> }">
<td class="param-name"> <td class="param-name">
<span class="param-name-content">{{prop._name}}</span> <span class="param-name-wrap">
<span (click)="subSchema.toggle()" class="param-name-content" >{{prop._name}}</span>
<svg *ngIf="prop._pointer" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 24 24" xml:space="preserve">
<polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "/>
</svg>
</span>
</td> </td>
<td class="param-info"> <td class="param-info">
<div> <div>
@ -50,11 +56,13 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr class="param-schema" [ngClass]="{'param-array': prop._isArray, 'last': last}" *ngIf="prop._pointer"> <tr class="param-schema" [ngClass]="{'param-array': prop._isArray, 'last': last}" [hidden]="!prop._pointer">
<td colspan="2"> <td colspan="2">
<json-schema class="nested-schema" pointer="{{prop._pointer}}" [isArray]='prop._isArray' <zippy #subSchema title="test" [headless]="true" (open)="lazySchema.load()">
[nestOdd]="!nestOdd" [isRequestSchema]="isRequestSchema" [attr.nesteven]="!nestOdd"> <json-schema-lazy #lazySchema class="nested-schema" pointer="{{prop._pointer}}" [isArray]='prop._isArray'
</json-schema> [nestOdd]="!nestOdd" [isRequestSchema]="isRequestSchema">
</json-schema-lazy>
</zippy>
</td> </td>
</tr> </tr>
</template> </template>

View File

@ -19,7 +19,7 @@ $array-marker-line-height: 1.5;
display: block; display: block;
} }
json-schema.nested-schema { :host.nested-schema {
background-color: white; background-color: white;
padding: 10px 20px; padding: 10px 20px;
position: relative; position: relative;
@ -50,7 +50,7 @@ json-schema.nested-schema {
} }
} }
json-schema[nesteven="true"] { :host[nestodd="true"] {
background-color: $side-menu-active-bg-color; background-color: $side-menu-active-bg-color;
border-radius: $border-radius; border-radius: $border-radius;
@ -69,10 +69,29 @@ json-schema[nesteven="true"] {
} }
} }
.param.complex > .param-info { .zippy-content-wrap {
padding: 0;
}
.param.complex.expanded > .param-info {
border-bottom: 0; border-bottom: 0;
} }
.param.complex > .param-name .param-name-content {
font-weight: bold;
cursor: pointer;
}
.param.complex > .param-name svg {
height: 1.2em;
vertical-align: middle;
transition: all 0.3s ease;
}
.param.complex.expanded > .param-name svg{
transform: rotateZ(-180deg);
}
.param.additional > .param-name { .param.additional > .param-name {
color: rgba($black, 0.4); color: rgba($black, 0.4);
} }
@ -127,7 +146,6 @@ json-schema[nesteven="true"] {
.param.discriminator { .param.discriminator {
> .param-info { > .param-info {
padding-bottom: 0; padding-bottom: 0;
border-bottom: 0;
} }
> .param-name:after { > .param-name:after {

View File

@ -1,16 +1,18 @@
'use strict'; 'use strict';
import { Input } from '@angular/core'; import { Input, Renderer, ElementRef } from '@angular/core';
import { RedocComponent, BaseComponent, SpecManager } from '../base'; import { RedocComponent, BaseComponent, SpecManager } from '../base';
import { DropDown } from '../../shared/components/index'; import { DropDown } from '../../shared/components/index';
import { SchemaNormalizer, SchemaHelper } from '../../services/index'; import { SchemaNormalizer, SchemaHelper } from '../../services/index';
import { JsonSchemaLazy } from './json-schema-lazy';
import { Zippy } from '../../shared/components/Zippy/zippy';
@RedocComponent({ @RedocComponent({
selector: 'json-schema', selector: 'json-schema',
templateUrl: './json-schema.html', templateUrl: './json-schema.html',
styleUrls: ['./json-schema.css'], styleUrls: ['./json-schema.css'],
directives: [JsonSchema, DropDown], directives: [JsonSchema, DropDown, JsonSchemaLazy, Zippy],
detect: true detect: true
}) })
export class JsonSchema extends BaseComponent { export class JsonSchema extends BaseComponent {
@ -24,7 +26,7 @@ export class JsonSchema extends BaseComponent {
@Input() isRequestSchema: boolean; @Input() isRequestSchema: boolean;
normalizer: SchemaNormalizer; normalizer: SchemaNormalizer;
constructor(specMgr:SpecManager) { constructor(specMgr:SpecManager, private _renderer: Renderer, private _elementRef: ElementRef) {
super(specMgr); super(specMgr);
this.normalizer = new SchemaNormalizer(specMgr); this.normalizer = new SchemaNormalizer(specMgr);
} }
@ -63,6 +65,9 @@ export class JsonSchema extends BaseComponent {
} }
prepareModel() { prepareModel() {
if (this.nestOdd) {
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'nestodd', 'true');
}
this.schema = this.componentSchema; this.schema = this.componentSchema;
if (!this.schema) { if (!this.schema) {
throw new Error(`Can't load component schema at ${this.pointer}`); throw new Error(`Can't load component schema at ${this.pointer}`);
@ -81,4 +86,8 @@ export class JsonSchema extends BaseComponent {
this.initDescendants(); this.initDescendants();
} }
trackByName(index: number, item: any): string {
return item['name'];
}
} }

View File

@ -8,7 +8,7 @@
<div class="params-wrap"> <div class="params-wrap">
<div *ngFor="let param of paramType.params" class="param"> <div *ngFor="let param of paramType.params" class="param">
<div class="param-name"> <div class="param-name">
<span class="param-name-content"> {{param.name}} </span> <span class="param-name-wrap"> {{param.name}} </span>
</div> </div>
<div class="param-info"> <div class="param-info">
<div> <div>