Skip to content

Commit

Permalink
feat: Add support for x-servers
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanHotsiy committed Feb 25, 2017
1 parent dcb97a5 commit fd49082
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 79 deletions.
5 changes: 5 additions & 0 deletions demo/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ securityDefinitions:
type: apiKey
name: api_key
in: header
x-servers:
- url: //petstore.swagger.io/v2
description: Default server
- url: //petstore.swagger.io/sandbox
description: Sandbox server
paths:
/pet:
post:
Expand Down
17 changes: 17 additions & 0 deletions lib/components/EndpointLink/endpoint-link.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="method-endpoint" (click)="handleClick()">
<h5 class="http-verb" [ngClass]="verb">{{verb}}</h5>
<span><!--
--><span class="method-api-url-path">{{path}}</span><!--
--></span>
<svg class="expand-icon" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 24 24" xml:space="preserve">
<polygon fill="white" points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "/>
</svg>
</div>
<div class="servers-overlay" [@overlayExpand]="expanded ? 'expanded' : 'collapsed'">
<div *ngFor="let server of servers" class="server-item">
<div class="description" [innerHtml]="server.description | marked"></div>
<div select-on-click class="url">
<span class="method-api-url"> {{server.url}}</span>{{path}}
</div>
</div>
</div>
101 changes: 101 additions & 0 deletions lib/components/EndpointLink/endpoint-link.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
@import '../../shared/styles/variables';

:host {
display: block;
position: relative;
cursor: pointer;
}

.method-endpoint {
padding: 10px 20px;
border-radius: $border-radius*2;
background-color: darken($black, 2%);
display: block;
font-weight: $light;
white-space: nowrap;
overflow-x: auto;
border: 1px solid transparent;
}

.method-endpoint > .method-params-subheader {
padding-top: 1px;
padding-bottom: 0;
margin: 0;
font-size: 12/14em;
color: $black;
vertical-align: middle;
display: inline-block;
border-radius: $border-radius;
}

.method-api-url {
color: rgba($black, .8);
&-path {
font-family: $headers-font, $headers-font-family;
position: relative;
top: 1px;
color: #ffffff;
margin-left: 10px;
}
}

.http-verb {
color: $black;
background: #ffffff;
padding: 3px 10px;
text-transform: uppercase;
display: inline-block;
margin: 0;
}

.servers-overlay {
position: absolute;
width: 100%;
z-index: 100;
background: $side-bar-bg-color;
color: $black;
box-sizing: border-box;
box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.33);
overflow: hidden;
border-bottom-left-radius: $border-radius*2;
border-bottom-right-radius: $border-radius*2;
}

.server-item {
padding: 10px;
//margin-bottom: 10px;

& > .url {
padding: 5px;
border: 1px solid $border-color;
background: $background-color;
word-break: break-all;
}

&:last-child {
margin-bottom: 0;
}
}

.expand-icon {
height: 20px;
width: 20px;
display: inline-block;
float: right;
margin-top: 2px;
background: darken($black, 2%);
transform: rotateZ(0);
transition: all 0.2s ease;
}

:host.expanded {
> .method-endpoint {
border-color: $side-bar-bg-color;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}

.expand-icon {
transform: rotateZ(180deg);
}
}
79 changes: 79 additions & 0 deletions lib/components/EndpointLink/endpoint-link.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';

import { Component } from '@angular/core';
import {
inject,
async,
TestBed
} from '@angular/core/testing';

import { getChildDebugElement } from '../../../tests/helpers';

import { EndpointLink } from './endpoint-link';
import { SpecManager } from '../../utils/spec-manager';

describe('Redoc components', () => {
beforeEach(() => {
TestBed.configureTestingModule({ declarations: [ TestAppComponent ] });
});
describe('EndpointLink Component', () => {
let builder;
let component: EndpointLink;
let specMgr: SpecManager;

beforeEach(async(inject([SpecManager], (_specMgr) => {
specMgr = _specMgr;
})));

beforeEach(() => {
specMgr.apiUrl = 'http://test.com/v1';
specMgr._schema = {
info: {},
host: 'petstore.swagger.io',
baseName: '/v2',
schemes: ['https', 'http'],
'x-servers': [
{
url: '//test.com/v2'
},
{
url: 'ws://test.com/v3',
description: 'test'
}
]
};
specMgr.init();

component = new EndpointLink(specMgr);
});

it('should replace // with appropriate protocol', () => {
component.ngOnInit();
component.servers[0].url.should.be.equal('https://test.com/v2');
});


it('should preserve other protocols', () => {
component.ngOnInit();
component.servers[1].url.should.be.equal('ws://test.com/v3');
});

it('should fallback to host + basePath + schemas if no x-servers', () => {
specMgr._schema['x-servers'] = null;
specMgr.init();
component.ngOnInit();
component.servers.should.be.lengthOf(1);
component.servers[0].url.should.be.equal('https://petstore.swagger.io');
});
});
});


