Skip to content
This repository was archived by the owner on Oct 20, 2022. It is now read-only.

Commit 945639a

Browse files
committed
enable permalinks to open a specific operation
1 parent c2f73f6 commit 945639a

File tree

2 files changed

+180
-157
lines changed

2 files changed

+180
-157
lines changed

src/scripts/swagger-ui.js

Lines changed: 174 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -22,189 +22,211 @@ angular
2222
}
2323
};
2424
})
25-
.controller('swaggerUiController', ['$scope', '$http', '$sce', 'swaggerModel', 'swaggerClient', function($scope, $http, $sce, swaggerModel, swaggerClient) {
25+
.controller('swaggerUiController', ['$scope', '$http', '$sce', '$location', 'swaggerModel', 'swaggerClient',
26+
function($scope, $http, $sce, $location, swaggerModel, swaggerClient) {
2627

27-
var swagger;
28+
var swagger;
2829

29-
// WARNING only Swagger 2.0 is supported (@see https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md)
30-
// WARNING XML is not supported
31-
// WARNING authentication is not implemented, please use 'api-explorer-transform' directive's param to customize API calls
30+
// WARNING only Swagger 2.0 is supported (@see https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md)
31+
// WARNING application/xml is not supported
32+
// WARNING authentication is not implemented, please use 'api-explorer-transform' directive's param to customize API calls
3233

33-
//TODO find a way to implement permalinks !!
34-
35-
$scope.$watch('url', function(url) {
36-
//reset
37-
$scope.infos = {};
38-
$scope.resources = [];
39-
$scope.form = {};
40-
if (url && url !== '') {
41-
// load Swagger description
34+
function get(url, callback) {
35+
$scope.loading = true;
4236
var notifyError = typeof $scope.errorHandler === 'function';
4337
$http.get(url)
4438
.success(function(data /*, status, headers, config*/ ) {
45-
swagger = data;
46-
if (data.swagger === '2.0') {
47-
parseV2(swagger);
48-
} else if (notifyError) {
49-
$scope.errorHandler('unsupported swagger version', '415');
50-
}
39+
$scope.loading = false;
40+
callback(data);
5141
})
5242
.error(function(data, status /*, headers, config*/ ) {
43+
$scope.loading = false;
5344
if (notifyError) {
5445
$scope.errorHandler(data, status);
5546
}
5647
});
5748
}
58-
});
5949

60-
/**
61-
* parses swagger description to ease HTML generation
62-
*/
63-
function parseV2() {
64-
$scope.infos = swagger.info;
65-
$scope.infos.description = $sce.trustAsHtml($scope.infos.description);
50+
$scope.$watch('url', function(url) {
51+
//reset
52+
$scope.infos = {};
53+
$scope.resources = [];
54+
$scope.form = {};
55+
if (url && url !== '') {
56+
// load Swagger description
57+
var notifyError = typeof $scope.errorHandler === 'function';
58+
get(url, function(data) {
59+
swagger = data;
60+
if (data.swagger === '2.0') {
61+
parseV2(swagger);
62+
} else if (notifyError) {
63+
$scope.errorHandler('unsupported swagger version', '415');
64+
}
65+
});
66+
}
67+
});
68+
69+
/**
70+
* parses swagger description to ease HTML generation
71+
*/
72+
function parseV2() {
73+
$scope.infos = swagger.info;
74+
$scope.infos.description = $sce.trustAsHtml($scope.infos.description);
6675

67-
var operationId = 0,
68-
paramId = 0,
69-
map = {},
70-
form = {},
71-
resources = [];
76+
var operationId = 0,
77+
paramId = 0,
78+
map = {},
79+
form = {},
80+
resources = [],
81+
openPath = $location.search().open;
7282

73-
// parse resources
74-
if (!swagger.tags) {
75-
resources.push({
76-
name: 'default',
77-
open: true
78-
});
79-
map['default'] = 0;
80-
} else {
81-
for (var i = 0, l = swagger.tags.length; i < l; i++) {
82-
var tag = swagger.tags[i];
83-
resources.push(tag);
84-
map[tag.name] = i;
83+
// parse resources
84+
if (!swagger.tags) {
85+
resources.push({
86+
name: 'default',
87+
open: true
88+
});
89+
map['default'] = 0;
90+
} else {
91+
for (var i = 0, l = swagger.tags.length; i < l; i++) {
92+
var tag = swagger.tags[i];
93+
resources.push(tag);
94+
map[tag.name] = i;
95+
}
8596
}
86-
}
87-
// parse operations
88-
for (var path in swagger.paths) {
89-
for (var httpMethod in swagger.paths[path]) {
90-
var operation = swagger.paths[path][httpMethod];
91-
//TODO manage 'deprecated' operations ?
92-
operation.id = operationId;
93-
form[operationId] = {
94-
contentType: operation.consumes && operation.consumes.length === 1 ? operation.consumes[0] : 'application/json',
95-
responseType: 'application/json'
96-
};
97-
operation.httpMethod = httpMethod;
98-
operation.path = path;
99-
// parse operation's parameters
100-
for (var j = 0, params = operation.parameters || [], k = params.length; j < k; j++) {
101-
//TODO manage 'collectionFormat' (csv, multi etc.) ?
102-
//TODO manage constraints (pattern, min, max etc.) ?
103-
var param = params[j];
104-
param.id = paramId;
105-
param.type = swaggerModel.getType(param);
106-
param.subtype = param.type === 'array' && param.enum ? 'enum' : param.type;
107-
// put param into form scope
108-
form[operationId][param.name] = param.default || '';
109-
if (param.schema) {
110-
param.schema.display = 1; // display schema
111-
param.schema.json = swaggerModel.generateSampleJson(swagger, param.schema);
112-
param.schema.model = $sce.trustAsHtml(swaggerModel.generateModel(swagger, param.schema));
113-
}
114-
if (param.in === 'body') {
115-
operation.consumes = operation.consumes || ['application/json'];
97+
// parse operations
98+
for (var path in swagger.paths) {
99+
for (var httpMethod in swagger.paths[path]) {
100+
var operation = swagger.paths[path][httpMethod];
101+
//TODO manage 'deprecated' operations ?
102+
operation.id = operationId;
103+
form[operationId] = {
104+
contentType: operation.consumes && operation.consumes.length === 1 ? operation.consumes[0] : 'application/json',
105+
responseType: 'application/json'
106+
};
107+
operation.httpMethod = httpMethod;
108+
operation.path = path;
109+
// parse operation's parameters
110+
for (var j = 0, params = operation.parameters || [], k = params.length; j < k; j++) {
111+
//TODO manage 'collectionFormat' (csv, multi etc.) ?
112+
//TODO manage constraints (pattern, min, max etc.) ?
113+
var param = params[j];
114+
param.id = paramId;
115+
param.type = swaggerModel.getType(param);
116+
param.subtype = param.type === 'array' && param.enum ? 'enum' : param.type;
117+
// put param into form scope
118+
form[operationId][param.name] = param.default || '';
119+
if (param.schema) {
120+
param.schema.display = 1; // display schema
121+
param.schema.json = swaggerModel.generateSampleJson(swagger, param.schema);
122+
param.schema.model = $sce.trustAsHtml(swaggerModel.generateModel(swagger, param.schema));
123+
}
124+
if (param.in === 'body') {
125+
operation.consumes = operation.consumes || ['application/json'];
126+
}
127+
paramId++;
116128
}
117-
paramId++;
118-
}
119-
// parse operation's responses
120-
if (operation.responses) {
121-
for (var code in operation.responses) {
122-
//TODO manage headers, examples ?
123-
var resp = operation.responses[code];
124-
resp.description = $sce.trustAsHtml(resp.description);
125-
if (resp.schema) {
126-
resp.schema.json = swaggerModel.generateSampleJson(swagger, resp.schema);
127-
if (resp.schema.type === 'object' || resp.schema.type === 'array' || resp.schema.$ref) {
128-
resp.display = 1; // display schema
129-
resp.schema.model = $sce.trustAsHtml(swaggerModel.generateModel(swagger, resp.schema));
130-
} else if (resp.schema.type === 'string') {
131-
delete resp.schema;
132-
}
133-
if (code === '200' || code === '201') {
134-
operation.responseClass = resp;
135-
operation.responseClass.display = 1;
136-
operation.responseClass.status = code;
137-
delete operation.responses[code];
129+
// parse operation's responses
130+
if (operation.responses) {
131+
for (var code in operation.responses) {
132+
//TODO manage headers, examples ?
133+
var resp = operation.responses[code];
134+
resp.description = $sce.trustAsHtml(resp.description);
135+
if (resp.schema) {
136+
resp.schema.json = swaggerModel.generateSampleJson(swagger, resp.schema);
137+
if (resp.schema.type === 'object' || resp.schema.type === 'array' || resp.schema.$ref) {
138+
resp.display = 1; // display schema
139+
resp.schema.model = $sce.trustAsHtml(swaggerModel.generateModel(swagger, resp.schema));
140+
} else if (resp.schema.type === 'string') {
141+
delete resp.schema;
142+
}
143+
if (code === '200' || code === '201') {
144+
operation.responseClass = resp;
145+
operation.responseClass.display = 1;
146+
operation.responseClass.status = code;
147+
delete operation.responses[code];
148+
} else {
149+
operation.hasResponses = true;
150+
}
138151
} else {
139152
operation.hasResponses = true;
140153
}
141-
} else {
142-
operation.hasResponses = true;
143154
}
144155
}
156+
operation.tags = operation.tags || ['default'];
157+
// map operation to resource
158+
var tag = operation.tags[0];
159+
if (typeof map[tag] === 'undefined') {
160+
map[tag] = resources.length;
161+
resources.push({
162+
name: tag
163+
});
164+
}
165+
var res = resources[map[operation.tags[0]]];
166+
operation.open = openPath === operation.operationId || openPath === res.name + '*';
167+
res.operations = res.operations || [];
168+
res.operations.push(operation);
169+
if (operation.open) {
170+
res.open = true;
171+
}
172+
operationId++;
145173
}
146-
operation.tags = operation.tags || ['default'];
147-
// map operation to resource
148-
var tag = operation.tags[0];
149-
if (typeof map[tag] === 'undefined') {
150-
map[tag] = resources.length;
151-
resources.push({
152-
name: tag
153-
});
154-
}
155-
var res = resources[map[operation.tags[0]]]; //TODO make sure there is only one defined !
156-
res.operations = res.operations || [];
157-
res.operations.push(operation);
158-
operationId++;
159174
}
160-
}
161-
// cleanup resources
162-
for (var i = 0; i < resources.length; i++) {
163-
var operations = resources[i].operations;
164-
if (!operations || (operations && operations.length === 0)) {
165-
resources.splice(i, 1);
175+
// cleanup resources
176+
for (var i = 0; i < resources.length; i++) {
177+
var res = resources[i],
178+
operations = resources[i].operations;
179+
180+
res.open = res.open || openPath === res.name || openPath === res.name + '*';
181+
if (!operations || (operations && operations.length === 0)) {
182+
resources.splice(i, 1);
183+
}
166184
}
185+
// sort resources alphabeticaly
186+
resources.sort(function(a, b) {
187+
if (a.name > b.name) {
188+
return 1;
189+
} else if (a.name < b.name) {
190+
return -1;
191+
}
192+
return 0;
193+
});
194+
// clear cache
195+
swaggerModel.clearCache();
196+
// display swagger
197+
$scope.form = form;
198+
$scope.resources = resources;
167199
}
168-
// sort resources alphabeticaly
169-
resources.sort(function(a, b) {
170-
if (a.name > b.name) {
171-
return 1;
172-
} else if (a.name < b.name) {
173-
return -1;
200+
201+
/**
202+
* show all resource's operations as list or as expanded list
203+
*/
204+
$scope.expand = function(resource, expandOperations) {
205+
resource.open = true;
206+
for (var i = 0, op = resource.operations, l = op.length; i < l; i++) {
207+
op[i].open = expandOperations;
174208
}
175-
return 0;
176-
});
177-
// clear cache
178-
swaggerModel.clearCache();
179-
// display swagger
180-
$scope.form = form;
181-
$scope.resources = resources;
182-
}
209+
};
183210

184-
/**
185-
* show all resource's operations as list or as expanded list
186-
*/
187-
$scope.expand = function(resource, expandOperations) {
188-
resource.open = true;
189-
for (var i = 0, op = resource.operations, l = op.length; i < l; i++) {
190-
op[i].open = expandOperations;
191-
}
192-
};
211+
$scope.permalink = function(name) {
212+
$location.search('open', name);
213+
};
193214

194-
/**
195-
* sends a sample API request
196-
*/
197-
$scope.submitExplorer = function(operation) {
198-
operation.loading = true;
199-
swaggerClient
200-
.send(swagger, operation, $scope.form[operation.id], $scope.apiExplorerTransform)
201-
.then(function(result) {
202-
operation.loading = false;
203-
operation.explorerResult = result;
204-
});
205-
};
215+
/**
216+
* sends a sample API request
217+
*/
218+
$scope.submitExplorer = function(operation) {
219+
operation.loading = true;
220+
swaggerClient
221+
.send(swagger, operation, $scope.form[operation.id], $scope.apiExplorerTransform)
222+
.then(function(result) {
223+
operation.loading = false;
224+
operation.explorerResult = result;
225+
});
226+
};
206227

207-
}])
228+
}
229+
])
208230
.directive('fileInput', function() {
209231
// helper to be able to retrieve HTML5 File in ngModel from input
210232
return {

0 commit comments

Comments
 (0)