Warnings on the top of page (fixes #48)

This commit is contained in:
Roman Hotsiy 2016-07-27 18:57:23 +03:00
parent 2872ffbcf9
commit 4b61357be0
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
11 changed files with 115 additions and 14 deletions

View File

@ -87,6 +87,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica
* **number**: A fixed number of pixels to be used as offset
* **selector**: selector of the element to be used for specifying the offset. The distance from the top of the page to the element's bottom will be used as offset.
* **function**: A getter function. Must return a number representing the offset (in pixels).
* `suppress-warnings` - if set, warnings are not rendered at the top of page (they still are logged to the console)
## Advanced usage
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:

View File

@ -4,7 +4,8 @@
<side-menu> </side-menu>
</div>
<div id="api-content">
<api-info> </api-info>
<warnings></warnings>
<api-info></api-info>
<methods-list> </methods-list>
<footer>
<div class="powered-by-badge">

View File

@ -12,11 +12,12 @@ import { ApiInfo } from '../ApiInfo/api-info';
import { ApiLogo } from '../ApiLogo/api-logo';
import { MethodsList } from '../MethodsList/methods-list';
import { SideMenu } from '../SideMenu/side-menu';
import { Warnings } from '../Warnings/warnings';
import { StickySidebar } from '../../shared/components/index';
import {SpecManager} from '../../utils/SpecManager';
import { OptionsService, RedocEventsService, MenuService,
ScrollService, Hash } from '../../services/index';
ScrollService, Hash, WarningsService } from '../../services/index';
var dom = new BrowserDomAdapter();
var _modeLocked = false;
@ -30,10 +31,11 @@ var _modeLocked = false;
ScrollService,
Hash,
MenuService,
WarningsService
],
templateUrl: './redoc.html',
styleUrls: ['./redoc.css'],
directives: [ ApiInfo, ApiLogo, MethodsList, SideMenu, StickySidebar ],
directives: [ ApiInfo, ApiLogo, MethodsList, SideMenu, StickySidebar, Warnings ],
detect: true,
onPushOnly: false
})

View File

@ -0,0 +1,4 @@
<div *ngIf="shown">
<a class="warnings-close" (click)="close()">×</a>
<div class="message" *ngFor="let message of warnings">{{message}}</div>
</div>

View File

@ -0,0 +1,33 @@
:host {
width: 60%;
display: block;
}
.message {
padding: 5px 40px;
background-color: #fcf8e3;
color: #8a6d3b;
&:before {
content: "Warning: ";
font-weight: bold;
}
}
.warnings-close {
font-size: 150%;
color: black;
opacity: 0.4;
float: right;
margin: 5px 20px 0 0;
font-weight: bold;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
p {
display: inline;
}

View File

@ -0,0 +1,31 @@
'use strict';
import { SpecManager, RedocComponent, BaseComponent } from '../base';
import { WarningsService, OptionsService } from '../../services/index';
@RedocComponent({
selector: 'warnings',
styleUrls: ['./warnings.css'],
templateUrl: './warnings.html',
detect: true,
onPushOnly: false
})
export class Warnings extends BaseComponent {
warnings: Array<string>;
shown: boolean;
constructor(specMgr:SpecManager, optionsMgr: OptionsService) {
super(specMgr);
this.shown = !optionsMgr.options.suppressWarnings;
}
init() {
WarningsService.warnings.subscribe((warns) => {
console.log(warns);
this.warnings = warns;
});
}
close() {
this.shown = false;
}
}

View File

@ -7,3 +7,4 @@ export * from './scroll.service';
export * from './hash.service';
export * from './schema-normalizer.service';
export * from './schema-helper.service';
export * from './warnings.service';

View File

@ -9,7 +9,7 @@ const defaults = {
debugMode: false//global && global.redocDebugMode
};
const OPTION_NAMES = new Set(['scrollYOffset', 'disableLazySchemas', 'specUrl']);
const OPTION_NAMES = new Set(['scrollYOffset', 'disableLazySchemas', 'specUrl', 'suppressWarnings']);
@Injectable()
export class OptionsService {
@ -70,5 +70,6 @@ export class OptionsService {
}
if (isString(this._options.disableLazySchemas)) this._options.disableLazySchemas = true;
if (isString(this._options.suppressWarnings)) this._options.suppressWarnings = true;
}
}

View File

@ -2,6 +2,7 @@
import { JsonPointer } from '../utils/JsonPointer';
import { SpecManager } from '../utils/SpecManager';
import {methods as swaggerMethods, keywordTypes} from '../utils/swagger-defs';
import { WarningsService } from './warnings.service';
import slugify from 'slugify';
interface PropertyPreprocessOptions {
@ -32,10 +33,10 @@ const injectors = {
inject: (injectTo, propertySchema, pointer) => {
injectTo.type = SchemaHelper.detectType(propertySchema);
propertySchema.type = injectTo.type;
let message = `No "type" specified at ${pointer}. `;
message += injectTo.type ? `Automatically detected: "${injectTo.type}"` :
`Can't detect automatically`;
console.warn(message);
if (injectTo.type) {
let message = `No "type" specified at "${pointer}". Automatically detected: "${injectTo.type}"`;
WarningsService.warn(message);
}
}
},
general: {

View File

@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { SpecManager } from '../utils/SpecManager';
import { JsonPointer } from '../utils/JsonPointer';
import { defaults } from '../utils/helpers';
import { WarningsService } from './warnings.service';
interface Reference {
$ref: string;
@ -127,20 +128,22 @@ class AllOfMerger {
private static checkCanMerge(subSchema, into) {
// TODO: add support for merge array schemas
if (typeof subSchema !== 'object') {
let errMessage = `Items of allOf should be Object: ${typeof subSchema} found
${subSchema}`;
let errMessage = `Items of allOf should be Object: ${typeof subSchema} found ` +
`${subSchema} at "#${into._pointer}"`;
throw new Error(errMessage);
}
if (into.type && subSchema.type && into.type !== subSchema.type) {
let errMessage = `allOf merging error: schemas with different types can't be merged`;
let errMessage = `allOf merging error: schemas with different types can't be merged: ` +
`"${into.type}" and "${subSchema.type}" at "#${into._pointer}"`;
throw new Error(errMessage);
}
if (into.type === 'array') {
console.warn('allOf: subschemas with type array are not supported yet');
WarningsService.warn('allOf: subschemas with type "array" are not supported yet');
}
// TODO: add check if can be merged correctly (no different properties with the same name)
// TODO: merge properties
}
}
@ -191,8 +194,8 @@ class SchemaDereferencer {
let keysCount = Object.keys(schema).length;
if ( keysCount > 2 || (keysCount === 2 && !schema.description) ) {
console.warn(`other properties defined at the same level as $ref at '${pointer}'.
They are IGNORRED according to JsonSchema spec`);
WarningsService.warn(`Other properties are defined at the same level as $ref at "#${pointer}". ` +
'They are IGNORRED according to the JsonSchema spec');
resolved.description = resolved.description || schema.description;
}

View File

@ -0,0 +1,23 @@
'use strict';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class WarningsService {
private static _warnings: Array<string> = [];
private static _warningsObs = new Subject<Array<string>>();
static get warnings() {
return WarningsService._warningsObs;
}
static hasWarnings() {
return !!WarningsService._warnings.length;
}
static warn(message:string) {
WarningsService._warnings.push(message);
WarningsService._warningsObs.next(WarningsService._warnings);
console.warn(message);
}
}