mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 17:30:46 +00:00
Migrate Stored Procedure tab to react (#894)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
This commit is contained in:
70
src/Explorer/Tabs/StoredProcedureTab/StoredProcedureTab.tsx
Normal file
70
src/Explorer/Tabs/StoredProcedureTab/StoredProcedureTab.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from "react";
|
||||
import { ExecuteSprocResult } from "../../../Common/dataAccess/executeStoredProcedure";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import Explorer from "../../Explorer";
|
||||
import StoredProcedure from "../../Tree/StoredProcedure";
|
||||
import ScriptTabBase from "../ScriptTabBase";
|
||||
import StoredProcedureTabComponent, {
|
||||
IStoredProcTabComponentProps,
|
||||
IStorProcTabComponentAccessor,
|
||||
} from "./StoredProcedureTabComponent";
|
||||
|
||||
export interface IStoredProcTabProps {
|
||||
container: Explorer;
|
||||
collection: ViewModels.Collection;
|
||||
}
|
||||
|
||||
export class NewStoredProcedureTab extends ScriptTabBase {
|
||||
public queryText: string;
|
||||
public currentQuery: string;
|
||||
public partitionKey: DataModels.PartitionKey;
|
||||
public iStoredProcTabComponentProps: IStoredProcTabComponentProps;
|
||||
public iStoreProcAccessor: IStorProcTabComponentAccessor;
|
||||
public node: StoredProcedure;
|
||||
public onSaveClick: () => void;
|
||||
public onUpdateClick: () => Promise<void>;
|
||||
|
||||
constructor(options: ViewModels.ScriptTabOption, private props: IStoredProcTabProps) {
|
||||
super(options);
|
||||
this.partitionKey = options.partitionKey;
|
||||
|
||||
this.iStoredProcTabComponentProps = {
|
||||
resource: options.resource,
|
||||
isNew: options.isNew,
|
||||
tabKind: options.tabKind,
|
||||
title: options.title,
|
||||
tabPath: options.tabPath,
|
||||
collectionBase: options.collection,
|
||||
node: options.node,
|
||||
hasLocation: options.hashLocation,
|
||||
scriptTabBaseInstance: this,
|
||||
collection: props.collection,
|
||||
iStorProcTabComponentAccessor: (instance: IStorProcTabComponentAccessor) => {
|
||||
this.iStoreProcAccessor = instance;
|
||||
},
|
||||
container: props.container,
|
||||
};
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
return <StoredProcedureTabComponent {...this.iStoredProcTabComponentProps} />;
|
||||
}
|
||||
|
||||
public onTabClick(): void {
|
||||
this.manager?.activateTab(this);
|
||||
this.iStoreProcAccessor.onTabClickEvent();
|
||||
}
|
||||
|
||||
public onCloseTabButtonClick(): void {
|
||||
this.manager?.closeTab(this);
|
||||
}
|
||||
|
||||
public onExecuteSprocsResult(result: ExecuteSprocResult): void {
|
||||
this.iStoreProcAccessor.onExecuteSprocsResultEvent(result);
|
||||
}
|
||||
|
||||
public onExecuteSprocsError(error: string): void {
|
||||
this.iStoreProcAccessor.onExecuteSprocsErrorEvent(error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,604 @@
|
||||
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
||||
import { Pivot, PivotItem } from "@fluentui/react";
|
||||
import React from "react";
|
||||
import DiscardIcon from "../../../../images/discard.svg";
|
||||
import ExecuteQueryIcon from "../../../../images/ExecuteQuery.svg";
|
||||
import SaveIcon from "../../../../images/save-cosmos.svg";
|
||||
import * as Constants from "../../../Common/Constants";
|
||||
import { NormalizedEventKey } from "../../../Common/Constants";
|
||||
import { createStoredProcedure } from "../../../Common/dataAccess/createStoredProcedure";
|
||||
import { ExecuteSprocResult } from "../../../Common/dataAccess/executeStoredProcedure";
|
||||
import { updateStoredProcedure } from "../../../Common/dataAccess/updateStoredProcedure";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
|
||||
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
||||
import { EditorReact } from "../../Controls/Editor/EditorReact";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useCommandBar } from "../../Menus/CommandBar/CommandBarComponentAdapter";
|
||||
import StoredProcedure from "../../Tree/StoredProcedure";
|
||||
import ScriptTabBase from "../ScriptTabBase";
|
||||
|
||||
export interface IStorProcTabComponentAccessor {
|
||||
onExecuteSprocsResultEvent: (result: ExecuteSprocResult) => void;
|
||||
onExecuteSprocsErrorEvent: (error: string) => void;
|
||||
onTabClickEvent: () => void;
|
||||
}
|
||||
|
||||
export interface Button {
|
||||
visible: boolean;
|
||||
enabled: boolean;
|
||||
isSelected?: boolean;
|
||||
}
|
||||
|
||||
interface IStoredProcTabComponentStates {
|
||||
hasResults: boolean;
|
||||
hasErrors: boolean;
|
||||
error: string;
|
||||
resultData: string;
|
||||
logsData: string;
|
||||
originalSprocBody: string;
|
||||
initialEditorContent: string;
|
||||
sProcEditorContent: string;
|
||||
id: string;
|
||||
executeButton: Button;
|
||||
saveButton: Button;
|
||||
updateButton: Button;
|
||||
discardButton: Button;
|
||||
}
|
||||
|
||||
export interface IStoredProcTabComponentProps {
|
||||
resource: StoredProcedureDefinition;
|
||||
isNew: boolean;
|
||||
tabKind: ViewModels.CollectionTabKind;
|
||||
title: string;
|
||||
tabPath: string;
|
||||
collectionBase: ViewModels.CollectionBase;
|
||||
//eslint-disable-next-line
|
||||
node?: any;
|
||||
hasLocation: string;
|
||||
scriptTabBaseInstance: ScriptTabBase;
|
||||
collection: ViewModels.Collection;
|
||||
iStorProcTabComponentAccessor: (instance: IStorProcTabComponentAccessor) => void;
|
||||
container: Explorer;
|
||||
}
|
||||
|
||||
export default class StoredProcedureTabComponent extends React.Component<
|
||||
IStoredProcTabComponentProps,
|
||||
IStoredProcTabComponentStates
|
||||
> {
|
||||
public node: StoredProcedure;
|
||||
public executeResultsEditorId: string;
|
||||
public executeLogsEditorId: string;
|
||||
public collection: ViewModels.Collection;
|
||||
|
||||
constructor(
|
||||
public storedProcTabCompProps: IStoredProcTabComponentProps,
|
||||
private storedProcTabCompStates: IStoredProcTabComponentStates
|
||||
) {
|
||||
super(storedProcTabCompProps);
|
||||
this.state = {
|
||||
error: "",
|
||||
hasErrors: false,
|
||||
hasResults: false,
|
||||
resultData: "",
|
||||
logsData: "",
|
||||
originalSprocBody: this.props.resource.body.toString(),
|
||||
initialEditorContent: this.props.resource.body.toString(),
|
||||
sProcEditorContent: this.props.resource.body.toString(),
|
||||
id: this.props.resource.id,
|
||||
executeButton: {
|
||||
enabled: !this.props.scriptTabBaseInstance.isNew(),
|
||||
visible: true,
|
||||
},
|
||||
saveButton: {
|
||||
enabled: (() => {
|
||||
if (!this.props.scriptTabBaseInstance.formIsValid()) {
|
||||
return false;
|
||||
}
|
||||
if (!this.props.scriptTabBaseInstance.formIsDirty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})(),
|
||||
visible: this.props.scriptTabBaseInstance.isNew(),
|
||||
},
|
||||
updateButton: {
|
||||
enabled: (() => {
|
||||
if (!this.props.scriptTabBaseInstance.formIsValid()) {
|
||||
return false;
|
||||
}
|
||||
if (!this.props.scriptTabBaseInstance.formIsDirty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})(),
|
||||
visible: !this.props.scriptTabBaseInstance.isNew(),
|
||||
},
|
||||
discardButton: {
|
||||
enabled: (() => {
|
||||
if (!this.props.scriptTabBaseInstance.formIsValid()) {
|
||||
return false;
|
||||
}
|
||||
if (!this.props.scriptTabBaseInstance.formIsDirty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})(),
|
||||
visible: true,
|
||||
},
|
||||
};
|
||||
|
||||
this.collection = this.props.collection;
|
||||
this.executeResultsEditorId = `executestoredprocedureresults${this.props.scriptTabBaseInstance.tabId}`;
|
||||
this.executeLogsEditorId = `executestoredprocedurelogs${this.props.scriptTabBaseInstance.tabId}`;
|
||||
this.props.scriptTabBaseInstance.ariaLabel("Stored Procedure Body");
|
||||
|
||||
this.props.iStorProcTabComponentAccessor({
|
||||
onExecuteSprocsResultEvent: this.onExecuteSprocsResult.bind(this),
|
||||
onExecuteSprocsErrorEvent: this.onExecuteSprocsError.bind(this),
|
||||
onTabClickEvent: this.onTabClick.bind(this),
|
||||
});
|
||||
|
||||
this.node = this.props.node;
|
||||
|
||||
this.buildCommandBarOptions();
|
||||
}
|
||||
|
||||
public onTabClick(): void {
|
||||
if (this.props.container.tabsManager.openedTabs().length > 0) {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}
|
||||
}
|
||||
|
||||
public onSaveClick = (): Promise<StoredProcedureDefinition & Resource> => {
|
||||
return this._createStoredProcedure({
|
||||
id: this.state.id,
|
||||
body: this.state.sProcEditorContent,
|
||||
});
|
||||
};
|
||||
|
||||
public onDiscard = (): Promise<unknown> => {
|
||||
const onDiscardPromise = new Promise(() => {
|
||||
this.props.scriptTabBaseInstance.setBaselines();
|
||||
const original = this.props.scriptTabBaseInstance.editorContent.getEditableOriginalValue();
|
||||
if (this.state.updateButton.visible) {
|
||||
this.setState({
|
||||
updateButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
sProcEditorContent: original,
|
||||
discardButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
executeButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
saveButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
sProcEditorContent: original,
|
||||
discardButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
executeButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
id: "",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}, 100);
|
||||
|
||||
return onDiscardPromise;
|
||||
};
|
||||
|
||||
public onUpdateClick = (): Promise<void> => {
|
||||
const data = this._getResource();
|
||||
|
||||
this.props.scriptTabBaseInstance.isExecutionError(false);
|
||||
this.props.scriptTabBaseInstance.isExecuting(true);
|
||||
|
||||
return updateStoredProcedure(
|
||||
this.props.scriptTabBaseInstance.collection.databaseId,
|
||||
this.props.scriptTabBaseInstance.collection.id(),
|
||||
data
|
||||
)
|
||||
.then(
|
||||
(updatedResource) => {
|
||||
this.props.scriptTabBaseInstance.resource(updatedResource);
|
||||
this.props.scriptTabBaseInstance.tabTitle(updatedResource.id);
|
||||
this.node.id(updatedResource.id);
|
||||
this.node.body(updatedResource.body as string);
|
||||
this.props.scriptTabBaseInstance.setBaselines();
|
||||
|
||||
const editorModel =
|
||||
this.props.scriptTabBaseInstance.editor() && this.props.scriptTabBaseInstance.editor().getModel();
|
||||
editorModel && editorModel.setValue(updatedResource.body as string);
|
||||
this.props.scriptTabBaseInstance.editorContent.setBaseline(updatedResource.body as string);
|
||||
this.setState({
|
||||
discardButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
updateButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
executeButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
});
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
},
|
||||
() => {
|
||||
this.props.scriptTabBaseInstance.isExecutionError(true);
|
||||
}
|
||||
)
|
||||
.finally(() => this.props.scriptTabBaseInstance.isExecuting(false));
|
||||
};
|
||||
|
||||
public onExecuteSprocsResult(result: ExecuteSprocResult): void {
|
||||
const resultData: string = this.props.scriptTabBaseInstance.renderObjectForEditor(result.result, undefined, 4);
|
||||
const scriptLogs: string = (result.scriptLogs && decodeURIComponent(result.scriptLogs)) || "";
|
||||
const logs: string = this.props.scriptTabBaseInstance.renderObjectForEditor(scriptLogs, undefined, 4);
|
||||
|
||||
this.setState({
|
||||
hasResults: false,
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
error: undefined,
|
||||
resultData: resultData,
|
||||
logsData: logs,
|
||||
hasResults: resultData ? true : false,
|
||||
hasErrors: false,
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
public onExecuteSprocsError(error: string): void {
|
||||
this.props.scriptTabBaseInstance.isExecutionError(true);
|
||||
console.error(error);
|
||||
this.setState({
|
||||
error: error,
|
||||
hasErrors: true,
|
||||
hasResults: false,
|
||||
});
|
||||
}
|
||||
|
||||
public onErrorDetailsClick = (): boolean => {
|
||||
useNotificationConsole.getState().expandConsole();
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
public onErrorDetailsKeyPress = (event: React.KeyboardEvent<HTMLAnchorElement>): boolean => {
|
||||
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
|
||||
this.onErrorDetailsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
protected updateSelectedNode(): void {
|
||||
if (this.props.collectionBase === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const database: ViewModels.Database = this.props.collectionBase.getDatabase();
|
||||
if (!database.isDatabaseExpanded()) {
|
||||
this.props.collectionBase.container.selectedNode(database);
|
||||
} else if (!this.props.collectionBase.isCollectionExpanded() || !this.collection.isStoredProceduresExpanded()) {
|
||||
this.props.collectionBase.container.selectedNode(this.props.collectionBase);
|
||||
} else {
|
||||
this.props.collectionBase.container.selectedNode(this.node);
|
||||
}
|
||||
}
|
||||
|
||||
protected buildCommandBarOptions(): void {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}
|
||||
|
||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||
const buttons: CommandButtonComponentProps[] = [];
|
||||
const label = "Save";
|
||||
if (this.state.saveButton.visible) {
|
||||
buttons.push({
|
||||
iconSrc: SaveIcon,
|
||||
iconAlt: label,
|
||||
onCommandClick: this.onSaveClick,
|
||||
commandButtonLabel: label,
|
||||
ariaLabel: label,
|
||||
hasPopup: false,
|
||||
disabled: !this.state.saveButton.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.updateButton.visible) {
|
||||
const label = "Update";
|
||||
buttons.push({
|
||||
iconSrc: SaveIcon,
|
||||
iconAlt: label,
|
||||
onCommandClick: this.onUpdateClick,
|
||||
commandButtonLabel: label,
|
||||
ariaLabel: label,
|
||||
hasPopup: false,
|
||||
disabled: !this.state.updateButton.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.discardButton.visible) {
|
||||
const label = "Discard";
|
||||
buttons.push({
|
||||
iconSrc: DiscardIcon,
|
||||
iconAlt: label,
|
||||
onCommandClick: this.onDiscard,
|
||||
commandButtonLabel: label,
|
||||
ariaLabel: label,
|
||||
hasPopup: false,
|
||||
disabled: !this.state.discardButton.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.executeButton.visible) {
|
||||
const label = "Execute";
|
||||
buttons.push({
|
||||
iconSrc: ExecuteQueryIcon,
|
||||
iconAlt: label,
|
||||
onCommandClick: () => {
|
||||
this.collection.container.openExecuteSprocParamsPanel(this.node);
|
||||
},
|
||||
commandButtonLabel: label,
|
||||
ariaLabel: label,
|
||||
hasPopup: false,
|
||||
disabled: !this.state.executeButton.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
private _getResource() {
|
||||
return {
|
||||
id: this.state.id,
|
||||
body: this.state.sProcEditorContent,
|
||||
};
|
||||
}
|
||||
|
||||
private _createStoredProcedure(resource: StoredProcedureDefinition): Promise<StoredProcedureDefinition & Resource> {
|
||||
this.props.scriptTabBaseInstance.isExecutionError(false);
|
||||
this.props.scriptTabBaseInstance.isExecuting(true);
|
||||
|
||||
return createStoredProcedure(this.props.collectionBase.databaseId, this.props.collectionBase.id(), resource)
|
||||
.then(
|
||||
(createdResource) => {
|
||||
this.props.scriptTabBaseInstance.tabTitle(createdResource.id);
|
||||
this.props.scriptTabBaseInstance.isNew(false);
|
||||
this.props.scriptTabBaseInstance.resource(createdResource);
|
||||
this.props.scriptTabBaseInstance.hashLocation(
|
||||
`${Constants.HashRoutePrefixes.collectionsWithIds(
|
||||
this.props.collectionBase.databaseId,
|
||||
this.props.collectionBase.id()
|
||||
)}/sprocs/${createdResource.id}`
|
||||
);
|
||||
this.props.scriptTabBaseInstance.setBaselines();
|
||||
|
||||
const editorModel =
|
||||
this.props.scriptTabBaseInstance.editor() && this.props.scriptTabBaseInstance.editor().getModel();
|
||||
editorModel && editorModel.setValue(createdResource.body as string);
|
||||
this.props.scriptTabBaseInstance.editorContent.setBaseline(createdResource.body as string);
|
||||
this.node = this.collection.createStoredProcedureNode(createdResource);
|
||||
this.props.container.tabsManager.openedTabs()[
|
||||
this.props.container.tabsManager.openedTabs().length - 1
|
||||
].node = this.node;
|
||||
|
||||
this.props.scriptTabBaseInstance.editorState(ViewModels.ScriptEditorState.exisitingNoEdits);
|
||||
|
||||
this.setState({
|
||||
executeButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
executeButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
updateButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
saveButton: {
|
||||
enabled: false,
|
||||
visible: false,
|
||||
},
|
||||
discardButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
sProcEditorContent: this.state.sProcEditorContent,
|
||||
});
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}, 100);
|
||||
|
||||
return createdResource;
|
||||
},
|
||||
(createError) => {
|
||||
this.props.scriptTabBaseInstance.isExecutionError(true);
|
||||
|
||||
return Promise.reject(createError);
|
||||
}
|
||||
)
|
||||
.finally(() => this.props.scriptTabBaseInstance.isExecuting(false));
|
||||
}
|
||||
|
||||
public onDelete(): Promise<unknown> {
|
||||
const isDeleted = false;
|
||||
const onDeletePromise = new Promise((resolve) => {
|
||||
resolve(isDeleted);
|
||||
});
|
||||
return onDeletePromise;
|
||||
}
|
||||
|
||||
public handleIdOnChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (this.state.saveButton.visible) {
|
||||
this.setState({
|
||||
id: event.target.value,
|
||||
saveButton: {
|
||||
enabled: true,
|
||||
visible: this.props.scriptTabBaseInstance.isNew(),
|
||||
},
|
||||
discardButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
setTimeout(() => {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
public onChangeContent(newConent: string): void {
|
||||
if (this.state.updateButton.visible) {
|
||||
this.setState({
|
||||
updateButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
discardButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
executeButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
sProcEditorContent: newConent,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
saveButton: {
|
||||
enabled: false,
|
||||
visible: this.props.scriptTabBaseInstance.isNew(),
|
||||
},
|
||||
executeButton: {
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
discardButton: {
|
||||
enabled: true,
|
||||
visible: true,
|
||||
},
|
||||
sProcEditorContent: newConent,
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}, 100);
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div className="tab-pane flexContainer stored-procedure-tab" role="tabpanel">
|
||||
<div className="storedTabForm flexContainer">
|
||||
<div className="formTitleFirst">Stored Procedure Id</div>
|
||||
<span className="formTitleTextbox">
|
||||
<input
|
||||
className="formTree"
|
||||
type="text"
|
||||
required
|
||||
pattern="[^/?#\\]*[^/?# \\]"
|
||||
title="May not end with space nor contain characters '\' '/' '#' '?'"
|
||||
aria-label="Stored procedure id"
|
||||
placeholder="Enter the new stored procedure id"
|
||||
size={40}
|
||||
value={this.state.id}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => this.handleIdOnChange(event)}
|
||||
/>
|
||||
</span>
|
||||
<div className="spUdfTriggerHeader">Stored Procedure Body</div>
|
||||
<EditorReact
|
||||
language={"javascript"}
|
||||
content={this.state.sProcEditorContent}
|
||||
isReadOnly={false}
|
||||
ariaLabel={"Stored procedure body"}
|
||||
lineNumbers={"on"}
|
||||
theme={"_theme"}
|
||||
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
|
||||
/>
|
||||
{this.state.hasResults && (
|
||||
<div className="results-container">
|
||||
<Pivot aria-label="Successful execution of stored procedure" style={{ height: "100%" }}>
|
||||
<PivotItem
|
||||
headerText="Result"
|
||||
headerButtonProps={{
|
||||
"data-order": 1,
|
||||
"data-title": "Result",
|
||||
}}
|
||||
style={{ height: "100%" }}
|
||||
>
|
||||
<EditorReact
|
||||
language={"javascript"}
|
||||
content={this.state.resultData}
|
||||
isReadOnly={true}
|
||||
ariaLabel={"Execute stored procedure result"}
|
||||
/>
|
||||
</PivotItem>
|
||||
<PivotItem
|
||||
headerText="console.log"
|
||||
headerButtonProps={{
|
||||
"data-order": 2,
|
||||
"data-title": "console.log",
|
||||
}}
|
||||
style={{ height: "100%" }}
|
||||
>
|
||||
<EditorReact
|
||||
language={"javascript"}
|
||||
content={this.state.logsData}
|
||||
isReadOnly={true}
|
||||
ariaLabel={"Execute stored procedure logs"}
|
||||
/>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</div>
|
||||
)}
|
||||
{this.state.hasErrors && (
|
||||
<div className="errors-container">
|
||||
<div className="errors-header">Errors:</div>
|
||||
<div className="errorContent">
|
||||
<span className="errorMessage">{this.state.error}</span>
|
||||
<span className="errorDetailsLink">
|
||||
<a
|
||||
aria-label="Error details link"
|
||||
onClick={() => this.onErrorDetailsClick()}
|
||||
onKeyPress={(event: React.KeyboardEvent<HTMLAnchorElement>) => this.onErrorDetailsKeyPress(event)}
|
||||
>
|
||||
More details
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user