/** Test component that contains a Method. */
@Component({
selector: 'test-app',
template:
`<method pointer='#/paths/~1user~1{username}/put'></method>`
})
class TestAppComponent {
}
69 changes: 69 additions & 0 deletions lib/components/EndpointLink/endpoint-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict';
import { Component, ChangeDetectionStrategy, Input, OnInit, HostListener, HostBinding} from '@angular/core';
import { BaseComponent, SpecManager } from '../base';
import { trigger, state, animate, transition, style } from '@angular/core';

export interface ServerInfo {
description: string;
url: string;
}

@Component({
selector: 'endpoint-link',
styleUrls: ['./endpoint-link.css'],
templateUrl: './endpoint-link.html',
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('overlayExpand', [
state('collapsed, void',
style({ height: '0px' })),
state('expanded',
style({ height: '*' })),
transition('collapsed <=> expanded', [
animate('200ms ease')
])
])
]
})
export class EndpointLink implements OnInit {
@Input() path:string;
@Input() verb:string;

apiUrl: string;
servers: ServerInfo[];
@HostBinding('class.expanded') expanded: boolean = false;

// @HostListener('click')
handleClick() {
this.expanded = !this.expanded;
}

constructor(public specMgr:SpecManager) {
this.expanded = false;
}

init() {
let servers:ServerInfo[] = this.specMgr.schema['x-servers'];
if (servers) {
this.servers = servers.map(({url, description}) => ({
description,
url: url.startsWith('//') ? `${this.specMgr.apiProtocol}:${url}` : url
}));
} else {
this.servers = [
{
description: 'Server URL',
url: this.getBaseUrl()
}
];
}
}

getBaseUrl():string {
return this.specMgr.apiUrl;
}

ngOnInit() {
this.init();
}
}
7 changes: 1 addition & 6 deletions lib/components/Method/method.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ <h2 class="method-header sharable-header">
<div class="method-samples">
<h4 class="method-params-subheader">Definition</h4>

<div class="method-endpoint">
<h5 class="http-method" [ngClass]="method.httpMethod">{{method.httpMethod}}</h5>
<span select-on-click><!--
--><span class="method-api-url">{{method.apiUrl}}</span><span class="method-api-url-path">{{method.path}}</span><!--
--></span>
</div>
<endpoint-link [verb]="method.verb" [path]="method.path"> </endpoint-link>

<div>
<request-samples [pointer]="pointer" [schemaPointer]="method.bodyParam?._pointer">
Expand Down
48 changes: 0 additions & 48 deletions lib/components/Method/method.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,45 +18,6 @@
margin-bottom: calc(1em - 6px);
}

.method-endpoint {
//margin: 0 0 2px 0;
padding: 10px 20px;
border-radius: $border-radius*2;
background-color: darken($black, 2%);
display: block;
font-weight: $light;
white-space: nowrap;
overflow-x: auto;
}

.method-endpoint > .method-params-subheader {
padding-top: 1px;
padding-bottom: 0;
margin: 0;
font-size: 12/14em;
color: $black;
vertical-align: middle;
display: inline-block;
border-radius: $border-radius;
}

.method-api-url {
color: rgba(#ffffff, .6);
margin-left: 10px;
margin-top: 2px;
position: relative;
top: 1px;
font-family: $headers-font, $headers-font-family;
font-size: 0.929em;

&-path {
font-family: $headers-font, $headers-font-family;
position: relative;
top: 1px;
color: #ffffff;
}
}

.method-tags {
margin-top: 20px;

Expand Down Expand Up @@ -121,15 +82,6 @@
margin: 0;
}

.http-method {
color: $black;
background: #ffffff;
padding: 3px 10px;
text-transform: uppercase;
display: inline-block;
margin: 0;
}

[select-on-click] {
cursor: pointer;
}
Expand Down
5 changes: 2 additions & 3 deletions lib/components/Method/method.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Redoc components', () => {
});
describe('Method Component', () => {
let builder;
let component;
let component: Method;
let specMgr;

beforeEach(async(inject([SpecManager, LazyTasksService], (_specMgr, lazyTasks) => {
Expand All @@ -43,8 +43,7 @@ describe('Redoc components', () => {
});

it('should init basic component data', () => {
component.method.apiUrl.should.be.equal('http://petstore.swagger.io/v2');
component.method.httpMethod.should.be.equal('put');
component.method.verb.should.be.equal('put');
component.method.path.should.be.equal('/user/{username}');
});

Expand Down

0 comments on commit fd49082

Please sign in to comment.