* [pmg-devel] [PATCH pmg-docs] build api-viewer from proxmox-widget-toolkit-dev
@ 2021-05-28 12:15 Dominik Csapak
0 siblings, 0 replies; only message in thread
From: Dominik Csapak @ 2021-05-28 12:15 UTC (permalink / raw)
To: pmg-devel
build-depends on the new proxmox-widget-toolkit-dev package
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
Makefile | 10 +-
api-viewer/PMGAPI.js | 490 +------------------------------------------
debian/control | 1 +
| 2 +-
4 files changed, 19 insertions(+), 484 deletions(-)
diff --git a/Makefile b/Makefile
index 8b125df..e2b7d6f 100644
--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,11 @@ GEN_SCRIPTS= \
gen-pmg.conf.5-opts.pl \
gen-user.conf.5-opts.pl
+API_VIEWER_FILES= \
+ api-viewer/apidata.js \
+ api-viewer/PMGAPI.js \
+ /usr/share/javascript/proxmox-widget-toolkit-dev/APIVIEWER.js
+
API_VIEWER_SOURCES= \
api-viewer/index.html \
api-viewer/apidoc.js
@@ -139,8 +144,9 @@ pmg-admin-guide.epub: ${PMG_ADMIN_GUIDE_ADOCDEPENDS}
api-viewer/apidata.js: extractapi.pl
./extractapi.pl >$@
-api-viewer/apidoc.js: api-viewer/apidata.js api-viewer/PMGAPI.js
- cat api-viewer/apidata.js api-viewer/PMGAPI.js >$@
+api-viewer/apidoc.js: ${API_VIEWER_FILES}
+ cat ${API_VIEWER_FILES} >$@.tmp
+ mv $@.tmp $@
.PHONY: dinstall
dinstall: ${GEN_DEB} ${DOC_DEB}
diff --git a/api-viewer/PMGAPI.js b/api-viewer/PMGAPI.js
index 76fd77e..838b0de 100644
--- a/api-viewer/PMGAPI.js
+++ b/api-viewer/PMGAPI.js
@@ -1,482 +1,10 @@
-// avoid errors when running without development tools
-if (!Ext.isDefined(Ext.global.console)) {
- var console = {
- dir: function() {},
- log: function() {}
- };
+var clicmdhash = {
+ GET: 'get',
+ POST: 'create',
+ PUT: 'set',
+ DELETE: 'delete'
+};
+
+function cliusage(method, path) {
+ return `<tr><td> </td></tr><tr><td>CLI:</td><td>pmgsh ${clicmdhash[method]} ${path}</td></tr></table>`;
}
-
-Ext.onReady(function() {
-
- Ext.define('pmg-param-schema', {
- extend: 'Ext.data.Model',
- fields: [
- 'name', 'type', 'typetext', 'description', 'verbose_description',
- 'enum', 'minimum', 'maximum', 'minLength', 'maxLength',
- 'pattern', 'title', 'requires', 'format', 'default',
- 'disallow', 'extends', 'links',
- {
- name: 'optional',
- type: 'boolean'
- }
- ]
- });
-
- var store = Ext.define('pmg-updated-treestore', {
- extend: 'Ext.data.TreeStore',
- model: Ext.define('pmg-api-doc', {
- extend: 'Ext.data.Model',
- fields: [
- 'path', 'info', 'text',
- ]
- }),
- proxy: {
- type: 'memory',
- data: pmgapi
- },
- sorters: [{
- property: 'leaf',
- direction: 'ASC'
- }, {
- property: 'text',
- direction: 'ASC'
- }],
- filterer: 'bottomup',
- doFilter: function(node) {
- this.filterNodes(node, this.getFilters().getFilterFn(), true);
- },
-
- filterNodes: function(node, filterFn, parentVisible) {
- var me = this,
- bottomUpFiltering = me.filterer === 'bottomup',
- match = filterFn(node) && parentVisible || (node.isRoot() && !me.getRootVisible()),
- childNodes = node.childNodes,
- len = childNodes && childNodes.length, i, matchingChildren;
-
- if (len) {
- for (i = 0; i < len; ++i) {
- matchingChildren = me.filterNodes(childNodes[i], filterFn, match || bottomUpFiltering) || matchingChildren;
- }
- if (bottomUpFiltering) {
- match = matchingChildren || match;
- }
- }
-
- node.set("visible", match, me._silentOptions);
- return match;
- },
-
- }).create();
-
- var render_description = function(value, metaData, record) {
- var pdef = record.data;
-
- value = pdef.verbose_description || value;
-
- // TODO: try to render asciidoc correctly
-
- metaData.style = 'white-space:pre-wrap;'
-
- return Ext.htmlEncode(value);
- };
-
- var render_type = function(value, metaData, record) {
- var pdef = record.data;
-
- return pdef['enum'] ? 'enum' : (pdef.type || 'string');
- };
-
- var render_format = function(value, metaData, record) {
- var pdef = record.data;
-
- metaData.style = 'white-space:normal;'
-
- if (pdef.typetext)
- return Ext.htmlEncode(pdef.typetext);
-
- if (pdef['enum'])
- return pdef['enum'].join(' | ');
-
- if (pdef.format)
- return pdef.format;
-
- if (pdef.pattern)
- return Ext.htmlEncode(pdef.pattern);
-
- return '';
- };
-
- var render_docu = function(data) {
- var md = data.info;
-
- // console.dir(data);
-
- var items = [];
-
- var clicmdhash = {
- GET: 'get',
- POST: 'create',
- PUT: 'set',
- DELETE: 'delete'
- };
-
- Ext.Array.each(['GET', 'POST', 'PUT', 'DELETE'], function(method) {
- var info = md[method];
- if (info) {
-
- var usage = "";
-
- usage += "<table><tr><td>HTTP: </td><td>" + method + " /api2/json" + data.path + "</td></tr><tr><td> </td></tr>";
- usage += "<tr><td>CLI:</td><td>pmgsh " + clicmdhash[method] + " " + data.path + "</td></tr></table>";
-
- var sections = [
- {
- title: 'Description',
- html: Ext.htmlEncode(info.description),
- bodyPadding: 10
- },
- {
- title: 'Usage',
- html: usage,
- bodyPadding: 10
- }
- ];
-
- if (info.parameters && info.parameters.properties) {
-
- var pstore = Ext.create('Ext.data.Store', {
- model: 'pmg-param-schema',
- proxy: {
- type: 'memory'
- },
- groupField: 'optional',
- sorters: [
- {
- property: 'name',
- direction: 'ASC'
- }
- ]
- });
-
- Ext.Object.each(info.parameters.properties, function(name, pdef) {
- pdef.name = name;
- pstore.add(pdef);
- });
-
- pstore.sort();
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
- enableGroupingMenu: false,
- groupHeaderTpl: '<tpl if="groupValue">Optional</tpl><tpl if="!groupValue">Required</tpl>'
- });
-
- sections.push({
- xtype: 'gridpanel',
- title: 'Parameters',
- features: [groupingFeature],
- store: pstore,
- viewConfig: {
- trackOver: false,
- stripeRows: true
- },
- columns: [
- {
- header: 'Name',
- dataIndex: 'name',
- flex: 1
- },
- {
- header: 'Type',
- dataIndex: 'type',
- renderer: render_type,
- flex: 1
- },
- {
- header: 'Default',
- dataIndex: 'default',
- flex: 1
- },
- {
- header: 'Format',
- dataIndex: 'type',
- renderer: render_format,
- flex: 2
- },
- {
- header: 'Description',
- dataIndex: 'description',
- renderer: render_description,
- flex: 6
- }
- ]
- });
-
- }
-
- if (info.returns) {
-
- var retinf = info.returns;
- var rtype = retinf.type;
- if (!rtype && retinf.items)
- rtype = 'array';
- if (!rtype)
- rtype = 'object';
-
- var rpstore = Ext.create('Ext.data.Store', {
- model: 'pmg-param-schema',
- proxy: {
- type: 'memory'
- },
- groupField: 'optional',
- sorters: [
- {
- property: 'name',
- direction: 'ASC'
- }
- ]
- });
-
- var properties;
- if (rtype === 'array' && retinf.items.properties) {
- properties = retinf.items.properties;
- }
-
- if (rtype === 'object' && retinf.properties) {
- properties = retinf.properties;
- }
-
- Ext.Object.each(properties, function(name, pdef) {
- pdef.name = name;
- rpstore.add(pdef);
- });
-
- rpstore.sort();
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
- enableGroupingMenu: false,
- groupHeaderTpl: '<tpl if="groupValue">Optional</tpl><tpl if="!groupValue">Obligatory</tpl>'
- });
- var returnhtml;
- if (retinf.items) {
- returnhtml = '<pre>items: ' + Ext.htmlEncode(JSON.stringify(retinf.items, null, 4)) + '</pre>';
- }
-
- if (retinf.properties) {
- returnhtml = returnhtml || '';
- returnhtml += '<pre>properties:' + Ext.htmlEncode(JSON.stringify(retinf.properties, null, 4)) + '</pre>';
- }
-
- var rawSection = Ext.create('Ext.panel.Panel', {
- bodyPadding: '0px 10px 10px 10px',
- html: returnhtml,
- hidden: true
- });
-
- sections.push({
- xtype: 'gridpanel',
- title: 'Returns: ' + rtype,
- features: [groupingFeature],
- store: rpstore,
- viewConfig: {
- trackOver: false,
- stripeRows: true
- },
- columns: [
- {
- header: 'Name',
- dataIndex: 'name',
- flex: 1
- },
- {
- header: 'Type',
- dataIndex: 'type',
- renderer: render_type,
- flex: 1
- },
- {
- header: 'Default',
- dataIndex: 'default',
- flex: 1
- },
- {
- header: 'Format',
- dataIndex: 'type',
- renderer: render_format,
- flex: 2
- },
- {
- header: 'Description',
- dataIndex: 'description',
- renderer: render_description,
- flex: 6
- }
- ],
- bbar: [
- {
- xtype: 'button',
- text: 'Show RAW',
- handler: function(btn) {
- rawSection.setVisible(!rawSection.isVisible());
- btn.setText(rawSection.isVisible() ? 'Hide RAW' : 'Show RAW');
- }}
- ]
- });
-
- sections.push(rawSection);
-
-
- }
-
- var permhtml = '';
- if (!info.permissions) {
- permhtml = "Root only.";
- } else {
- if (info.permissions.description) {
- permhtml += "<div style='white-space:pre-wrap;padding-bottom:10px;'>" +
- Ext.htmlEncode(info.permissions.description) + "</div>";
- }
-
- if (info.permissions.user) {
- if (!info.permissions.description) {
- if (info.permissions.user === 'world') {
- permhtml += "Accessible without any authentication.";
- } else if (info.permissions.user === 'all') {
- permhtml += "Accessible by all authenticated users.";
- } else {
- permhtml += 'Onyl accessible by user "' +
- info.permissions.user + '"';
- }
- }
- } else if (info.permissions.check) {
- permhtml += "<pre>Check: " +
- Ext.htmlEncode(Ext.JSON.encode(info.permissions.check)) + "</pre>";
- } else {
- permhtml += "Unknown systax!";
- }
- }
- if (!info.allowtoken) {
- // PMG doesn't fully supports API token, and probably won't ever!?
- permhtml += "<br />This API endpoint is not available for API tokens."
- }
-
- sections.push({
- title: 'Required permissions',
- bodyPadding: 10,
- html: permhtml
- });
-
-
- items.push({
- title: method,
- autoScroll: true,
- defaults: {
- border: false
- },
- items: sections
- });
- }
- });
-
- var ct = Ext.getCmp('docview');
- ct.setTitle("Path: " + data.path);
- ct.removeAll(true);
- ct.add(items);
- ct.setActiveTab(0);
- };
-
- Ext.define('Ext.form.SearchField', {
- extend: 'Ext.form.field.Text',
- alias: 'widget.searchfield',
-
- emptyText: 'Search...',
-
- flex: 1,
-
- inputType: 'search',
- listeners: {
- 'change': function(){
-
- var value = this.getValue();
- if (!Ext.isEmpty(value)) {
- store.filter({
- property: 'path',
- value: value,
- anyMatch: true
- });
- } else {
- store.clearFilter();
- }
- }
- }
- });
-
- var tree = Ext.create('Ext.tree.Panel', {
- title: 'Resource Tree',
- tbar: [
- {
- xtype: 'searchfield',
- }
- ],
- tools: [
- {
- type: 'expand',
- tooltip: 'Expand all',
- tooltipType: 'title',
- callback: (tree) => tree.expandAll(),
- },
- {
- type: 'collapse',
- tooltip: 'Collapse all',
- tooltipType: 'title',
- callback: (tree) => tree.collapseAll(),
- },
- ],
- store: store,
- width: 200,
- region: 'west',
- split: true,
- margins: '5 0 5 5',
- rootVisible: false,
- listeners: {
- selectionchange: function(v, selections) {
- if (!selections[0])
- return;
- var rec = selections[0];
- render_docu(rec.data);
- location.hash = '#' + rec.data.path;
- }
- }
- });
-
- Ext.create('Ext.container.Viewport', {
- layout: 'border',
- renderTo: Ext.getBody(),
- items: [
- tree,
- {
- xtype: 'tabpanel',
- title: 'Documentation',
- id: 'docview',
- region: 'center',
- margins: '5 5 5 0',
- layout: 'fit',
- items: []
- }
- ]
- });
-
- var deepLink = function() {
- var path = window.location.hash.substring(1).replace(/\/\s*$/, '')
- var endpoint = store.findNode('path', path);
-
- if (endpoint) {
- tree.getSelectionModel().select(endpoint);
- tree.expandPath(endpoint.getPath());
- render_docu(endpoint.data);
- }
- }
- window.onhashchange = deepLink;
-
- deepLink();
-
-});
diff --git a/debian/control b/debian/control
index 8d2ccde..353f688 100644
--- a/debian/control
+++ b/debian/control
@@ -10,6 +10,7 @@ Build-Depends: asciidoc-dblatex,
librsvg2-bin,
lintian,
source-highlight,
+ proxmox-widget-toolkit-dev,
Standards-Version: 3.8.4
Package: pmg-doc-generator
--git a/extractapi.pl b/extractapi.pl
index 283d8a0..85ab54f 100755
--- a/extractapi.pl
+++ b/extractapi.pl
@@ -42,6 +42,6 @@ sub cleanup_tree {
my $tree = cleanup_tree(PVE::RESTHandler::api_dump('PMG::API2'));
-print "var pmgapi = " . to_json($tree, {pretty => 1, canonical => 1}) . ";\n\n";
+print "var pmxapi = " . to_json($tree, {pretty => 1, canonical => 1}) . ";\n\n";
exit(0);
--
2.20.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-05-28 12:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-28 12:15 [pmg-devel] [PATCH pmg-docs] build api-viewer from proxmox-widget-toolkit-dev Dominik Csapak
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal