UNPKG

api-console-assets

Version:

This repo only exists to publish api console components to npm

679 lines (608 loc) 21.9 kB
<!-- @license Copyright 2016 The Advanced REST client authors <arc@mulesoft.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../raml-behaviors/raml-behavior.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../paper-button/paper-button.html"> <link rel="import" href="../docs-parameters-table/docs-parameters-table.html"> <link rel="import" href="../docs-parameters-table/docs-headers-table.html"> <link rel="import" href="../docs-parameters-table/docs-body-parameters-table.html"> <link rel="import" href="../raml-annotations-display/raml-annotations-display.html"> <link rel="import" href="../raml-docs-response-panel/raml-docs-response-panel.html"> <link rel="import" href="../iron-media-query/iron-media-query.html"> <link rel="import" href="../marked-element/marked-element.html"> <link rel="import" href="../markdown-styles/markdown-styles.html"> <link rel="import" href="../iron-collapse/iron-collapse.html"> <link rel="import" href="../iron-icon/iron-icon.html"> <link rel="import" href="../arc-icons/arc-icons.html"> <!-- `<raml-docs-method-viewer>` Documentation view for the method defined in RAML file This element is meant to work with data structure returned by the `<raml-js-parser>` and `<raml-path-to-object>`. Regular JSON output from the RAML JS parser will not work with this element. ### Example ``` <raml-docs-method-viewer raml="[[methodDefinition]]" parent-endpoint="[[selectedParent]]"></raml-docs-method-viewer> ``` To properly compute values displayed in the view it needs to know its `parentEndpoint`. Though, it will work properly if the parent is not passed. Parent is used to display title of the method. ## Disabling the "try it" button You can either set the `noTryIt` property to true (or set the `no-try-it` attribute on the element) or send for the `tryit-toggle` custom event with the `state` property set to the detail object. The element will listen on `window` object for the event. ### Styling `<raml-docs-method-viewer>` provides the following custom properties and mixins for styling: Custom property | Description | Default ----------------|-------------|---------- `--raml-docs-method-viewer` | Mixin applied to the element | `{}` `--raml-docs-h1` | Mixin applied to H1 | `{}` | `--raml-docs-h2` | Mixin applied to H2 | `{}` | `--raml-docs-h3` | Mixin applied to H3 | `{}` | `--raml-docs-method-viewer-title-method-font-weight` | Font weight of the name if the method | `500` | `--raml-docs-method-viewer-http-method-font-weight` | Font weight of the HTTP method | `500` | `--raml-docs-item-description` | Mixin applied to the description field. | `{}` | `--raml-docs-method-viewer-url-color` | Color of the URL field | `--accent-color` | `--raml-docs-method-viewer-url-font-style` | font-style of the URL value | `italic` | `--raml-docs-method-viewer-url` | Mixin applied to the URL field | `{}` | `--action-button` | Mixin applied to the main action button (Try it) | `{}` `--action-button-hover` | Mixin applied to the main action button on hover (Try it) | `{}` `--arc-font-headline` | Mixin applied to the h1 element (API title) | `{}` `--arc-font-title` | Mixin applied to the h2 elements (section title) | `{}` `--arc-font-subhead` | Mixin applied to the h3 elements (section sub-titles) | `{}` `--toggle-button` | Mixin applied to toggling button (show/hide) | `{}` `--toggle-button-hover` | Mixin applied to toggling button on hover (show/hide) | `{}` `--raml-docs-method-viewer-title-area-actions` | Mixin applied to toggling actions area | `{}` `--raml-docs-method-viewer-traits-list` | Mixin applied to the list of traits container | `{}` `--raml-docs-method-viewer-traits-list-values` | Mixin applied to the list of traits values (names) | `{}` `--raml-docs-method-viewer-traits-list-label` | Mixin applied to the list of traits list label | `{}` `--raml-docs-method-viewer-traits-list-color` | Color of the traits list section | `rgba(0,0,0,0.74)` `--raml-docs-method-viewer-traits-list-values-color` | Color of the traits list values (names) | `rgba(0,0,0,0.94)` `--raml-docs-method-viewer-traits-list-label-color` | Color of the traits list label | `inherit` @group RAML Elements @element raml-docs-method-viewer @demo demo/index.html --> <dom-module id="raml-docs-method-viewer"> <template> <style include="markdown-styles"></style> <style> :host { display: block; @apply(--raml-docs-method-viewer); } :host([hidden]) { display: none !important; } h1 { @apply(--arc-font-headline); @apply(--raml-docs-method-viewer-content-section); @apply(--raml-docs-h1); } h2 { @apply(--arc-font-title); @apply(--raml-docs-method-viewer-content-section); @apply(--raml-docs-h2); } h3 { @apply(--arc-font-subhead); @apply(--raml-docs-method-viewer-content-section); @apply(--raml-docs-h3); } .method-name { font-weight: var(--raml-docs-method-viewer-title-method-font-weight, 500); } .method-value { text-transform: uppercase; font-weight: var(--raml-docs-method-viewer-http-method-font-weight, 500); } .title-area { @apply(--layout-horizontal); @apply(--layout-center); } .title { @apply(--layout-flex); } .method-desc { margin-bottom: 28px; color: rgba(0,0,0,0.74); @apply(--arc-font-body1); @apply(--raml-docs-method-viewer-content-section); @apply(--raml-docs-item-description); } .url-area { @apply(--layout-horizontal); @apply(--arc-font-body1); font-size: 16px; margin-bottom: 40px; color: var(--raml-docs-method-viewer-url-color, --accent-color); @apply(--raml-docs-method-viewer-content-section); } .url-value { font-style: var(--raml-docs-method-viewer-url-font-style, italic); margin-left: 12px; word-break: break-all; @apply(--raml-docs-method-viewer-url); } .body-selector { margin: 0 12px; } .action-button { background-color: var(--primary-color); color: var(--primary-action-color, #fff); @apply(--action-button); } .action-button:hover { @apply(--action-button-hover); } .bottom.action { @apply(--layout-horizontal); @apply(--layout-end-justified); } :host([narrow]) .container { max-width: var(--raml-docs-method-viewer-narrow-container-width, calc(100vw - 32px)); overflow: auto; } :host([narrow]) docs-parameters-table, :host([narrow]) docs-headers-table, :host([narrow]) docs-body-parameters-table, :host([narrow]) raml-docs-response-panel { max-width: var(--raml-docs-method-viewer-narrow-container-width, calc(100vw - 32px)); overflow: auto; } :host([narrow]) .title-area { margin-bottom: 24px; /*@apply(--layout-start);*/ } :host([narrow]) h1 { font-size: 20px; margin: 0; } :host([narrow]) h2 { font-size: 18px; } :host([narrow]) h3 { font-size: 17px; } .section-title-area { @apply(--layout-horizontal); @apply(--layout-center); border-bottom: 1px var(--raml-docs-resource-viewer-title-border-color, #e5e5e5) solid; } .section-title-area h3 { @apply(--layout-flex); } .toggle-button { color: var(--arc-toggle-view-icon-color, rgba(0, 0, 0, 0.54)); transition: color 0.25s linear; @apply(--toggle-button); } .toggle-button:hover { color: var(--arc-toggle-view-icon-hover-color, rgba(0, 0, 0, 0.78)); @apply(--toggle-button-hover); } .toggle-icon { transform: rotateZ(0deg); transition: transform 0.3s linear; } .toggle-icon.opened { transform: rotateZ(-180deg); } .title-area-actions { @apply(--raml-docs-method-viewer-title-area-actions); } .traits-list { @apply(--arc-font-body1); margin-bottom: 8px; color: var(--raml-docs-method-viewer-traits-list-color, rgba(0,0,0,0.74)); @apply(--raml-docs-method-viewer-traits-list); } .trait-value { color: var(--raml-docs-method-viewer-traits-list-values-color, rgba(0,0,0,0.94)); @apply(--raml-docs-method-viewer-traits-list-values); } .trait-label { color: var(--raml-docs-method-viewer-traits-list-label-color, inherit); @apply(--raml-docs-method-viewer-traits-list-label); } raml-annotations-display { color: rgba(0,0,0,0.74); margin-bottom: 12px; } </style> <iron-media-query query="(max-width: [[narrowWidth]])" query-matches="{{narrow}}"></iron-media-query> <section class="container"> <div class="title-area"> <h1 class="title"> <span>[[parentName]]</span> <span hidden$="[[!parentName]]">:</span> <span class="method-name">[[methodName]]</span> </h1> <template is="dom-if" if="[[!noTryIt]]"> <div class="action"> <paper-button class="action-button" on-tap="_tryIt">Try it</paper-button> </div> </template> </div> <template is="dom-if" if="[[hasTraits]]"> <div class="traits-list"> <span class="trait-label">Traits:</span> <span class="trait-value">[[_computeTraitsList(raml.is)]]</span> </div> </template> <template is="dom-if" if="[[hasValue(raml.annotations)]]"> <raml-annotations-display annotations="[[raml.annotations]]"></raml-annotations-display> </template> <div hidden$="[[_computeHideMethodDesc(raml.description)]]" class="method-desc"> <marked-element markdown="[[raml.description]]"> <div class="markdown-html markdown-body"></div> </marked-element> </div> <section class="request-doc"> <h2>Request</h2> <div class="url-area"> <div class="method-value">[[raml.method]]</div> <div class="url-value">[[raml.absoluteUri]]</div> </div> <section hidden$="[[!hasParameters]]"> <div class="section-title-area"> <h3>Parameters</h3> <div class="title-area-actions"> <paper-button data-section="parameters" on-tap="_toggleCollapseSection" class="toggle-button" title="Toogle parameters details"> [[_computeToggleActionLabel(parametersOpened)]] <iron-icon icon="arc:expand-more" class$="[[_computeToggleIconClass(parametersOpened)]]"></iron-icon> </paper-button> </div> </div> <iron-collapse opened="[[parametersOpened]]"> <docs-parameters-table uri-parameters="[[raml.allUriParameters]]" query-parameters="[[raml.queryParameters]]" has-parameters="{{hasParameters}}" narrow=[[narrow]] auto-hide></docs-parameters-table> </iron-collapse> </section> <section hidden$="[[!hasHeaders]]"> <div class="section-title-area"> <h3>Headers</h3> <div class="title-area-actions"> <paper-button data-section="headers" on-tap="_toggleCollapseSection" class="toggle-button" title="Toogle headers details"> [[_computeToggleActionLabel(headersOpened)]] <iron-icon icon="arc:expand-more" class$="[[_computeToggleIconClass(headersOpened)]]"></iron-icon> </paper-button> </div> </div> <iron-collapse opened="[[headersOpened]]"> <docs-headers-table has-headers="{{hasHeaders}}" headers="[[raml.headers]]" auto-hide></docs-headers-table> </iron-collapse> </section> <section hidden$="[[!hasBody]]"> <div class="section-title-area"> <h3>Body</h3> <div class="title-area-actions"> <paper-button data-section="body" on-tap="_toggleCollapseSection" class="toggle-button" title="Toogle body details"> [[_computeToggleActionLabel(bodyOpened)]] <iron-icon icon="arc:expand-more" class$="[[_computeToggleIconClass(bodyOpened)]]"></iron-icon> </paper-button> </div> </div> <iron-collapse opened="[[bodyOpened]]"> <docs-body-parameters-table body="[[raml.body]]" narrow=[[narrow]]></docs-body-parameters-table> </iron-collapse> </section> </section> <section class="response-doc" hidden$="[[!hasResponses]]"> <h2>Response</h2> <raml-docs-response-panel has-responses="{{hasResponses}}" responses="[[raml.responses]]"></raml-docs-response-panel> </section> <template is="dom-if" if="[[!noTryIt]]"> <div class="bottom action"> <paper-button class="action-button" on-tap="_tryIt">Try it</paper-button> </div> </template> </section> </template> <script> Polymer({ is: 'raml-docs-method-viewer', behaviors: [Polymer.RamlBehavior], /** * Fired when the user pressed the `try it` button. * * @event tryit-requested */ properties: { // Parent endpoint object parentEndpoint: { type: Object, value: false }, // True if current endpont has a body hasBody: { value: false, type: Boolean, computed: '_computeHasBody(raml.body)' }, // Computed name of the parent resource parentName: { type: String, value: null, computed: '_computeParentName(parentEndpoint.*)' }, // Computed name of current method methodName: { type: String, computed: '_computeMethodName(raml.*)' }, // If true then the query / uri parameters will be displayed. hasParameters: Boolean, // Value obtained from the `raml-docs-response-panel` hasResponses: Boolean, // If true, the method has traits applied to it. hasTraits: { type: Boolean, readOnly: true }, /** * If true then the element will start listen for the * `raml-is-method-changed`, `raml-selected-object-changed` and * `raml-selected-path-changed` event and set corresponding properties * when needed. It's a replacement for the Polymer's data biding * for apps that are not Polymer powered. */ autoHide: { type: Boolean, observer: '_autoHideChanged' }, // If true then the element will be hidden ui the UI. hidden: { type: Boolean, reflectToAttribute: true }, // If set then the `tryit` button will be hidden. noTryIt: { type: Boolean, value: false }, /** * If set it will renders the view in the narrow layout. */ narrow: { type: Boolean, notify: true, reflectToAttribute: true }, // A widith below which the `narrow` property will be set to true. narrowWidth: { type: String, value: '768px' }, // If true then the parameters docs table is displayed. parametersOpened: { type: Boolean, value: true }, // If true then the headers docs table is displayed. headersOpened: { type: Boolean, value: true }, // If true then the body docs table is displayed. bodyOpened: { type: Boolean, value: true } }, observers: [ '_objectChanged(raml.*)' ], attached: function() { this._eventTarget = Polymer.dom(this).host || document; if (this.autoHide) { this._attacheListeners(); } this.listen(window, 'tryit-toggle', '_toggleTryitHandler'); }, detached: function() { this.unlisten(window, 'tryit-toggle', '_toggleTryitHandler'); }, _autoHideChanged: function(state) { if (state === undefined) { return; } if (state) { this._attacheListeners(); } else { this._detachListeners(); } }, _attacheListeners: function() { if (!this._eventTarget) { this.hidden = true; return; } this._detachListeners(); this.listen(this._eventTarget, 'raml-is-method-changed', '_isMethodHandler'); this.listen(this._eventTarget, 'raml-selected-object-changed', '_selectedChangeHandler'); this.listen(this._eventTarget, 'raml-selected-parent-changed', '_selectedParentChangeHandler'); }, _detachListeners: function() { if (!this._eventTarget) { return; } this.unlisten(this._eventTarget, 'raml-is-method-changed', '_isMethodHandler'); this.unlisten(this._eventTarget, 'raml-selected-object-changed', '_selectedChangeHandler'); this.unlisten(this._eventTarget, 'raml-selected-parent-changed', '_selectedParentChangeHandler'); }, _objectChanged: function(record) { // this.hidden = false; var raml = record && record.base; if (!raml) { this._setHasTraits(false); return; } if (raml.is && raml.is.length) { this._setHasTraits(true); } else { this._setHasTraits(false); } }, _computeMethodName: function() { var m = this.raml; if (!m) { return ''; } return m.displayName || m.method; }, _computeHideMethodDesc: function(description) { return !description; }, _computeHasBody: function(body) { return !!(body && body.length > 0); }, _isMethodHandler: function(e, detail) { var state = detail.state; this.hidden = !state; }, _selectedChangeHandler: function(e, detail) { if (this.hidden) { this.raml = undefined; return; } this.raml = detail.selectedObject; }, _selectedParentChangeHandler: function(e, detail) { if (this.hidden) { this.parentEndpoint = undefined; return; } this.parentEndpoint = detail.selectedParent; }, _tryIt: function() { this.fire('tryit-requested'); }, _computeParentName: function() { var endpoint = this.parentEndpoint; if (!endpoint) { return ''; } return endpoint.displayName || endpoint.relativeUri; }, /** * Toogles collapsable sections. * The toggle button must have `data-section` property with the name of the * section to toggle. Variable that controls the state (Boolean value) * must be called section + 'Opened'. */ _toggleCollapseSection: function(e) { var target = this._getPathElement(e, 'paper-button'); if (!target) { return console.warn('Toggle element not in path ', e.path); } var section = target.dataset.section; if (!section) { return console.warn('Toggle section not fond in path ', e.path); } var variable = section + 'Opened'; this[variable] = !this[variable]; }, /** * Extracts an element from the path. It is iterating over the path to find * an element that matches `nodeName`. * * @param {String} nodeName A node to find in the path. * @return {HTMLElement|dndefined} A first node in the path that matches the * name or undefiend. */ _getPathElement: function(e, nodeName) { if (!(e instanceof Polymer.DomApi.Event)) { e = Polymer.dom(e); } var path = e.path; if (!path || !path.length) { return e.rootTarget; } nodeName = nodeName.toUpperCase(); for (var i = 0, len = path.length; i < len; i++) { if (path[i] && path[i].nodeName && path[i].nodeName === nodeName) { return path[i]; } } }, // Computes class for the toggle's button icon. _computeToggleIconClass: function(opened) { var clazz = 'toggle-icon'; if (opened) { clazz += ' opened'; } return clazz; }, // Computes a label for the section toggle buttons. _computeToggleActionLabel: function(opened) { return opened ? 'Hide' : 'Show'; }, _toggleTryitHandler: function(e) { this.noTryIt = !e.detail.state; }, // Computes list of traits names to display in the view. _computeTraitsList: function(traits) { if (!traits || !traits.length) { return; } return traits.map(function(trait) { if (typeof trait === 'string') { return trait; } if (trait.name) { return trait.name; } try { var keys = Object.keys(trait); return keys[0]; } catch (e) {} }).join(', '); }, /** * Check if passed object is set. * 0 (zero) returns true while empty string returns false. * * @return {Boolean} True/False depending if passed object has a value. */ hasValue: function(obj) { var type = typeof obj; if (type === 'number' && obj === 0) { return true; } if (type === 'boolean') { return true; } if (type === 'string' && obj === '') { return true; } return !!obj; } }); </script> </dom-module>