Skip to content

Commit

Permalink
updated the Add Definition modal to include an optional example
Browse files Browse the repository at this point in the history
  • Loading branch information
EricWittmann committed Mar 3, 2017
1 parent 4a30e88 commit 0381112
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import {ICommand, AbstractCommand} from "../commands.manager";
import {OasDocument, Oas20Document, Oas20DefinitionSchema} from "oai-ts-core";
import {OasDocument, Oas20Document, Oas20DefinitionSchema, Oas20PropertySchema, JsonSchemaType} from "oai-ts-core";

/**
* A command used to create a new definition in a document.
Expand All @@ -25,11 +25,13 @@ export class NewDefinitionCommand extends AbstractCommand implements ICommand {

private _defExisted: boolean;
private _newDefinitionName: string;
private _newDefinitionExample: string;
private _nullDefinitions: boolean;

constructor(definitionName: string) {
constructor(definitionName: string, example: string) {
super();
this._newDefinitionName = definitionName;
this._newDefinitionExample = example;
}

/**
Expand All @@ -47,6 +49,13 @@ export class NewDefinitionCommand extends AbstractCommand implements ICommand {
if (this.isNullOrUndefined(doc.definitions.definition(this._newDefinitionName))) {
let definition: Oas20DefinitionSchema = doc.definitions.createDefinitionSchema(this._newDefinitionName);
doc.definitions.addDefinition(this._newDefinitionName, definition);

// TODO replace this with some code that processes the example and generates a schema
let pschema: Oas20PropertySchema = definition.createPropertySchema("property-1");
definition.addProperty("property-1", pschema);
pschema.type = JsonSchemaType.string;
pschema.format = "date-time";

this._defExisted = false;
} else {
this._defExisted = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ <h2>{{ document().info.title }}</h2>
<span class="section-label">Definitions</span>
</a>
<button class="btn btn-sm btn-default pull-right"
(click)="addDefinitionModal.show(); initAddDefinition()"><span class="fa fa-plus"></span></button>
(click)="addDefinitionModal.show()"><span class="fa fa-plus"></span></button>
</div>
<div class="section-body collapse in" id="definition-section-body">
<div definition-item class="api-definition" *ngFor="let defName of definitionNames()" [name]="defName"
Expand All @@ -66,7 +66,7 @@ <h2>{{ document().info.title }}</h2>
<span>Reusable types are useful!</span>
<span>&nbsp;</span>
<button class="btn btn-xs btn-default pull-right" style="margin-top: 0px"
(click)="addDefinitionModal.show(); initAddDefinition()">Add Now</button>
(click)="addDefinitionModal.show()">Add Now</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -105,6 +105,66 @@ <h2>{{ document().info.title }}</h2>
<definition-form [definition]="selectedDefinition()" (onCommand)="onCommand($event)" class="editor-detail-form"
(onDeselect)="deselectDefinition()" *ngIf="selectedType === 'definition'"></definition-form>
</div>

<!-- Add Definition Dialog -->
<div bsModal #addDefinitionModal="bs-modal" class="modal fade" id="addDefinitionModal" tabindex="-1" role="dialog" aria-labelledby="addDefinitionModalLabel"
role="dialog" aria-hidden="true" (onShown)="initAddDefinition(); addDefinitionInput.focus(); addDefinitionInput.select()">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="addDefinitionModal.hide()">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="addDefinitionModalLabel">Add Definition</h4>
</div>
<div class="modal-body">
<p>Enter a new definition name below and then click Add.</p>
<form id="adddef-form" class="form-horizontal" #addDefinitionForm="ngForm" data-dismiss="modal">
<div class="form-group">
<label class="col-sm-2 control-label" for="definitionName">Name</label>
<div class="col-sm-10">
<input #addDefinitionInput name="definitionName" type="text" id="definitionName" class="form-control"
placeholder="Enter a Definition Name"
required [(ngModel)]="modals.addDefinition.definitionName">
</div>
</div>
<div class="section example-section">
<div class="section-header">
<a data-toggle="collapse" data-target="#example-section-body">
<span class="section-label">FROM EXAMPLE (optional)</span>
</a>
</div>
<div class="section-body collapse in" id="example-section-body">
<div class="explanation">
Input a JSON formatted sample below and we'll do our best to initialize the Definition's schema
based on the example.
</div>
<div class="example">
<ace-editor #exampleEditor
[theme]="'eclipse'"
[mode]="'json'"
[durationBeforeCallback]="350"
(textChanged)="setExampleDefinition($event)"
style="position: relative; height: 200px; border: 1px solid #ccc; width: 100%"></ace-editor>
<button class="btn btn-default btn-xs" style="margin-top: 10px;" type="button"
[disabled]="!isExampleDefinitionFormattable()" (click)="formatExampleDefinition()">
<span class="fa fa-fw fa-indent"></span>
<span>Format</span>
</button>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" (click)="addDefinition()"
[disabled]="!addDefinitionForm.form.valid || !isExampleDefinitionValid()">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal" (click)="addDefinitionModal.hide()">Cancel</button>
</div>
</div>
</div>
</div>

</div>

<!-- Add Path Dialog -->
Expand Down Expand Up @@ -139,36 +199,3 @@ <h4 class="modal-title" id="addPathModalLabel">Add Path</h4>
</div>
</div>


<!-- Add Definition Dialog -->
<div bsModal #addDefinitionModal="bs-modal" class="modal fade" id="addDefinitionModal" tabindex="-1" role="dialog" aria-labelledby="addDefinitionModalLabel"
role="dialog" aria-hidden="true" (onShown)="addDefinitionInput.focus(); addDefinitionInput.select()">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="addDefinitionModal.hide()">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="addDefinitionModalLabel">Add Definition</h4>
</div>
<div class="modal-body">
<p>Enter a new definition name below and then click Add.</p>
<form id="adddef-form" class="form-horizontal" (submit)="addDefinition()" #addDefinitionForm="ngForm" data-dismiss="modal">
<div class="form-group">
<label class="col-sm-2 control-label" for="definitionName">Name</label>
<div class="col-sm-10">
<input #addDefinitionInput name="definitionName" type="text" id="definitionName" class="form-control"
placeholder="Enter a Definition Name"
required [(ngModel)]="modals.addDefinition.definitionName">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" (click)="addDefinition()"
[disabled]="!addDefinitionForm.form.valid">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal" (click)="addDefinitionModal.hide()">Cancel</button>
</div>
</div>
</div>
</div>
62 changes: 60 additions & 2 deletions front-end/app/studio/pages/apis/{apiId}/editor/editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {CommandsManager, ICommand} from "./commands.manager";
import {ModalDirective} from "ng2-bootstrap";
import {NewPathCommand} from "./commands/new-path.command";
import {NewDefinitionCommand} from "./commands/new-definition.command";
import {AceEditorDirective} from "ng2-ace-editor";


@Component({
Expand All @@ -38,10 +39,15 @@ export class ApiEditorComponent {

@ViewChild("addPathModal") public addPathModal: ModalDirective;
@ViewChild("addDefinitionModal") public addDefinitionModal: ModalDirective;
@ViewChild("exampleEditor") exampleEditor: AceEditorDirective;

public modals: any = {
addPath: {},
addDefinition: {}
addDefinition: {
exampleDefinition: "",
exampleDefinitionValid: true,
exampleDefinitionFormattable: false
}
};

private _library: OasLibraryUtils = new OasLibraryUtils();
Expand Down Expand Up @@ -261,6 +267,8 @@ export class ApiEditorComponent {
*/
public initAddDefinition(): void {
this.modals.addDefinition.definitionName = "";
this.modals.addDefinition.exampleDefinition = "";
this.exampleEditor.setText("");
}

