diff --git a/lib/components/Method/method.html b/lib/components/Method/method.html
index e677c448..1a428a93 100644
--- a/lib/components/Method/method.html
+++ b/lib/components/Method/method.html
@@ -1,7 +1,7 @@
{{data.httpMethod}}
diff --git a/lib/components/Method/method.js b/lib/components/Method/method.js
index 13aa8178..3ab6f066 100644
--- a/lib/components/Method/method.js
+++ b/lib/components/Method/method.js
@@ -28,6 +28,11 @@ export default class Method extends BaseComponent {
this.data.methodInfo = this.componentSchema;
this.data.methodInfo.tags = this.filterMainTags(this.data.methodInfo.tags);
this.data.bodyParam = this.findBodyParam();
+ if (this.componentSchema.operationId) {
+ this.data.methodAnchor = 'operation/' + this.componentSchema.operationId;
+ } else {
+ this.data.methodAnchor = 'tag/' + this.tag + this.pointer;
+ }
}
filterMainTags(tags) {
diff --git a/lib/components/MethodsList/methods-list.html b/lib/components/MethodsList/methods-list.html
index 4532d941..10e0ccf6 100644
--- a/lib/components/MethodsList/methods-list.html
+++ b/lib/components/MethodsList/methods-list.html
@@ -1,10 +1,10 @@
+ [attr.tag]="method.tag" [tag]="method.tag" [attr.operation-id]="method.operationId">
diff --git a/lib/components/SideMenu/side-menu.js b/lib/components/SideMenu/side-menu.js
index 614b70bc..fe050c8f 100644
--- a/lib/components/SideMenu/side-menu.js
+++ b/lib/components/SideMenu/side-menu.js
@@ -3,7 +3,8 @@
import {RedocComponent, BaseComponent} from '../base';
import {redocEvents} from '../../events';
-import {NgZone, ChangeDetectionStrategy, ElementRef} from 'angular2/core';
+import {NgZone, ChangeDetectionStrategy, ElementRef, forwardRef} from 'angular2/core';
+import Redoc from '../Redoc/redoc';
import {document} from 'angular2/src/facade/browser';
import {BrowserDomAdapter} from 'angular2/platform/browser';
import {global} from 'angular2/src/facade/lang';
@@ -60,10 +61,18 @@ export default class SideMenu extends BaseComponent {
let hash = this.adapter.getLocation().hash;
if (!hash) return;
+ let el;
hash = hash.substr(1);
- let tag = hash.split('/')[0];
- let ptr = hash.substr(tag.length);
- let el = this.getMethodEl(ptr, tag);
+ let namespace = hash.split('/')[0];
+ let ptr = hash.substr(namespace.length + 1);
+ if (namespace === 'operation') {
+ el = this.getMethodElByOperId(ptr);
+ } else if (namespace === 'tag') {
+ let tag = ptr.split('/')[0];
+ ptr = ptr.substr(tag.length);
+ el = this.getMethodElByPtr(ptr, tag);
+ }
+
if (el) this.scrollTo(el);
if (evt) evt.preventDefault();
}
@@ -170,13 +179,18 @@ export default class SideMenu extends BaseComponent {
return (methodIdx === 0 && catIdx === 0);
}
- getMethodEl(ptr, tag) {
+ getMethodElByPtr(ptr, tag) {
let selector = ptr ? `[pointer="${ptr}"][tag="${tag}"]` : `[tag="${tag}"]`;
return document.querySelector(selector);
}
+ getMethodElByOperId(operationId) {
+ let selector =`[operation-id="${operationId}"]`;
+ return document.querySelector(selector);
+ }
+
getCurrentMethodEl() {
- return this.getMethodEl(this.activeMethodPtr, this.data.menu[this.activeCatIdx].name);
+ return this.getMethodElByPtr(this.activeMethodPtr, this.data.menu[this.activeCatIdx].name);
}
/* returns 1 if element if above the view, 0 if in view and -1 below the view */
@@ -240,4 +254,5 @@ export default class SideMenu extends BaseComponent {
this.changeActive(CHANGE.INITIAL);
}
}
-SideMenu.parameters = SideMenu.parameters.concat([[ElementRef], [BrowserDomAdapter], [NgZone]]);
+SideMenu.parameters = SideMenu.parameters.concat([[ElementRef],
+ [BrowserDomAdapter], [NgZone], [forwardRef(() => Redoc)] ]);
diff --git a/lib/components/SideMenu/side-menu.spec.js b/lib/components/SideMenu/side-menu.spec.js
index 8b3da94f..9f154f00 100644
--- a/lib/components/SideMenu/side-menu.spec.js
+++ b/lib/components/SideMenu/side-menu.spec.js
@@ -75,8 +75,22 @@ describe('Redoc components', () => {
});
});
- it('should scroll to method when location hash is present', (done) => {
- let hash = '#pet/paths/~1pet~1findByStatus/get';
+ it('should scroll to method when location hash is present [jp]', (done) => {
+ let hash = '#tag/pet/paths/~1pet~1findByStatus/get';
+ spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash});
+ spyOn(component, 'hashScroll').and.callThrough();
+ spyOn(window, 'scrollTo').and.stub();
+ redocEvents.bootstrapped.next();
+ setTimeout(() => {
+ expect(component.hashScroll).toHaveBeenCalled();
+ let scrollY = window.scrollTo.calls.argsFor(0)[1];
+ expect(scrollY).toBeGreaterThan(0);
+ done();
+ });
+ });
+
+ it('should scroll to method when location hash is present [operation]', (done) => {
+ let hash = '#operation/getPetById';
spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash});
spyOn(component, 'hashScroll').and.callThrough();
spyOn(window, 'scrollTo').and.stub();
@@ -121,8 +135,20 @@ describe('Redoc components', () => {
expect(component.data).not.toBeNull();
});
- it('should scroll to method when location hash is present', (done) => {
- let hash = '#pet/paths/~1pet~1findByStatus/get';
+ it('should scroll to method when location hash is present [jp]', (done) => {
+ let hash = '#tag/pet/paths/~1pet~1findByStatus/get';
+ spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash});
+ spyOn(component, 'hashScroll').and.callThrough();
+ redocEvents.bootstrapped.next();
+ setTimeout(() => {
+ expect(component.hashScroll).toHaveBeenCalled();
+ expect(component.scrollParent.scrollTop).toBeGreaterThan(0);
+ done();
+ });
+ });
+
+ it('should scroll to method when location hash is present [operation]', (done) => {
+ let hash = '#operation/getPetById';
spyOn(component.adapter, 'getLocation').and.returnValue({hash: hash});
spyOn(component, 'hashScroll').and.callThrough();
redocEvents.bootstrapped.next();
diff --git a/lib/utils/SchemaManager.js b/lib/utils/SchemaManager.js
index 254fd88d..2c11af6a 100644
--- a/lib/utils/SchemaManager.js
+++ b/lib/utils/SchemaManager.js
@@ -150,7 +150,11 @@ export default class SchemaManager {
}
if (tagDetails['x-traitTag']) continue;
if (!tagDetails.methods) tagDetails.methods = [];
- tagDetails.methods.push({pointer: methodPointer, summary: methodSummary});
+ tagDetails.methods.push({
+ pointer: methodPointer,
+ summary: methodSummary,
+ operationId: methodInfo.operationId
+ });
}
}
}
diff --git a/tests/unit/SchemaManager.spec.js b/tests/unit/SchemaManager.spec.js
index 0a2bfbf8..1ec4ec87 100644
--- a/tests/unit/SchemaManager.spec.js
+++ b/tests/unit/SchemaManager.spec.js
@@ -165,7 +165,7 @@ describe('Utils', () => {
info.should.be.an.Object();
info.methods.should.be.an.Array();
for (let methodInfo of info.methods) {
- methodInfo.should.have.keys('pointer', 'summary');
+ methodInfo.should.have.properties(['pointer', 'summary']);
let methSchema = schemaMgr.byPointer(methodInfo.pointer);
expect(methSchema).not.toBeNull();
if (methSchema.summary) {