diff --git a/lib/components/JsonSchema/json-schema.html b/lib/components/JsonSchema/json-schema.html index dd6441a4..7ba2f8a1 100644 --- a/lib/components/JsonSchema/json-schema.html +++ b/lib/components/JsonSchema/json-schema.html @@ -84,7 +84,7 @@
- + diff --git a/lib/components/JsonSchema/json-schema.ts b/lib/components/JsonSchema/json-schema.ts index a4de8c8f..44b5f27b 100644 --- a/lib/components/JsonSchema/json-schema.ts +++ b/lib/components/JsonSchema/json-schema.ts @@ -11,7 +11,7 @@ import { Component, import { BaseSearchableComponent, SpecManager } from '../base'; import { SchemaNormalizer, SchemaHelper, AppStateService } from '../../services/'; -import { JsonPointer } from '../../utils/'; +import { JsonPointer, DescendantInfo } from '../../utils/'; import { Zippy } from '../../shared/components'; import { JsonSchemaLazy } from './json-schema-lazy'; @@ -36,10 +36,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { properties: any; _isArray: boolean; normalizer: SchemaNormalizer; - descendants: any; - - // @ViewChildren(Zippy) childZippies: QueryList; - // @ViewChildren(forwardRef(() => JsonSchemaLazy)) childSchemas: QueryList; + descendants: DescendantInfo[]; constructor( specMgr:SpecManager, @@ -55,8 +52,11 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { return this.schema._pointer || this.pointer; } - selectDescendant(idx) { - let activeDescendant = this.descendants[idx]; + selectDescendantByIdx(idx) { + this.selectDescendant(this.descendants[idx]); + } + + selectDescendant(activeDescendant: DescendantInfo) { if (!activeDescendant || activeDescendant.active) return; this.descendants.forEach(d => { d.active = false; @@ -69,6 +69,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { this.schema = this.normalizer.normalize(this.schema, this.normPointer, {resolved: true}); this.preprocessSchema(); + this.activeDescendant = activeDescendant; } initDescendants() { @@ -91,7 +92,7 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { return enumOrder[a.name] > enumOrder[b.name] ? 1 : -1; }); } - this.selectDescendant(0); + this.selectDescendantByIdx(0); } init() { @@ -154,6 +155,21 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { return idx; } + findDescendantWithField(fieldName: string): DescendantInfo { + let res: DescendantInfo; + for (let descendantInfo of this.descendants) { + let schema = this.specMgr.getDescendant(descendantInfo, this.schema); + this.normalizer.reset(); + schema = this.normalizer.normalize(schema, this.normPointer, + {resolved: true}); + if (schema.properties && schema.properties[fieldName]) { + res = descendantInfo; + break; + }; + }; + return res; + } + ensureSearchIsShown(ptr: string) { if (ptr.startsWith(this.absolutePointer)) { let props = this.properties; @@ -164,8 +180,12 @@ export class JsonSchema extends BaseSearchableComponent implements OnInit { propName = relative[1]; } let prop = props.find(p => p._name === propName); - if (!prop || prop.isTrivial) return; - prop.expanded = true; + if (!prop) { + let d = this.findDescendantWithField(propName); + this.selectDescendant(d); + prop = this.properties.find(p => p._name === propName); + } + if (prop && !prop.isTrivial) prop.expanded = true; this.cdr.markForCheck(); this.cdr.detectChanges(); } diff --git a/lib/services/search.service.ts b/lib/services/search.service.ts index 9ca7c406..4888292f 100644 --- a/lib/services/search.service.ts +++ b/lib/services/search.service.ts @@ -47,6 +47,8 @@ export class SearchService { } index(element: IndexElement) { + // don't reindex same pointers (for discriminator) + if (store[element.pointer]) return; index.add(element); store[element.pointer] = element; } @@ -117,7 +119,8 @@ export class SearchService { let schema = _schema; let title = name; - schema = this.normalizer.normalize(schema, absolutePointer); + this.normalizer.reset(); + schema = this.normalizer.normalize(schema, schema._pointer || absolutePointer); let body = schema.description; // TODO: defaults, examples, etc... @@ -126,6 +129,14 @@ export class SearchService { return; } + if (schema.discriminator && !schema['x-derived-from']) { + let derived = this.spec.findDerivedDefinitions(schema._pointer, schema); + for (let defInfo of derived ) { + let subSpec = this.spec.getDescendant(defInfo, schema); + this.indexSchema(subSpec, '', absolutePointer, menuPointer); + } + } + this.index({ pointer: absolutePointer, menuId: menuPointer, diff --git a/lib/shared/components/DropDown/drop-down.ts b/lib/shared/components/DropDown/drop-down.ts index 5e3e920b..a89f3eba 100644 --- a/lib/shared/components/DropDown/drop-down.ts +++ b/lib/shared/components/DropDown/drop-down.ts @@ -1,6 +1,6 @@ 'use strict'; -import { Component, EventEmitter, ElementRef, Output, AfterContentInit } from '@angular/core'; +import { Component, EventEmitter, ElementRef, Output, Input, AfterContentInit, OnChanges } from '@angular/core'; import * as DropKick from 'dropkickjs'; @Component({ @@ -8,8 +8,9 @@ import * as DropKick from 'dropkickjs'; templateUrl: 'drop-down.html', styleUrls: ['./drop-down.css'] }) -export class DropDown implements AfterContentInit { +export class DropDown implements AfterContentInit, OnChanges { @Output() change = new EventEmitter(); + @Input() active: string; elem: any; inst: any; constructor(elem:ElementRef) { @@ -24,6 +25,12 @@ export class DropDown implements AfterContentInit { this.change.next(value); } + ngOnChanges(ch) { + if (ch.active.currentValue) { + this.inst && this.inst.select(ch.active.currentValue); + } + } + destroy() { this.inst.dispose(); } diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index d465b026..9fea813c 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -11,6 +11,13 @@ function getDiscriminator(obj) { return obj.discriminator || obj['x-extendedDiscriminator']; } +export interface DescendantInfo { + $ref: string; + name: string; + active?: boolean; + idx: number; +} + export class SpecManager { public _schema: any = {}; public apiUrl: string; @@ -163,7 +170,7 @@ export class SpecManager { return tagsMap; } - findDerivedDefinitions(defPointer, schema) { + findDerivedDefinitions(defPointer: string, schema): DescendantInfo[] { let definition = schema || this.byPointer(defPointer); if (!definition) throw new Error(`Can't load schema at ${defPointer}`); if (!definition.discriminator && !definition['x-extendedDiscriminator']) return []; @@ -201,12 +208,12 @@ export class SpecManager { } } - res.push({name: derivedName, $ref: `#/definitions/${defName}`}); + res.push({name: derivedName, $ref: `#/definitions/${defName}`, idx: res.length}); } return res; } - getDescendant(descendant, componentSchema) { + getDescendant(descendant:DescendantInfo, componentSchema:any) { let res; if (!getDiscriminator(componentSchema) && componentSchema.allOf) { // discriminator inherited from parents