Skip to content

Commit

Permalink
Examples column added to operation details table (#2012)
Browse files Browse the repository at this point in the history
  • Loading branch information
JMach1 authored Dec 1, 2022
1 parent f30cc70 commit 0939b62
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
Automatically scroll to operation name
</label>
</div>
<div class="form-group">
<label for="showExamples" class="form-label">
<input type="checkbox" id="showExamples" name="showExamples"
data-bind="checked: showExamples" />
Show field examples in a table column
</label>
</div>
<div class="form-group">
<label for="defaultSchemaView" class="form-label">
Default schema view
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export class OperationDetailsEditor {
public readonly enableScrollTo: ko.Observable<boolean>;
public readonly defaultSchemaView: ko.Observable<string>;
public readonly useCorsProxy: ko.Observable<boolean>;
public readonly showExamples: ko.Observable<boolean>;

constructor() {
this.enableConsole = ko.observable();
this.enableScrollTo = ko.observable();
this.defaultSchemaView = ko.observable();
this.useCorsProxy = ko.observable();
this.showExamples = ko.observable();
}

@Param()
Expand All @@ -32,18 +34,21 @@ export class OperationDetailsEditor {
this.useCorsProxy(this.model.useCorsProxy);
this.enableScrollTo(this.model.enableScrollTo);
this.defaultSchemaView(this.model.defaultSchemaView || "table");

this.showExamples(this.model.showExamples);

this.enableConsole.subscribe(this.applyChanges);
this.useCorsProxy.subscribe(this.applyChanges);
this.enableScrollTo.subscribe(this.applyChanges);
this.defaultSchemaView.subscribe(this.applyChanges);
this.showExamples.subscribe(this.applyChanges);
}

private applyChanges(): void {
this.model.enableConsole = this.enableConsole();
this.model.useCorsProxy = this.useCorsProxy();
this.model.enableScrollTo = this.enableScrollTo();
this.model.defaultSchemaView = this.defaultSchemaView();
this.model.showExamples = this.showExamples();
this.onChange(this.model);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class OperationDetailsViewModelBinder implements ViewModelBinder<Operatio
enableConsole: model.enableConsole,
enableScrollTo: model.enableScrollTo,
defaultSchemaView: model.defaultSchemaView,
useCorsProxy: model.useCorsProxy
useCorsProxy: model.useCorsProxy,
showExamples: model.showExamples,
};

viewModel.config(JSON.stringify(runtimeConfig));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ <h4>Response headers</h4>
<div class="tab-content">
<!-- ko if: representation.typeName -->
<type-definition
params="{ apiName: $component.api().name, operationName: $component.operation().name, definition: $component.getDefinitionForRepresentation(representation), defaultSchemaView: $component.defaultSchemaView }">
params="{ apiName: $component.api().name, operationName: $component.operation().name, definition: $component.getDefinitionForRepresentation(representation), defaultSchemaView: $component.defaultSchemaView, examples: $component.examples()[response.identifier]?.[representation.contentType] }">
</type-definition>
<!-- /ko -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Component, RuntimeComponent, OnMounted, OnDestroyed, Param } from "@pap
import { Api } from "../../../../../models/api";
import { Operation } from "../../../../../models/operation";
import { ApiService } from "../../../../../services/apiService";
import { AuthorizationServer } from "./../../../../../models/authorizationServer";
import { Representation } from "./../../../../../models/representation";
import { AuthorizationServer } from "../../../../../models/authorizationServer";
import { Representation } from "../../../../../models/representation";
import { RouteHelper } from "../../../../../routing/routeHelper";
import { Utils } from "../../../../../utils";
import { TypeOfApi } from "../../../../../constants";
Expand All @@ -17,7 +17,8 @@ import {
TypeDefinitionPropertyTypeArrayOfReference,
TypeDefinitionPropertyTypeArrayOfPrimitive,
TypeDefinitionPropertyTypeCombination,
TypeDefinitionPropertyTypePrimitive
TypeDefinitionPropertyTypePrimitive,
OperationExamples,
} from "../../../../../models/typeDefinition";
import { OAuthService } from "../../../../../services/oauthService";
import { LruCache } from "@paperbits/common/caching/lruCache";
Expand Down Expand Up @@ -49,6 +50,7 @@ export class OperationDetails {
public readonly associatedAuthServer: ko.Observable<AuthorizationServer>;
public readonly apiType: ko.Observable<string>;
public readonly protocol: ko.Computed<string>;
public readonly examples: ko.Observable<OperationExamples>;

constructor(
private readonly apiService: ApiService,
Expand Down Expand Up @@ -112,6 +114,8 @@ export class OperationDetails {

return api.protocols?.join(", ");
});
this.examples = ko.observable({});

this.apiType = ko.observable();
this.onRouteChange = this.onRouteChange.bind(this);

Expand All @@ -132,6 +136,9 @@ export class OperationDetails {
@Param()
public defaultSchemaView: ko.Observable<string>;

@Param()
public showExamples: boolean;

@OnMounted()
public async initialize(): Promise<void> {
const apiName = this.routeHelper.getApiName();
Expand Down Expand Up @@ -210,6 +217,7 @@ export class OperationDetails {

if (operation) {
await this.loadDefinitions(operation);
if (this.showExamples) this.parseExamples(operation);
this.operation(operation);
}
else {
Expand Down Expand Up @@ -329,6 +337,40 @@ export class OperationDetails {
return result;
}

private parseExamples(operation: Operation): void {
const examples = operation.getMeaningfulResponses().reduce((acc, cur) => {
const representations = cur.meaningfulRepresentations();
if (!representations || !representations.length) return acc;

const examplesObj = {}
representations.forEach(representation => {
const value = representation.examples?.[0]?.value;
if (!value) return;

let valueObj;
try {
valueObj = JSON.parse(value);
} catch (e) {
return;
}

const contentTypeObj = {}
Object.entries(valueObj).forEach(([key, val]) => {
if (typeof val === 'object') return
contentTypeObj[key] = val.toString();
})

if (Object.keys(contentTypeObj).length) examplesObj[representation.contentType] = contentTypeObj;
});
if (!Object.keys(examplesObj).length) return acc;

acc[cur.identifier] = examplesObj;
return acc;
}, {} as OperationExamples);

this.examples(examples);
}

public async loadGatewayInfo(apiName: string): Promise<void> {
const hostnames = await this.apiService.getApiHostnames(apiName);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- ko if: properties.length > 0 -->

<div role="table" class="table-preset" data-bind="css: readOnly === true ? 'table-preset-schema-readonly' : 'table-preset-schema'">
<div role="table" class="table-preset table-preset-schema" data-bind="css: {'table-preset-schema-examples': $component.examples, 'table-preset-schema-readonly': readOnly}">
<div class="d-contents" role="rowgroup">
<div class="d-contents" role="row">
<div role="columnheader" class="table-preset-head text-truncate">Name</div>
Expand All @@ -9,6 +9,9 @@
<div role="columnheader" class="table-preset-head text-truncate">Read-only</div>
<!-- /ko -->
<div role="columnheader" class="table-preset-head text-truncate">Type</div>
<!-- ko if: $component.examples -->
<div role="columnheader" class="table-preset-head text-truncate">Example</div>
<!-- /ko -->
<div role="columnheader" class="table-preset-head">Description</div>
</div>
</div>
Expand Down Expand Up @@ -63,6 +66,9 @@

<!-- /ko -->
</div>
<!-- ko if: $component.examples -->
<div role="cell" class="text-truncate" data-bind="text: $component.examples[property.name], attr: {title: $component.examples[property.name]}"></div>
<!-- /ko -->
<div role="cell" data-bind="markdown: property.description"></div>
</div>
<!-- /ko -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export class TypeDefinitionViewModel {
@Param()
public defaultSchemaView: ko.Observable<string>;

@Param()
public examples?: Record<string, string>;

@OnMounted()
public initialize(): void {
this.schemaView(this.defaultSchemaView() || "table");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Contract } from "@paperbits/common";

export interface OperationDetailsContract extends Contract {
export interface OperationDetailsContract extends Contract {
/**
* Indicates whether "Try" button should appear on the operation details widget.
*/
Expand All @@ -20,4 +20,9 @@ export interface OperationDetailsContract extends Contract {
* Indicates whether the Test console should use CORS proxy vs direct calls from the browser.
*/
useCorsProxy?: boolean;

/**
* Show operation attribute values examples in a column in tables.
*/
showExamples?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export class OperationDetailsModel {
*/
public useCorsProxy?: boolean;

/**
* Show operation attribute values examples in a column in tables.
*/
public showExamples?: boolean;

constructor() {
this.enableConsole = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class OperationDetailsModelBinder implements IModelBinder<OperationDetail
model.enableScrollTo = contract.enableScrollTo !== undefined && contract.enableScrollTo === true;
model.defaultSchemaView = contract.defaultSchemaView || "table";
model.useCorsProxy = contract.useCorsProxy;
model.showExamples = contract.showExamples || false;

return model;
}
Expand All @@ -29,7 +30,8 @@ export class OperationDetailsModelBinder implements IModelBinder<OperationDetail
enableConsole: model.enableConsole,
enableScrollTo: model.enableScrollTo,
defaultSchemaView: model.defaultSchemaView,
useCorsProxy: model.useCorsProxy
useCorsProxy: model.useCorsProxy,
showExamples: model.showExamples,
};

return contract;
Expand Down
12 changes: 7 additions & 5 deletions src/models/typeDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface ProcessedCombinationPropertiesObject {
combinationRequiredPropereties?: string[];
}

export type OperationExamples = Record<string, Record<string, Record<string, string>>>;

export abstract class TypeDefinitionPropertyType {
public displayAs: string;

Expand Down Expand Up @@ -282,11 +284,11 @@ export class TypeDefinitionObjectProperty extends TypeDefinitionProperty {
processedTypeDefinitionsArray = combinationPropertiesProcessed.combinationReferenceObjectsArray;
processedTypeDefinitionsArray.push(
new TypeDefinition(
"Other properties",
"Other properties",
{
properties: combinationPropertiesProcessed.combinationOtherProperties,
required: combinationPropertiesProcessed.combinationRequiredPropereties
},
},
definitions
));

Expand All @@ -305,8 +307,8 @@ export class TypeDefinitionObjectProperty extends TypeDefinitionProperty {
if (combinationArrayItem.allOf || combinationArrayItem.anyOf || combinationArrayItem.oneOf) {
const { combinationType, combinationArray } = this.destructCombination(combinationArrayItem);
processedCombinationPropertiesObject = this.processCombinationProperties(combinationArray, definitions, processedCombinationPropertiesObject);
}
}

if (combinationArrayItem.$ref) {
const combinationReferenceName = this.getTypeNameFromRef(combinationArrayItem.$ref);
processedCombinationPropertiesObject.combinationReferencesNames.push(combinationReferenceName);
Expand All @@ -317,7 +319,7 @@ export class TypeDefinitionObjectProperty extends TypeDefinitionProperty {
if (combinationArrayItem.required) {
processedCombinationPropertiesObject.combinationRequiredPropereties = combinationArrayItem.required;
}

if (combinationArrayItem.properties) {
processedCombinationPropertiesObject.combinationOtherProperties = { ...processedCombinationPropertiesObject.combinationOtherProperties, ...combinationArrayItem.properties };
}
Expand Down
8 changes: 8 additions & 0 deletions src/themes/website/styles/tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,18 @@ $body-bg: none;
grid-template-columns: minmax(150px, 350px) 100px 200px minmax(350px, 1fr);
}

.table-preset-schema-examples {
grid-template-columns: minmax(150px, 350px) 100px 150px 150px minmax(350px, 1fr);
}

.table-preset-schema-readonly {
grid-template-columns: minmax(150px, 350px) 100px 100px 200px minmax(350px, 1fr);
}

.table-preset-schema-examples.table-preset-schema-readonly {
grid-template-columns: minmax(150px, 350px) 100px 100px 100px 150px minmax(350px, 1fr);
}

.table-preset-definitions {
grid-template-columns: minmax(150px, 350px) minmax(350px, 1fr);
}
Expand Down

0 comments on commit 0939b62

Please sign in to comment.