@@ -45,11 +45,19 @@ import {
4545 distinctUntilChanged ,
4646 catchError ,
4747} from 'rxjs/operators' ;
48- import { HttpClient , HttpErrorResponse } from '@angular/common/http' ;
48+ import {
49+ HttpClient ,
50+ HttpErrorResponse ,
51+ HttpBackend ,
52+ HttpHeaders ,
53+ } from '@angular/common/http' ;
4954import { BASE_URL } from 'src/app/shared/constants/urls' ;
5055import { Subscription , of , forkJoin } from 'rxjs' ;
5156import { DfApiQuickstartComponent } from '../df-api-quickstart/df-api-quickstart.component' ;
5257import { ApiDocJson } from 'src/app/shared/types/files' ;
58+ import { healthCheckEndpointsInfo } from '../constants/health-check-endpoints' ;
59+ import { MatSlideToggleModule } from '@angular/material/slide-toggle' ;
60+ import { FormsModule } from '@angular/forms' ;
5361
5462interface ServiceResponse {
5563 resource : Array < {
@@ -77,6 +85,7 @@ interface HealthCheckResult {
7785 MatSelectModule ,
7886 MatIconModule ,
7987 TranslocoModule ,
88+ FormsModule ,
8089 AsyncPipe ,
8190 NgIf ,
8291 NgFor ,
@@ -88,6 +97,8 @@ interface HealthCheckResult {
8897 MatExpansionModule ,
8998 MatCardModule ,
9099 DfApiQuickstartComponent ,
100+ MatSlideToggleModule ,
101+ FormsModule ,
91102 ] ,
92103} )
93104export class DfApiDocsComponent implements OnInit , AfterContentInit , OnDestroy {
@@ -103,38 +114,15 @@ export class DfApiDocsComponent implements OnInit, AfterContentInit, OnDestroy {
103114 apiDocJson : ApiDocJson ;
104115 apiKeys : ApiKeyInfo [ ] = [ ] ;
105116 faCopy = faCopy ;
117+ expandSchema = false ;
106118
107119 private subscriptions : Subscription [ ] = [ ] ;
108120 healthStatus : 'loading' | 'healthy' | 'unhealthy' | 'warning' = 'loading' ;
109121 healthError : string | null = null ;
110122 serviceName : string | null = null ;
111123 showUnhealthyErrorDetails = false ;
112- // Mapping of service types to their corresponding endpoints, probably would be better to move to the back-end
113- healthCheckEndpointsInfo : {
114- [ key : string ] : { endpoint : string ; title : string ; description : string } [ ] ;
115- } = {
116- Database : [
117- {
118- endpoint : '/_schema' ,
119- title : 'View Available Schemas' ,
120- description :
121- 'This command fetches a list of schemas from your connected database' ,
122- } ,
123- {
124- endpoint : '/_table' ,
125- title : 'View Tables in Your Database' ,
126- description : 'This command lists all tables in your database' ,
127- } ,
128- ] ,
129- File : [
130- {
131- endpoint : '/' ,
132- title : 'View Available Folders' ,
133- description :
134- 'This command fetches a list of folders from your connected file storage' ,
135- } ,
136- ] ,
137- } ;
124+
125+ private rawHttp : HttpClient ;
138126
139127 constructor (
140128 private activatedRoute : ActivatedRoute ,
@@ -145,14 +133,17 @@ export class DfApiDocsComponent implements OnInit, AfterContentInit, OnDestroy {
145133 private clipboard : Clipboard ,
146134 private snackBar : MatSnackBar ,
147135 private currentServiceService : DfCurrentServiceService ,
148- private http : HttpClient
149- ) { }
136+ private http : HttpClient ,
137+ private httpBackend : HttpBackend
138+ ) {
139+ this . rawHttp = new HttpClient ( httpBackend ) ;
140+ }
150141 isDarkMode = this . themeService . darkMode$ ;
151142 ngOnInit ( ) : void {
152143 // Get the service name from the route
153144 this . serviceName = this . activatedRoute . snapshot . params [ 'name' ] ;
154145
155- // First fetch the service ID by name
146+ // First fetch the service ID by name (use normal http)
156147 if ( this . serviceName ) {
157148 this . subscriptions . push (
158149 this . http
@@ -201,51 +192,8 @@ export class DfApiDocsComponent implements OnInit, AfterContentInit, OnDestroy {
201192 }
202193
203194 ngAfterContentInit ( ) : void {
204- const apiDocumentation = this . apiDocJson ;
205195 this . checkApiHealth ( ) ;
206-
207- SwaggerUI ( {
208- spec : apiDocumentation ,
209- domNode : this . apiDocElement ?. nativeElement ,
210- requestInterceptor : ( req : SwaggerUI . Request ) => {
211- req [ 'headers' ] [ SESSION_TOKEN_HEADER ] = this . userDataService . token ;
212- req [ 'headers' ] [ API_KEY_HEADER ] = environment . dfApiDocsApiKey ;
213- // Parse the request URL
214- const url = new URL ( req [ 'url' ] ) ;
215- const params = new URLSearchParams ( url . search ) ;
216- // Decode all parameters
217- params . forEach ( ( value , key ) => {
218- params . set ( key , decodeURIComponent ( value ) ) ;
219- } ) ;
220- // Update the URL with decoded parameters
221- url . search = params . toString ( ) ;
222- req [ 'url' ] = url . toString ( ) ;
223- return req ;
224- } ,
225- showMutatedRequest : true ,
226- onComplete : ( ) => {
227- if (
228- this . apiDocElement &&
229- this . apiDocElement . nativeElement &&
230- this . swaggerInjectedContentContainerRef &&
231- this . swaggerInjectedContentContainerRef . nativeElement
232- ) {
233- const swaggerContainer = this . apiDocElement . nativeElement ;
234- const customContentNode =
235- this . swaggerInjectedContentContainerRef . nativeElement ;
236-
237- const infoContainer = swaggerContainer . querySelector (
238- '.information-container .main'
239- ) ;
240-
241- this . injectCustomContent (
242- swaggerContainer ,
243- infoContainer ,
244- customContentNode
245- ) ;
246- }
247- } ,
248- } ) ;
196+ this . generateSwaggerWithApiKey ( this . apiDocJson ) ;
249197 }
250198
251199 ngOnDestroy ( ) : void {
@@ -255,7 +203,7 @@ export class DfApiDocsComponent implements OnInit, AfterContentInit, OnDestroy {
255203
256204 private checkApiHealth ( ) : void {
257205 let endpointsInfoToValidate =
258- this . healthCheckEndpointsInfo [ this . apiDocJson . info . group ] ;
206+ healthCheckEndpointsInfo [ this . apiDocJson . info . group ] ;
259207 if ( this . serviceName && endpointsInfoToValidate ) {
260208 // Perform health check
261209 this . performHealthCheck ( endpointsInfoToValidate [ 0 ] . endpoint ) ;
@@ -322,6 +270,70 @@ export class DfApiDocsComponent implements OnInit, AfterContentInit, OnDestroy {
322270 this . showUnhealthyErrorDetails = ! this . showUnhealthyErrorDetails ;
323271 }
324272
273+ private generateSwaggerWithApiKey ( apiDocumentation : ApiDocJson ) : void {
274+ SwaggerUI ( {
275+ spec : apiDocumentation ,
276+ domNode : this . apiDocElement ?. nativeElement ,
277+ requestInterceptor : ( req : SwaggerUI . Request ) => {
278+ req [ 'headers' ] [ SESSION_TOKEN_HEADER ] = this . userDataService . token ;
279+ req [ 'headers' ] [ API_KEY_HEADER ] = environment . dfApiDocsApiKey ;
280+ // Parse the request URL
281+ const url = new URL ( req [ 'url' ] ) ;
282+ const params = new URLSearchParams ( url . search ) ;
283+ // Decode all parameters
284+ params . forEach ( ( value , key ) => {
285+ params . set ( key , decodeURIComponent ( value ) ) ;
286+ } ) ;
287+ // Update the URL with decoded parameters
288+ url . search = params . toString ( ) ;
289+ req [ 'url' ] = url . toString ( ) ;
290+ return req ;
291+ } ,
292+ showMutatedRequest : true ,
293+ onComplete : ( ) => {
294+ if (
295+ this . apiDocElement &&
296+ this . apiDocElement . nativeElement &&
297+ this . swaggerInjectedContentContainerRef &&
298+ this . swaggerInjectedContentContainerRef . nativeElement
299+ ) {
300+ const swaggerContainer = this . apiDocElement . nativeElement ;
301+ const customContentNode =
302+ this . swaggerInjectedContentContainerRef . nativeElement ;
303+
304+ const infoContainer = swaggerContainer . querySelector (
305+ '.information-container .main'
306+ ) ;
307+
308+ this . injectCustomContent (
309+ swaggerContainer ,
310+ infoContainer ,
311+ customContentNode
312+ ) ;
313+ }
314+ } ,
315+ } ) ;
316+ }
317+
318+ reloadApiDocs ( ) {
319+ if ( ! this . serviceName ) return ;
320+ const params = this . expandSchema ? '?expand_schema=true' : '' ;
321+ const headers = new HttpHeaders ( {
322+ 'X-DreamFactory-API-Key' : environment . dfApiDocsApiKey ,
323+ 'X-DreamFactory-Session-Token' : this . userDataService . token || '' ,
324+ } ) ;
325+ this . rawHttp
326+ . get < any > ( `${ BASE_URL } /api_docs/${ this . serviceName } ${ params } ` , {
327+ headers,
328+ } )
329+ . subscribe ( data => {
330+ if ( data ) {
331+ this . apiDocJson = data ;
332+ }
333+ this . ngAfterContentInit ( ) ;
334+ } ) ;
335+ }
336+
325337 private injectCustomContent (
326338 swaggerContainer : HTMLElement ,
327339 infoContainer : HTMLElement | null ,
0 commit comments