forked from mulesoft/api-console
-
Notifications
You must be signed in to change notification settings - Fork 0
/
api-console.html
961 lines (924 loc) · 36.8 KB
/
api-console.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
<!--
@license
Copyright 2018 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-element.html">
<link rel="import" href="../polymer/lib/utils/render-status.html">
<link rel="import" href="../raml-aware/raml-aware.html">
<link rel="import" href="../app-layout/app-drawer/app-drawer.html">
<link rel="import" href="../app-layout/app-drawer-layout/app-drawer-layout.html">
<link rel="import" href="../app-layout/app-header/app-header.html">
<link rel="import" href="../app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../app-layout/app-scroll-effects/app-scroll-effects.html">
<link rel="import" href="../app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../app-route/app-location.html">
<link rel="import" href="../app-route/app-route.html">
<link rel="import" href="../api-navigation/api-navigation.html">
<link rel="import" href="../api-documentation/api-documentation.html">
<link rel="import" href="../api-request-panel/api-request-panel.html">
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
<link rel="import" href="../paper-toast/paper-toast.html">
<link rel="import" href="../iron-media-query/iron-media-query.html">
<link rel="import" href="../api-console-ext-comm/api-console-ext-comm.html">
<link rel="import" href="../amf-helper-mixin/amf-helper-mixin.html">
<dom-module id="api-console">
<template>
<style>
:host {
--app-primary-color: var(--api-console-primary-color, #00A2DF);
--app-secondary-color: var(--api-console-secondary-color, black);
display: block;
background-color: var(--api-console-primary-background-color, var(--primary-background-color, transparent));
@apply --arc-font-body1;
}
:host([app]) {
min-height: 100%;
}
*[hidden] {
display: none !important;
}
.nav-content {
@apply --layout-horizontal;
@apply --layout-center;
}
.powered-by {
padding: 12px 0px;
border-top: 1px rgba(0,0,0,0.24) solid;
margin: 8px 12px 0 12px;
}
a img {
text-underline: none;
}
a.attribution {
display: inline-block;
width: 177px;
margin-left: 24px;
fill: var(--api-console-menu-color, #424143);
}
app-drawer-layout:not([narrow]) [drawer-toggle] {
display: none;
}
app-drawer {
z-index: 0;
}
:host(:not([app])) app-drawer {
position: absolute;
}
:host([layout-narrow]) app-drawer {
z-index: var(--api-console-drawer-zindex, 1);
}
app-toolbar {
background-color: var(--api-console-toolbar-background-color, #000);
color: var(--api-console-toolbar-color, #fff);
}
.extension-banner {
@apply --layout-center;
display: none;
border-bottom: 1px var(--api-console-extension-banner-border-bottom-color, rgba(0,0,0,0.12)) solid;
border-top: 1px var(--api-console-extension-banner-border-bottom-color, rgba(0,0,0,0.12)) solid;
margin-bottom: 12px;
box-sizing: border-box;
color: var(--api-console-extension-banner-color, rgba(0,0,0,0.54));
}
.extension-banner[active] {
@apply --layout-horizontal;
}
.main-content {
margin-left: var(--api-console-main-content-margin-left, 24px);
margin-right: var(--api-console-main-content-margin-right, 24px);
margin-top: var(--api-console-main-content-margin-top, 0px);
}
.drawer-content-wrapper {
max-height: calc(100% - 64px);
/* overflow: auto; */
@apply --layout-vertical;
background-color: var(--api-console-menu-background-color, inherit);
color: var(--api-console-menu-color);
height: 100%;
}
api-navigation {
background-color: var(--api-console-menu-background-color, inherit);
color: var(--api-console-menu-color);
--paper-tab-content-unselected_-_color: var(--api-console-menu-tabs-color-unselected);
@apply --layout-flex-auto;
}
:host(:not([app])) app-drawer-layout {
min-height: inherit;
overflow: hidden;
}
:host(:not([app])) app-header {
position: absolute;
right: 0 !important;
left: 0 !important;
}
api-request-panel,
api-documentation {
max-width: var(--api-console-main-max-width, 1600px);
}
.api-docs {
@apply --layout-horizontal;
overflow: auto;
}
.api-docs api-documentation {
@apply --layout-flex;
}
.api-docs .inline-request {
max-width: 600px;
margin-left: 12px;
background-color: var(--apic-tryint-wide-background-color, #f8f8f8);
padding: 0 12px;
box-sizing: border-box;
@apply --layout-flex;
}
.method-title-area {
@apply --layout-horizontal;
@apply --layout-center;
}
.method-title-area,
.extension-banner {
max-width: var(--api-console-main-max-width, 900px);
}
.method-title {
@apply --layout-flex;
@apply --arc-font-headline;
font-weight: var(--api-method-documentation-title-method-font-weight, 500);
text-transform: capitalize;
@apply --api-method-documentation-title;
}
:host([narrow]) .method-title-area {
margin-bottom: 24px;
margin-top: 12px;
}
:host([narrow]) .method-title {
font-size: 20px;
margin: 0;
@apply --api-method-documentation-title-narrow;
}
.store-link {
@apply --arc-link;
}
</style>
<template is="dom-if" if="[[app]]" restamp="true">
<iron-media-query query="(max-width: 740px)" query-matches="{{narrow}}"></iron-media-query>
<iron-media-query query="(min-width: 1500px)" query-matches="{{wideLayout}}"></iron-media-query>
</template>
<app-drawer-layout responsive-width="[[responsiveWidth]]" force-narrow="[[_narrowNavForced]]" narrow="{{layoutNarrow}}">
<app-drawer slot="drawer" align="[[drawerAlign]]" opened="[[navigationOpened]]">
<template is="dom-if" if="[[!noToolbars]]">
<app-toolbar>
<div>API console</div>
</app-toolbar>
</template>
<div class="drawer-content-wrapper">
<api-navigation amf-model="[[amfModel]]" summary endpoints-opened on-api-navigation-selection-changed="_apiNavigationOcurred" selected="{{selectedShape}}" selected-type="{{selectedShapeType}}"></api-navigation>
<template is="dom-if" if="[[!noAttribution]]">
<div class="powered-by">
<a href="https://github.com/mulesoft/api-console" class="attribution" target="_blank" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 818.9 148"><defs><style>.cls-1{}.cls-2{font-size:60px;font-family:OpenSans, Open Sans;}</style></defs><path class="cls-1" d="M436.08,12.57a61.79,61.79,0,1,0,62.08,61.79A62,62,0,0,0,436.08,12.57Zm0,118.8a56.63,56.63,0,1,1,56.63-56.63A56.63,56.63,0,0,1,436.09,131.36Z"/><path class="cls-1" d="M420.34,102.08a28.4,28.4,0,0,1-15.87-25.84,29.25,29.25,0,0,1,4.89-16.29l20.42,30.43h12.34l20.42-30.43a29.25,29.25,0,0,1,4.89,16.29,28.55,28.55,0,0,1-14,24.87l3.93,15.06a46.47,46.47,0,0,0,2.45-81.29L436.08,71.47,412.6,34.75A46.47,46.47,0,0,0,416.45,117Z"/><polygon class="cls-1" points="544.97 80.8 529.71 48.31 521.79 48.31 521.79 100.53 529.71 100.53 529.71 65.62 542.03 91.08 547.9 91.08 559.93 65.62 559.93 100.53 567.85 100.53 567.85 48.31 559.93 48.31 544.97 80.8"/><path class="cls-1" d="M597.61,86c0,5.73-3.53,8.29-7.7,8.29s-7.48-2.5-7.48-8.29V63.34h-7.48V87.11c0,4.19.88,7.71,3.74,10.5a12.93,12.93,0,0,0,9.17,3.37,13.28,13.28,0,0,0,9.9-4.18v3.74h7.34V63.34h-7.48Z"/><path class="cls-1" d="M619.75,89.83V48.31h-7.48v42c0,5.51,3.08,10.27,10.2,10.27h4.62V94.16h-3.3C620.77,94.16,619.75,92.68,619.75,89.83Z"/><path class="cls-1" d="M645.07,62.91c-9.54,0-15.77,7-15.77,19,0,14.16,7.41,19.07,16.73,19.07,6.53,0,10.12-2,13.93-5.79L655.2,90.7a11.08,11.08,0,0,1-9,3.81c-6.09,0-9.46-4-9.46-10.41h24.13V80.8C660.85,70.24,655.05,62.91,645.07,62.91Zm-8.36,16a11.79,11.79,0,0,1,1-5.06,7.77,7.77,0,0,1,7.41-4.69,7.66,7.66,0,0,1,7.34,4.69,11.62,11.62,0,0,1,1,5.06Z"/><path class="cls-1" d="M697.78,74.93c-2.2-2-4.91-3.15-9.76-3.89l-5.94-.88a11.67,11.67,0,0,1-5.87-2.42,6.24,6.24,0,0,1-2-4.84c0-4.62,3.37-8.15,9.54-8.15,4.4,0,8.14,1,11.37,4l5.06-5c-4.47-4.18-9.31-5.94-16.21-5.94-10.86,0-17.46,6.23-17.46,15.33,0,4.25,1.25,7.55,3.82,10,2.27,2.12,5.64,3.59,9.9,4.18l6.16.89c3.09.44,4.4,1,5.73,2.2a7,7,0,0,1,2.05,5.43c0,5.06-4,8-10.78,8-5.36,0-9.54-1.17-13.35-5l-5.28,5.21c5,5.06,10.64,6.9,18.48,6.9C694.18,101,702,95.25,702,85.65,702,81.16,700.63,77.43,697.78,74.93Z"/><path class="cls-1" d="M721.76,62.91a14.88,14.88,0,0,0-11.08,4.4c-3.52,3.66-4.4,8.36-4.4,14.6s.88,11,4.4,14.67a14.88,14.88,0,0,0,11.08,4.4,15,15,0,0,0,11.15-4.4c3.52-3.66,4.4-8.36,4.4-14.67s-.88-10.94-4.4-14.6A15,15,0,0,0,721.76,62.91Zm5.5,29.19a7.65,7.65,0,0,1-5.5,2.2,7.44,7.44,0,0,1-5.42-2.2c-2.28-2.27-2.57-6.17-2.57-10.2s.29-7.92,2.57-10.2a7.39,7.39,0,0,1,5.42-2.13,7.6,7.6,0,0,1,5.5,2.13c2.27,2.27,2.57,6.16,2.57,10.2S729.54,89.83,727.27,92.1Z"/><path class="cls-1" d="M744.88,58.29V64h-4.26v5.73h4.26v30.81h7.48V69.73h7.41V64h-7.41V58.65c0-2.71,1.31-4.33,4.1-4.33h3.31V47.94h-4.7C748.1,47.94,744.88,52.93,744.88,58.29Z"/><path class="cls-1" d="M776.12,52.71h-7.48V64h-4.26v5.73h4.26V90.19c0,5.36,3.22,10.35,10.19,10.35h4.47V94.16h-3.08c-2.78,0-4.11-1.62-4.11-4.33V69.73h7.19V64h-7.19Z"/><path class="cls-1" d="M792.58,58.48a4,4,0,0,0-2.14-2.11,4.11,4.11,0,0,0-3.11,0,4.07,4.07,0,0,0-1.29.84,4,4,0,0,0-.87,1.26,3.86,3.86,0,0,0-.32,1.58,3.94,3.94,0,0,0,.32,1.6,4,4,0,0,0,.87,1.28,4,4,0,0,0,1.29.84,4.19,4.19,0,0,0,3.11,0,3.92,3.92,0,0,0,1.28-.84,4.1,4.1,0,0,0,.87-1.28,4,4,0,0,0,.32-1.6A3.86,3.86,0,0,0,792.58,58.48Zm-.66,2.94a3.34,3.34,0,0,1-.7,1.09,3.25,3.25,0,0,1-1,.72,3.19,3.19,0,0,1-1.3.26,3.24,3.24,0,0,1-2.36-1,3.35,3.35,0,0,1-.7-1.09,3.64,3.64,0,0,1-.25-1.37,3.54,3.54,0,0,1,.25-1.34,3.26,3.26,0,0,1,3.06-2.06,3.21,3.21,0,0,1,1.3.26,3.26,3.26,0,0,1,1.74,1.8,3.52,3.52,0,0,1,.25,1.34A3.62,3.62,0,0,1,791.92,61.42Z"/><path class="cls-1" d="M790.42,60a1.14,1.14,0,0,0,.35-.93,1.23,1.23,0,0,0-.4-1,1.92,1.92,0,0,0-1.24-.33h-1.81v4.68H788v-2h.77l1.28,2h.78l-1.34-2.07A1.59,1.59,0,0,0,790.42,60Zm-1.61-.19H788V58.32h1l.37,0a1,1,0,0,1,.33.1.63.63,0,0,1,.24.21A.68.68,0,0,1,790,59a.79.79,0,0,1-.1.43.61.61,0,0,1-.27.23,1.19,1.19,0,0,1-.39.09Z"/><text class="cls-2" transform="translate(19 91.93)">Powered by</text></svg>
</a>
</div>
</template>
</div>
</app-drawer>
<app-header-layout>
<template is="dom-if" if="[[!noToolbars]]">
<app-header slot="header" fixed condenses effects="waterfall">
<app-toolbar>
<paper-icon-button icon="arc:menu" drawer-toggle hidden$="[[manualNavigation]]"></paper-icon-button>
<div main-title>[[apiTitle]]</div>
<slot name="toolbar"></slot>
</app-toolbar>
</app-header>
</template>
<div class="main-content">
<slot name="content"></slot>
<template is="dom-if" if="[[isRequest]]">
<div class="method-title-area">
<h1 class="method-title">[[methodName]]</h1>
<div class="method-close-action">
<paper-button class="action-button" on-click="closeTryIt" raised>Back to docs</paper-button>
</div>
</div>
<div class="extension-banner" active$="[[extensionBannerActive]]">
<p>For better experience install API console extension. Get it from <a target="_blank" class="store-link" href="https://chrome.google.com/webstore/detail/olkpohecoakpkpinafnpppponcfojioa">Chrome Web Store</a></p>
<paper-icon-button icon="arc:close" on-click="dismissExtensionBanner"></paper-icon-button>
</div>
<api-request-panel
amf-model="[[amfModel]]"
selected="[[selectedShape]]"
narrow="[[narrow]]"
no-url-editor="[[noUrlEditor]]"
redirect-uri="[[redirectUri]]"
scroll-target="[[scrollTarget]]"
allow-custom="[[allowCustom]]"
allow-disable-params="[[allowDisableParams]]"
allow-hide-optional="[[allowHideOptional]]"
bower-location="[[bowerLocation]]"
base-uri="[[baseUri]]"
no-docs="[[noDocs]]"
events-target="[[eventsTarget]]"></api-request-panel>
</template>
<template is="dom-if" if="[[isDocs]]">
<section class="api-docs">
<api-documentation
amf-model="[[amfModel]]"
selected="[[selectedShape]]"
selected-type="[[selectedShapeType]]"
no-try-it="[[_noTryItValue]]"
narrow="[[narrow]]"
base-uri="[[baseUri]]"
inline-methods="[[inlineMethods]]"
redirect-uri="[[redirectUri]]"
scroll-target="[[scrollTarget]]"></api-documentation>
<template is="dom-if" if="[[_renderInlineTyit]]" restamp>
<div class="inline-request">
<div class="extension-banner" active$="[[extensionBannerActive]]">
<p>For better experience install API console extension. Get it from <a target="_blank" class="store-link" href="https://chrome.google.com/webstore/detail/olkpohecoakpkpinafnpppponcfojioa">Chrome Web Store</a></p>
<paper-icon-button icon="arc:close" on-click="dismissExtensionBanner"></paper-icon-button>
</div>
<api-request-panel
amf-model="[[amfModel]]"
selected="[[selectedShape]]"
narrow="[[narrow]]"
no-url-editor="[[noUrlEditor]]"
redirect-uri="[[redirectUri]]"
scroll-target="[[scrollTarget]]"
allow-custom="[[allowCustom]]"
allow-disable-params="[[allowDisableParams]]"
allow-hide-optional="[[allowHideOptional]]"
bower-location="[[bowerLocation]]"
base-uri="[[baseUri]]"
no-docs="[[noDocs]]"
events-target="[[eventsTarget]]"></api-request-panel>
</div>
</template>
</section>
</template>
</div>
</app-header-layout>
</app-drawer-layout>
<template is="dom-if" if="[[aware]]">
<raml-aware raml="{{amfModel}}" scope="[[aware]]"></raml-aware>
</template>
<paper-toast class="error-toast" id="apiLoadErrorToast"></paper-toast>
<api-console-ext-comm has-extension="{{_hasApicCorsExtension}}"></api-console-ext-comm>
<!--
The components below are optional dependencies. They will not be used until
sources of the components are included into AC bundle.
This would help build the console and only add a dependency at the build time
without statically include the dependency.
TBD:
`xhr-simple-request` component placed here will prohibit application from
using `api-request` custom event. If the application uses both this element
(by adding it's import file to the build / page) this element would be the
first one to handle the event and run the request. Any other listener
attached to the console, body or window is called after this one.
-->
<xhr-simple-request append-headers="[[appendHeaders]]" proxy="[[proxy]]" proxy-encode-url="[[proxyEncodeUrl]]"></xhr-simple-request>
<oauth1-authorization></oauth1-authorization>
<oauth2-authorization></oauth2-authorization>
</template>
<script>
/**
* # The API Console
*
* The API console for RAML (Restful Api Modeling Language) documents.
* The RAML Console allows browsing of API documentation and in-browser testing of API methods.
*
* @customElement
* @polymer
* @demo demo/index.html
* @memberof MulesoftApps
* @appliesMixin ApiElements.AmfHelperMixin
*/
class ApiConsole extends ApiElements.AmfHelperMixin(Polymer.Element) {
static get is() {return 'api-console';}
static get properties() {
return {
/**
* You can use `raml-aware` component to pass AMF data to the console.
* Raml aware uses monostate pattern to pass the data to any other
* instance of the same component and receives updates from them.
*
* When using `<raml-aware>` set it's `scope` property to some name
* and this property to the same name. Once you update `raml` property
* on the aware it updates the model in the console.
*/
aware: String,
/**
* Generated AMF json/ld model form the API spec.
* The element assumes the object of the first array item to be a
* type of `"http://raml.org/vocabularies/document#Document`
* on AMF vocabulary.
*
* It is only usefult for the element to resolve references.
*
* @type {Object|Array}
*/
amfModel: Object,
/**
* It is current selection from the navigation represented
* as an `@id` property of the AMD json/ld model.
*
* This property is updated internally when the user performs a navigation.
* Change this property (with `selectedShapeType` property if needed)
* to force the console to render specific view.
*
* ## example
* ```
* file://demo/models/api-name/api.raml#/web-api/end-points/%2Ftest-endpoint
* ```
*/
selectedShape: {
type: String,
notify: true
},
/**
* One of recognizable bby the console types of currently rendered
* documentation. It can be one of:
*
* - summary
* - documentation
* - type
* - security
* - endpoint
* - method
*
* Use it with combination of setting `selectedShape` property to control
* the view.
*/
selectedShapeType: {
type: String,
notify: true
},
/**
* Computed value, true if current selection represent a method
*/
isMethod: {
type: Boolean,
computed: '_computeIsMethod(selectedShapeType)'
},
/**
* Location of the AMF json/ld model. It can be an endpoint that
* produces AMF model or a file that contains generated model.
*
* When changed it download's data from the location
* and assigns value to the `amfModel` property.
*
* ## Example
* ```html
* <api-console model-location="https://amf-parser/domain.com"></api-console>
* ```
*/
modelLocation: {
type: String,
observer: '_modelLocationChanged'
},
/**
* Currently rendered page. It can be either `docs` or `request`.
*/
page: {
type: String,
value: 'docs',
notify: true
},
/**
* Computed value (read only), `true` when current page is the
* request panel.
*/
isRequest: {
type: Boolean,
computed: '_computeIsRequest(page)'
},
/**
* Computed value (read only), `true` when current page is the
* documentation panel.
*/
isDocs: {
type: Boolean,
computed: '_computeIsDocs(page)'
},
/**
* The API console works with API console extension that proxies
* request through Chrome extension's sandbox and eliminates CORS.
*
* The banner informing a user about the extension is rendered
* automatically unless this property is set.
*/
noExtensionBanner: {
type: Boolean,
observer: '_noExtBannerChanged'
},
/**
* When set the extension banner is rendered.
*/
extensionBannerActive: {
type: Boolean,
readOnly: true
},
_hasApicCorsExtension: {type: Boolean, observer: '_hasCorsExtensionChanged'},
/**
* Forces the console to send headers defined in this string overriding
* any used defined header.
* It can be useful if the console has to send any headers string
* to a server without user knowing about it.
* The headers should be valid HTTP headers string.
*/
appendHeaders: String,
/**
* If true it forces the console to render narrow layout.
* This hides left hand side navigation and some fonts are smaller
* (like titles).
*/
narrow: {
type: Boolean,
reflectToAttribute: true
},
/**
* If set every request made from the console will be proxied by the service provided in this
* value.
* It will prefix entered URL with the proxy value. so the call to
* `http://domain.com/path/?query=some+value` will become
* `https://proxy.com/path/http://domain.com/path/?query=some+value`
*
* If the proxy require a to pass the URL as a query parameter define value as follows:
* `https://proxy.com/path/?url=`. In this case be sure to set `proxy-encode-url`
* attribute.
*/
proxy: String,
/**
* If `proxy` is set, it will URL encode the request URL before appending it to the proxy URL.
* `http://domain.com/path/?query=some+value` will become
* `https://proxy.com/?url=http%3A%2F%2Fdomain.com%2Fpath%2F%3Fquery%3Dsome%2Bvalue`
*/
proxyEncodeUrl: Boolean,
/**
* If set then the API console hide the "try it" button from the
* method documentation view. The request and response panels still will
* be available, but to enter this section you'll have to do it
* programatically.
*/
noTryIt: Boolean,
/**
* If set, the open navigation button will be always hidden.
* The left hand side navigation will be hidden until `navigationOpened`
* property is set.
* The navigation will cover full screen, hiding the content.
* This works best with `narrow` layout.
*/
manualNavigation: Boolean,
/**
* True when navigation is opened.
*/
navigationOpened: {
type: Boolean,
notify: true
},
/**
* A width when the navigation drawer is automatically toggled to narrow
* view.
* By default it is `640px`.
*
* To control width of the navigation drawer, set `--app-drawer-width`
* CSS variable to requested size.
*/
responsiveWidth: String,
/**
* Computed value, true when the navigation drawer should be hidden
* event with wide layout.
*/
_narrowNavForced: {
type: Boolean,
computed: '_computeNarrowNavForced(manualNavigation, narrow)'
},
/**
* Location of the `bower_components` folder.
* It should be a path from server's root path including bower_components.
*/
bowerLocation: String,
/**
* OAuth2 redirect URI.
* By default the app uses `bowerLocation` to compute redirect location
* URI. If you set this value if has to work with authorization
* component meaning it has to pass auth data to the opener window or
* top frame.
* See documentation for `advanced-rest-client/oauth-authorization`
* for API details.
*/
redirectUri: String,
/**
* Hides the URL editor from the view.
* Note that the editor is still in the DOM. This property just hiddes
* it.
*/
noUrlEditor: Boolean,
/**
* A base URI for the API. To be set if RAML spec is missing `baseUri`
* declaration and this produces invalid URL input. This information
* is passed to the URL editor that prefixes the URL with `baseUri` value
* if passed URL is a relative URL.
*/
baseUri: String,
/**
* Removes the "Powered by Mulesoft" attribution from the main navigation.
* The use of this feature must be in accordance with all licensing
* and copyright protections required by the use of this software
*/
noAttribution: {
type: Boolean,
value: false
},
/**
* Computed value of AMF model of a type of `http://schema.org/WebAPI`
*
* @type {Object}
*/
webApi: {
type: Object,
computed: '_computeWebApi(amfModel)'
},
/**
* Computed title of the API
*/
apiTitle: {
type: String,
computed: '_computeApiTitle(webApi)'
},
/**
* If true then current browser is Chrome.
* Used to determine if the console should render the extension banner.
*/
isChrome: {
type: Boolean,
readOnly: true,
value: function() {
return /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
}
},
/**
* True when the main layout element renders in narrow view.
* This changes when media query breakpoint has been reached or
* when narrow property is set.
*/
layoutNarrow: {
type: Boolean,
reflectToAttribute: true
},
/**
* An alignment of the layout drawer.
* Possible values are:
* - start
* - end
*
* Default to "start".
*/
drawerAlign: String,
/**
* If set the top toolbars are not rendered.
*/
noToolbars: {
type: Boolean,
value: false
},
/**
* By default API console renders itself as an embeddable
* web component that has changed behavior of main layout elements
* (menu drawer and main view). When this option is set it renders
* layout elements in it's static positions instead relative.
*
* Note, this option is experimental and mey be removed.
*/
app: {
type: Boolean,
reflectToAttribute: true
},
/**
* When true it places try it panel next to the documentation panel.
* It is set automatically via media queries
*/
wideLayout: Boolean,
/**
* If set then it renders methods documentation inline with
* the endpoint documentation.
* When it's not set (or value is `false`, default) then it renders
* just a list of methods with links in the documentation panel
*/
inlineMethods: {type: Boolean, value: false},
_renderInlineTyit: {
type: Boolean,
computed: '_computeRenderInlineTryIt(wideLayout, isMethod, app, inlineMethods)'
},
_noTryItValue: {
type: Boolean,
computed: '_computeNoTryItValue(noTryIt, _renderInlineTyit)'
},
/**
* Computed value from the method model, name of the method.
* It is either a `displayName` or HTTP method name
*/
methodName: {
type: String,
computed: '_computeMethodName(isMethod, selectedShape, webApi)'
},
/**
* Scroll target used to observe `scroll` events.
* Set it to a parent element that is a scroll region (has overflow set)
* so the app can handle scrolling properly.
*/
scrollTarget: Object,
/**
* Option passed to the try it panel.
* When set it allows to disable parameters in an editor (headers,
* query parameters). Disabled parameter won't be used with a test call
* but won't be removed from the UI.
*/
allowDisableParams: Boolean,
/**
* Option passed to the try it panel.
* When set, editors renders "add custom" button that allows to define
* custom parameters next to API spec defined.
*/
allowCustom: Boolean,
/**
* Option passed to the try it panel.
* Enables auto hiding of optional properties (like query parameters
* or headers) and renders a checkbox to render optional items in the
* editor view.
*/
allowHideOptional: Boolean,
/**
* Prohibits rendering documentation (the icon and the
* description) in request editors.
*/
noDocs: Boolean,
/**
* A HTML element used to listen for events on.
* If you use one than more API console elements on single page
* at the same time wrap the console is a HTML element (eg div) and
* set this value to the container so the request panel only listen
* to events dispatched inside the container. Otherwise events dispatched
* by the request panel will be handled by other instances of the console.
* @type {Element}
*/
eventsTarget: Object
};
}
constructor() {
super();
this._tryitHandler = this._tryitHandler.bind(this);
}
connectedCallback() {
super.connectedCallback();
this.addEventListener('tryit-requested', this._tryitHandler);
this._notifyApicExtension();
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('tryit-requested', this._tryitHandler);
}
ready() {
super.ready();
this._initExtensionBanner();
}
/**
* Loads model from a file described in `modelLocation` property.
* This function is called automatically when the value of the property
* change.
*
* @param {String} url Model location
*/
_modelLocationChanged(url) {
if (!url) {
return;
}
const xhr = new XMLHttpRequest();
xhr.addEventListener('error', (error) => this._apiLoadErrorHandler(error));
xhr.addEventListener('loadend', () => this._apiLoadEndHandler(xhr));
xhr.open('GET', url, true);
xhr.send();
}
/**
* Called by `_modelLocationChanged` when model data are read from remote location.
* @param {XMLHttpRequest} xhr
*/
_apiLoadEndHandler(xhr) {
let data;
try {
data = JSON.parse(xhr.response);
} catch (e) {
this._apiLoadErrorHandler(e);
return;
}
this.set('amfModel', data);
}
/**
* Called by `_modelLocationChanged` when error occurred when getting API data.
* @param {Error} error
*/
_apiLoadErrorHandler(error) {
const message = 'Unable to load API model data. ' + (error.message ? error.message : '');
this.$.apiLoadErrorToast.text = message;
this.$.apiLoadErrorToast.opened = true;
}
/**
* Handler for the `tryit-requested` event. Sets current screen to
* `request`.
*/
_tryitHandler() {
this.page = 'request';
}
/**
* Resets current selection to "summary" page
*/
resetSelection() {
if (this.page !== 'docs') {
this.page = 'docs';
}
this.selectedShapeType = 'summary';
this.selectedShape = 'summary';
}
/**
* Computes value of `apiTitle` property.
*
* @param {Object} shape Shape of AMF model.
* @return {String|undefined} Description if defined.
*/
_computeApiTitle(shape) {
return this._getValue(shape, this.ns.schema.schemaName);
}
/**
* Computes value for `isRequest` property.
*
* @param {?String} page Currently selected page.
* @return {Boolean}
*/
_computeIsRequest(page) {
return page === 'request';
}
/**
* Computes value for `isDocs` property.
*
* @param {?String} page Currently selected page.
* @return {Boolean}
*/
_computeIsDocs(page) {
return page === 'docs';
}
/**
* Renders the extension banner if is Chrome and extension is not detected.
*/
_initExtensionBanner() {
if (!this.isChrome || this.noExtensionBanner) {
return;
}
setTimeout(() => {
if (!this.noExtensionBanner && !this._hasApicCorsExtension) {
this._setExtensionBannerActive(true);
}
});
}
/**
* Dismisses Chrome extension banner.
*/
dismissExtensionBanner() {
this._setExtensionBannerActive(false);
}
/**
* Handler for the navigation event dispatched by the `api-navigation`
* component.
*
* @param {CustomEvent} e
*/
_apiNavigationOcurred(e) {
const isPassive = e.detail.passive === true;
if (!isPassive && this.page !== 'docs') {
this.closeTryIt();
}
if (e.detail.selected !== this.selectedShape) {
this.selectedShape = e.detail.selected;
}
if (e.detail.type !== this.selectedShapeType) {
this.selectedShapeType = e.detail.type;
}
}
/**
* Closes "try it" panel and restores docs view.
*/
closeTryIt() {
this.page = 'docs';
}
/**
* Computes value of `_narrowNavForced` property.
*
* @param {Boolean} manualNavigation
* @param {Boolean} narrow
* @return {Boolean}
*/
_computeNarrowNavForced(manualNavigation, narrow) {
return !!(manualNavigation || narrow);
}
/**
* When the console is initialized when being hidden
* it may not layout properly. The app drawer layout component
* positions elements statically so if the console is hidden it cannot do
* this properly. In this case call `resetLayout()` function
* when getting the console back from the hidden state.
*/
resetLayout() {
this.shadowRoot.querySelector('app-drawer-layout').notifyResize();
}
/**
* Dispatches `api-console-ready` event that is used by APIC extension
* so it can initialize itself when handled
*/
_notifyApicExtension() {
this.dispatchEvent(new CustomEvent('api-console-ready', {
bubbles: true,
composed: true
}));
}
/**
* Controls behavior if the extension banner.
* @param {Boolean} value Current value of `noExtensionBanner` property
*/
_noExtBannerChanged(value) {
if (value && this.extensionBannerActive) {
this._setExtensionBannerActive(false);
}
}
_hasCorsExtensionChanged(value) {
if (value && this.extensionBannerActive) {
this._setExtensionBannerActive(false);
}
}
/**
* Computes value of `isMethod` proiperty.
* @param {String} selectedShapeType Current value of `selectedShapeType`
* property
* @return {Boolean} True if current selection represent a method
*/
_computeIsMethod(selectedShapeType) {
return selectedShapeType === 'method';
}
/**
* Computes value for `_renderInlineTyit` property.
* @param {Boolean} wideLayout
* @param {Boolean} isMethod
* @param {Boolean} app
* @param {Boolean} inlineMethods
* @return {Boolean} True if is wideLayout, it is a method, it is the app
* and when inlineMethods is not set.
*/
_computeRenderInlineTryIt(wideLayout, isMethod, app, inlineMethods) {
if (!wideLayout || !app || !isMethod || inlineMethods) {
return false;
}
return wideLayout && isMethod;
}
_computeNoTryItValue(noTryIt, renderInlineTyit) {
if (renderInlineTyit) {
return true;
}
return noTryIt;
}
/**
* Computes method name for not-wide view, where the request panel
* has close button.
* @param {Boolean} isMethod Current state of `isMethod` property
* @param {String} selected Curerently selected AMF shape (@id).
* @param {Object} webApi Computed AMF WebAPI model.
* @return {String|Undefined} Name of current method (verb) as RAML's
* `displayName` property or name of the HTTP method.
*/
_computeMethodName(isMethod, selected, webApi) {
if (!isMethod || !selected || !webApi) {
return;
}
let method;
try {
method = this._computeMethodModel(webApi, selected);
} catch (_) {
return;
}
if (!method) {
return;
}
let name = this._getValue(method, this.ns.schema.schemaName);
if (!name) {
name = this._getValue(method, this.ns.w3.hydra.core + 'method');
}
return name;
}
}
window.customElements.define(ApiConsole.is, ApiConsole);
</script>
</dom-module>