mirror of
https://github.com/Redocly/redoc.git
synced 2025-01-31 10:04:08 +03:00
Refactor menu generation + handle methods without tags
This commit is contained in:
parent
4a475677f7
commit
b22b8d2122
|
@ -1,7 +1,7 @@
|
|||
<div class="method">
|
||||
<div class="method-content">
|
||||
<h2 class="method-header sharable-header">
|
||||
<a class="share-link" href="#{{data.methodAnchor}}"></a>{{data.methodInfo.summary}}
|
||||
<a class="share-link" href="#{{data.methodAnchor}}"></a>{{data.summary}}
|
||||
</h2>
|
||||
<div class="method-tags" *ngIf="data.methodInfo.tags.length">
|
||||
<a *ngFor="let tag of data.methodInfo.tags" attr.href="#{{tag}}"> {{tag}} </a>
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ResponsesList } from '../ResponsesList/responses-list';
|
|||
import { ResponsesSamples } from '../ResponsesSamples/responses-samples';
|
||||
import { SchemaSample } from '../SchemaSample/schema-sample';
|
||||
import { RequestSamples } from '../RequestSamples/request-samples';
|
||||
import { SchemaHelper } from '../../services/schema-helper.service';
|
||||
|
||||
@RedocComponent({
|
||||
selector: 'method',
|
||||
|
@ -31,6 +32,7 @@ export class Method extends BaseComponent {
|
|||
this.data.methodInfo = this.componentSchema;
|
||||
this.data.methodInfo.tags = this.filterMainTags(this.data.methodInfo.tags);
|
||||
this.data.bodyParam = this.findBodyParam();
|
||||
this.data.summary = SchemaHelper.methodSummary(this.componentSchema);
|
||||
if (this.componentSchema.operationId) {
|
||||
this.data.methodAnchor = 'operation/' + encodeURIComponent(this.componentSchema.operationId);
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="methods">
|
||||
<div class="tag" *ngFor="let tag of data.tags;trackBy:trackByTagName">
|
||||
<div class="tag-info" [attr.tag]="tag.name">
|
||||
<div class="tag-info" [attr.tag]="tag.name" *ngIf="!tag.empty">
|
||||
<h1 class="sharable-header"> <a class="share-link" href="#tag/{{tag.name | encodeURIComponent}}"></a>{{tag.name}} </h1>
|
||||
<p *ngIf="tag.description" [innerHtml]="tag.description | marked"> </p>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { forwardRef } from '@angular/core';
|
|||
import { RedocComponent, BaseComponent, SpecManager } from '../base';
|
||||
import { Method } from '../Method/method';
|
||||
import { EncodeURIComponentPipe } from '../../utils/pipes';
|
||||
import { SchemaHelper } from '../../services/index';
|
||||
|
||||
@RedocComponent({
|
||||
selector: 'methods-list',
|
||||
|
@ -24,21 +25,14 @@ export class MethodsList extends BaseComponent {
|
|||
// follow SwaggerUI behavior for cases when one method has more than one tag:
|
||||
// duplicate methods
|
||||
|
||||
let menuStructure = this.specMgr.buildMenuTree();
|
||||
let tags = Array.from<any>(menuStructure.entries())
|
||||
.map((entry) => {
|
||||
let [tag, {description, methods}] = entry;
|
||||
// inject tag name into method info
|
||||
methods = methods || [];
|
||||
methods.forEach(method => {
|
||||
method.tag = tag;
|
||||
});
|
||||
return {
|
||||
name: tag,
|
||||
description: description,
|
||||
methods: methods
|
||||
};
|
||||
let tags = SchemaHelper.buildMenuTree(this.specMgr.schema);
|
||||
tags.forEach(tagInfo => {
|
||||
// inject tag name into method info
|
||||
tagInfo.methods = tagInfo.methods || [];
|
||||
tagInfo.methods.forEach(method => {
|
||||
method.tag = name;
|
||||
});
|
||||
});
|
||||
this.data.tags = tags;
|
||||
// TODO: check $ref field
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
<h5 class="menu-header"> API reference </h5>
|
||||
<div *ngFor="let cat of data.menu; let idx = index" class="menu-cat">
|
||||
|
||||
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [ngClass]="{active: cat.active}"> {{cat.name}}</label>
|
||||
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [hidden]="cat.empty"
|
||||
[ngClass]="{active: cat.active}"> {{cat.name}}</label>
|
||||
<ul class="menu-subitems" @itemAnimation="cat.active ? 'expanded' : 'collapsed'">
|
||||
<li *ngFor="let method of cat.methods; let methIdx = index"
|
||||
[ngClass]="{active: method.active}"
|
||||
|
|
|
@ -29,6 +29,10 @@ $mobile-menu-compact-breakpoint: 550px;
|
|||
color: $primary-color;
|
||||
background-color: $side-menu-active-bg-color;
|
||||
}
|
||||
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-subitems {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Injectable, EventEmitter } from '@angular/core';
|
|||
import { ScrollService, INVIEW_POSITION } from './scroll.service';
|
||||
import { Hash } from './hash.service';
|
||||
import { SpecManager } from '../utils/SpecManager';
|
||||
import { SchemaHelper } from './schema-helper.service';
|
||||
|
||||
const CHANGE = {
|
||||
NEXT : 1,
|
||||
|
@ -21,9 +22,7 @@ export class MenuService {
|
|||
|
||||
constructor(private hash:Hash, private scrollService:ScrollService, specMgr:SpecManager) {
|
||||
this.hash = hash;
|
||||
this.categories = Array.from(specMgr.buildMenuTree().entries()).map(
|
||||
el => ({name: el[0], description: el[1].description, methods: el[1].methods})
|
||||
);
|
||||
this.categories = SchemaHelper.buildMenuTree(specMgr.schema);
|
||||
|
||||
scrollService.scroll.subscribe((evt) => {
|
||||
this.scrollUpdate(evt.isScrolledDown);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
import { JsonPointer } from '../utils/JsonPointer';
|
||||
import { SpecManager } from '../utils/SpecManager';
|
||||
import {methods as swaggerMethods} from '../utils/swagger-defs';
|
||||
|
||||
interface PropertyPreprocessOptions {
|
||||
childFor: string;
|
||||
|
@ -218,4 +219,57 @@ export class SchemaHelper {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static methodSummary(method) {
|
||||
return method.summary || method.operationId || method.description.substring(0, 50);
|
||||
}
|
||||
|
||||
static buildMenuTree(schema) {
|
||||
let tag2MethodMapping = {};
|
||||
|
||||
let definedTags = schema.tags || [];
|
||||
// add tags into map to preserve order
|
||||
for (let tag of definedTags) {
|
||||
tag2MethodMapping[tag.name] = {
|
||||
'description': tag.description,
|
||||
'x-traitTag': tag['x-traitTag'],
|
||||
'methods': []
|
||||
};
|
||||
}
|
||||
|
||||
let paths = schema.paths;
|
||||
for (let path of Object.keys(paths)) {
|
||||
let methods = Object.keys(paths[path]).filter((k) => swaggerMethods.has(k));
|
||||
for (let method of methods) {
|
||||
let methodInfo = paths[path][method];
|
||||
let tags = methodInfo.tags;
|
||||
|
||||
//TODO: mb need to do something cleverer
|
||||
if (!tags || !tags.length) {
|
||||
tags = [''];
|
||||
}
|
||||
let methodPointer = JsonPointer.compile(['paths', path, method]);
|
||||
let methodSummary = SchemaHelper.methodSummary(methodInfo);
|
||||
for (let tag of tags) {
|
||||
let tagDetails = tag2MethodMapping[tag];
|
||||
if (!tagDetails) {
|
||||
tagDetails = {
|
||||
name: tag,
|
||||
empty: !tag
|
||||
};
|
||||
tag2MethodMapping[tag] = tagDetails;
|
||||
}
|
||||
if (tagDetails['x-traitTag']) continue;
|
||||
if (!tagDetails.methods) tagDetails.methods = [];
|
||||
tagDetails.methods.push({
|
||||
pointer: methodPointer,
|
||||
summary: methodSummary,
|
||||
operationId: methodInfo.operationId,
|
||||
tag: tag
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return Object.keys(tag2MethodMapping).map(tag => tag2MethodMapping[tag]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import JsonSchemaRefParser from 'json-schema-ref-parser';
|
||||
import JsonPointer from './JsonPointer';
|
||||
import {methods as swaggerMethods} from './swagger-defs';
|
||||
|
||||
export class SpecManager {
|
||||
public _schema:any = {};
|
||||
|
@ -114,52 +113,6 @@ export class SpecManager {
|
|||
return tagsMap;
|
||||
}
|
||||
|
||||
/* returns ES6 Map */
|
||||
buildMenuTree():Map<string, any> {
|
||||
let tag2MethodMapping = new Map();
|
||||
|
||||
let definedTags = this._schema.tags || [];
|
||||
// add tags into map to preserve order
|
||||
for (let tag of definedTags) {
|
||||
tag2MethodMapping.set(tag.name, {
|
||||
'description': tag.description,
|
||||
'x-traitTag': tag['x-traitTag'],
|
||||
'methods': []
|
||||
});
|
||||
}
|
||||
|
||||
let paths = this._schema.paths;
|
||||
for (let path of Object.keys(paths)) {
|
||||
let methods = Object.keys(paths[path]).filter((k) => swaggerMethods.has(k));
|
||||
for (let method of methods) {
|
||||
let methodInfo = paths[path][method];
|
||||
let tags = methodInfo.tags;
|
||||
|
||||
//TODO: mb need to do something cleverer
|
||||
if (!tags || !tags.length) {
|
||||
tags = ['[Other]'];
|
||||
}
|
||||
let methodPointer = JsonPointer.compile(['paths', path, method]);
|
||||
let methodSummary = methodInfo.summary || methodInfo.operationId;
|
||||
for (let tag of tags) {
|
||||
let tagDetails = tag2MethodMapping.get(tag);
|
||||
if (!tagDetails) {
|
||||
tagDetails = {};
|
||||
tag2MethodMapping.set(tag, tagDetails);
|
||||
}
|
||||
if (tagDetails['x-traitTag']) continue;
|
||||
if (!tagDetails.methods) tagDetails.methods = [];
|
||||
tagDetails.methods.push({
|
||||
pointer: methodPointer,
|
||||
summary: methodSummary,
|
||||
operationId: methodInfo.operationId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag2MethodMapping;
|
||||
}
|
||||
|
||||
findDerivedDefinitions(defPointer) {
|
||||
let definition = this.byPointer(defPointer);
|
||||
if (!definition) throw new Error(`Can't load schema at ${defPointer}`);
|
||||
|
|
Loading…
Reference in New Issue
Block a user