/**
Expand Down Expand Up @@ -356,7 +364,8 @@ export class ApiEditorComponent {
* Called when the user fills out the Add Definition modal dialog and clicks Add.
*/
public addDefinition(): void {
let command: ICommand = new NewDefinitionCommand(this.modals.addDefinition.definitionName);
let command: ICommand = new NewDefinitionCommand(this.modals.addDefinition.definitionName,
this.modals.addDefinition.exampleDefinition);
this.onCommand(command);
this.addDefinitionModal.hide();
this.selectDefinition(this.modals.addDefinition.definitionName);
Expand Down Expand Up @@ -415,4 +424,53 @@ export class ApiEditorComponent {
return name.toLowerCase().indexOf(this.filterCriteria) != -1;
}

/**
* Called when the user changes the example definition in the Add Definition modal dialog.
* @param definition
*/
public setExampleDefinition(definition: string): void {
console.info("Setting Example Def: %s", definition);
this.modals.addDefinition.exampleDefinition = definition;
if (this.modals.addDefinition.exampleDefinition === "") {
this.modals.addDefinition.exampleDefinitionValid = true;
this.modals.addDefinition.exampleDefinitionFormattable = false;
} else {
try {
JSON.parse(this.modals.addDefinition.exampleDefinition);
this.modals.addDefinition.exampleDefinitionValid = true;
this.modals.addDefinition.exampleDefinitionFormattable = true;
} catch (e) {
this.modals.addDefinition.exampleDefinitionValid = false;
this.modals.addDefinition.exampleDefinitionFormattable = false;
}
}
}

/**
* Returns true if it's possible to format the example definition (it must be non-null and
* syntactically valid).
* @return {boolean}
*/
public isExampleDefinitionFormattable(): boolean {
return this.modals.addDefinition.exampleDefinitionFormattable;
}

/**
* Returns true if the example definition added by the user in the Add Definition modal
* dialog is valid (syntactically).
* @return {boolean}
*/
public isExampleDefinitionValid(): boolean {
return this.modals.addDefinition.exampleDefinitionValid;
}

/**
* Called to format the example definition.
*/
public formatExampleDefinition(): void {
let jsObj: any = JSON.parse(this.modals.addDefinition.exampleDefinition);
let nsrcStr: string = JSON.stringify(jsObj, null, 4);
this.exampleEditor.setText(nsrcStr);
}

}

0 comments on commit 0381112

Please sign in to comment.