add api doc viewer (moved from package pve2-api-doc)
[pve-docs.git] / PVEAPI.js
1 // avoid errors when running without development tools
2 if (!Ext.isDefined(Ext.global.console)) {
3 var console = {
4 dir: function() {},
5 log: function() {}
6 };
7 }
8
9 Ext.onReady(function() {
10
11 Ext.define('pve-param-schema', {
12 extend: 'Ext.data.Model',
13 fields: [
14 'name', 'type', 'typetext', 'description', 'enum',
15 'minimum', 'maximum', 'minLength', 'maxLength',
16 'pattern', 'title', 'requires', 'format', 'default',
17 'disallow', 'extends', 'links',
18 {
19 name: 'optional',
20 type: 'boolean'
21 }
22 ]
23 });
24
25 var store = Ext.create('Ext.data.TreeStore', {
26 model: Ext.define('pve-api-doc', {
27 extend: 'Ext.data.Model',
28 fields: [
29 'path', 'info', 'text',
30 ]
31 }),
32 proxy: {
33 type: 'memory',
34 data: pveapi
35 },
36 sorters: [{
37 property: 'leaf',
38 direction: 'ASC'
39 }, {
40 property: 'text',
41 direction: 'ASC'
42 }]
43 });
44
45 var render_text = function(value, metaData, record) {
46 var pdef = record.data;
47
48 metaData.style = 'white-space:pre-wrap;'
49
50 return Ext.htmlEncode(value);
51 };
52
53 var render_type = function(value, metaData, record) {
54 var pdef = record.data;
55
56 return pdef['enum'] ? 'enum' : (pdef.type || 'string');
57 };
58
59 var render_format = function(value, metaData, record) {
60 var pdef = record.data;
61
62 metaData.style = 'white-space:normal;'
63
64 if (pdef.typetext)
65 return pdef.typetext;
66
67 if (pdef['enum'])
68 return pdef['enum'].join(' | ');
69
70 if (pdef.format)
71 return pdef.format;
72
73 if (pdef.pattern)
74 return pdef.pattern;
75
76 return '';
77 };
78
79 var render_docu = function(data) {
80 var md = data.info;
81
82 // console.dir(data);
83
84 var items = [];
85
86 var clicmdhash = {
87 GET: 'get',
88 POST: 'create',
89 PUT: 'set',
90 DELETE: 'delete'
91 };
92
93 Ext.Array.each(['GET', 'POST', 'PUT', 'DELETE'], function(method) {
94 var info = md[method];
95 if (info) {
96
97 var usage = "";
98
99 usage += "<table><tr><td>HTTP:&nbsp;&nbsp;&nbsp;</td><td>" + method + " /api2/json" + data.path + "</td></tr><tr><td>&nbsp</td></tr>";
100 usage += "<tr><td>CLI:</td><td>pvesh " + clicmdhash[method] + " " + data.path + "</td></tr></table>";
101
102 var sections = [
103 {
104 title: 'Description',
105 html: Ext.htmlEncode(info.description),
106 bodyPadding: 10
107 },
108 {
109 title: 'Usage',
110 html: usage,
111 bodyPadding: 10
112 }
113 ];
114
115 if (info.parameters && info.parameters.properties) {
116
117 var pstore = Ext.create('Ext.data.Store', {
118 model: 'pve-param-schema',
119 proxy: {
120 type: 'memory'
121 },
122 groupField: 'optional',
123 sorters: [
124 {
125 property: 'name',
126 direction: 'ASC'
127 }
128 ]
129 });
130
131 Ext.Object.each(info.parameters.properties, function(name, pdef) {
132 pdef.name = name;
133 pstore.add(pdef);
134 });
135
136 pstore.sort();
137
138 var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
139 enableGroupingMenu: false,
140 groupHeaderTpl: '<tpl if="name">Optional</tpl><tpl if="!name">Required</tpl>'
141 });
142
143 sections.push({
144 xtype: 'gridpanel',
145 title: 'Parameters',
146 features: [groupingFeature],
147 store: pstore,
148 viewConfig: {
149 trackOver: false,
150 stripeRows: true
151 },
152 columns: [
153 {
154 header: 'Name',
155 dataIndex: 'name'
156 },
157 {
158 header: 'Type',
159 dataIndex: 'type',
160 renderer: render_type,
161 },
162 {
163 header: 'Format',
164 dataIndex: 'type',
165 renderer: render_format,
166 flex: 1
167 },
168 {
169 header: 'Description',
170 dataIndex: 'description',
171 renderer: render_text,
172 flex: 2
173 }
174 ]
175 });
176
177 }
178
179 if (info.returns) {
180
181 var rtype = info.returns.type;
182 if (!rtype && info.returns.items)
183 rtype = 'array';
184 if (!rtype)
185 rtype = 'object';
186
187 sections.push({
188 title: 'Returns: ' + rtype
189 });
190 }
191
192 var permhtml = '';
193 if (!info.permissions) {
194 permhtml = "Root only.";
195 } else {
196 if (info.permissions.description) {
197 permhtml += "<div style='white-space:pre-wrap;padding-bottom:10px;'>" +
198 Ext.htmlEncode(info.permissions.description) + "</div>";
199 }
200
201 if (info.permissions.user) {
202 if (!info.permissions.description) {
203 if (info.permissions.user === 'world') {
204 permhtml += "Accessible without any authententification.";
205 } else if (info.permissions.user === 'all') {
206 permhtml += "Accessible by all authententicated users.";
207 } else {
208 permhtml += 'Onyl accessible by user "' +
209 info.permissions.user + '"';
210 }
211 }
212 } else if (info.permissions.check) {
213 permhtml += "<pre>Check: " +
214 Ext.htmlEncode(Ext.JSON.encode(info.permissions.check)) + "</pre>";
215 } else {
216 permhtml += "Unknown systax!";
217 }
218 }
219
220 sections.push({
221 title: 'Required permissions',
222 bodyPadding: 10,
223 html: permhtml
224 });
225
226
227 items.push({
228 title: method,
229 autoScroll: true,
230 defaults: {
231 border: false
232 },
233 items: sections
234 });
235 }
236 });
237
238 var ct = Ext.getCmp('docview');
239 ct.setTitle("Path: " + data.path);
240 ct.removeAll(true);
241 ct.add(items);
242 };
243
244 var tree = Ext.create('Ext.tree.Panel', {
245 title: 'Resource Tree',
246 store: store,
247 width: 200,
248 region: 'west',
249 split: true,
250 margins: '5 0 5 5',
251 rootVisible: false,
252 listeners: {
253 selectionchange: function(v, selections) {
254 if (!selections[0])
255 return;
256 var rec = selections[0];
257 render_docu(rec.data);
258 }
259 }
260 });
261
262 Ext.create('Ext.container.Viewport', {
263 layout: 'border',
264 renderTo: Ext.getBody(),
265 items: [
266 tree,
267 {
268 xtype: 'tabpanel',
269 title: 'Documentation',
270 id: 'docview',
271 region: 'center',
272 margins: '5 5 5 0',
273 layout: 'fit',
274 items: []
275 }
276 ]
277 });
278
279 });