mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-07-03 10:35:21 +01:00
FIxed all PR change request
This commit is contained in:
parent
7d30268cd9
commit
ea21ab2580
@ -15,7 +15,6 @@ export interface EditorReactProps {
|
|||||||
onContentChanged?: (newContent: string) => void; // Called when text is changed
|
onContentChanged?: (newContent: string) => void; // Called when text is changed
|
||||||
lineNumbers?: monaco.editor.IEditorOptions["lineNumbers"];
|
lineNumbers?: monaco.editor.IEditorOptions["lineNumbers"];
|
||||||
theme?: string; // Monaco editor theme
|
theme?: string; // Monaco editor theme
|
||||||
editorKey?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorReact extends React.Component<EditorReactProps, EditorReactStates> {
|
export class EditorReact extends React.Component<EditorReactProps, EditorReactStates> {
|
||||||
@ -35,7 +34,6 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public shouldComponentUpdate(): boolean {
|
public shouldComponentUpdate(): boolean {
|
||||||
// Prevents component re-rendering
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,8 +42,8 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: EditorReactProps): void {
|
public componentDidUpdate(prevProps: EditorReactProps): void {
|
||||||
if (prevProps.editorKey !== this.props.editorKey) {
|
if (this.props.content !== prevProps.content) {
|
||||||
this.createEditor(this.configureEditor.bind(this));
|
this.editor.setValue(this.props.content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ export interface IDocumentsTabContentState {
|
|||||||
documentContent: string;
|
documentContent: string;
|
||||||
documentIds: Array<DocumentId>;
|
documentIds: Array<DocumentId>;
|
||||||
documentSqlIds: Array<Resource>;
|
documentSqlIds: Array<Resource>;
|
||||||
editorKey: string;
|
|
||||||
selectedDocumentId?: DocumentId;
|
selectedDocumentId?: DocumentId;
|
||||||
selectedSqlDocumentId?: Resource;
|
selectedSqlDocumentId?: Resource;
|
||||||
isEditorContentEdited: boolean;
|
isEditorContentEdited: boolean;
|
||||||
@ -58,13 +57,7 @@ export function getPartitionKeyDefinition(
|
|||||||
partitionKey: DataModels.PartitionKey,
|
partitionKey: DataModels.PartitionKey,
|
||||||
partitionKeyProperty: string
|
partitionKeyProperty: string
|
||||||
): DataModels.PartitionKey {
|
): DataModels.PartitionKey {
|
||||||
if (
|
if (partitionKey?.paths?.[0]?.indexOf("$v") > -1) {
|
||||||
partitionKey &&
|
|
||||||
partitionKey.paths &&
|
|
||||||
partitionKey.paths.length &&
|
|
||||||
partitionKey.paths.length > 0 &&
|
|
||||||
partitionKey.paths[0].indexOf("$v") > -1
|
|
||||||
) {
|
|
||||||
// Convert BsonSchema2 to /path format
|
// Convert BsonSchema2 to /path format
|
||||||
partitionKey = {
|
partitionKey = {
|
||||||
kind: partitionKey.kind,
|
kind: partitionKey.kind,
|
||||||
@ -78,7 +71,7 @@ export function getPartitionKeyDefinition(
|
|||||||
export function formatDocumentContent(row: DocumentId): string {
|
export function formatDocumentContent(row: DocumentId): string {
|
||||||
const { partitionKeyProperty, partitionKeyValue, id } = row;
|
const { partitionKeyProperty, partitionKeyValue, id } = row;
|
||||||
const documentContent = JSON.stringify({
|
const documentContent = JSON.stringify({
|
||||||
_id1: id(),
|
_id: id(),
|
||||||
[partitionKeyProperty]: partitionKeyValue || "",
|
[partitionKeyProperty]: partitionKeyValue || "",
|
||||||
});
|
});
|
||||||
const formattedDocumentContent = documentContent.replace(/,/g, ",\n").replace("{", "{\n").replace("}", "\n}");
|
const formattedDocumentContent = documentContent.replace(/,/g, ",\n").replace("{", "{\n").replace("}", "\n}");
|
||||||
@ -129,7 +122,10 @@ export function getDocumentItems(
|
|||||||
return isAllDocumentsVisible ? documentSqlIds : documentSqlIds.slice(0, 5);
|
return isAllDocumentsVisible ? documentSqlIds : documentSqlIds.slice(0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tabButtonVisibility = (visible: boolean, enabled: boolean): { visible: boolean; enabled: boolean } => {
|
export const assignTabButtonVisibility = (
|
||||||
|
visible: boolean,
|
||||||
|
enabled: boolean
|
||||||
|
): { visible: boolean; enabled: boolean } => {
|
||||||
return {
|
return {
|
||||||
visible,
|
visible,
|
||||||
enabled,
|
enabled,
|
||||||
@ -145,9 +141,3 @@ export const getfilterText = (isPreferredApiMongoDB: boolean, filter: string): s
|
|||||||
}
|
}
|
||||||
return `Select * from C ${filter}`;
|
return `Select * from C ${filter}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getConfirmationMessage = (apiType: string): string => {
|
|
||||||
return apiType !== "Mongo"
|
|
||||||
? "Are you sure you want to delete the selected item ?"
|
|
||||||
: "Are you sure you want to delete the selected document ?";
|
|
||||||
};
|
|
||||||
|
@ -41,13 +41,7 @@ export default class DocumentsTab extends TabsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getPartitionKeyPropertyHeader(): string {
|
private _getPartitionKeyPropertyHeader(): string {
|
||||||
return (
|
return this.partitionKey?.paths?.[0];
|
||||||
(this.partitionKey &&
|
|
||||||
this.partitionKey.paths &&
|
|
||||||
this.partitionKey.paths.length > 0 &&
|
|
||||||
this.partitionKey.paths[0]) ||
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
|
@ -22,11 +22,13 @@ import NewDocumentIcon from "../../../images/NewDocument.svg";
|
|||||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||||
import UploadIcon from "../../../images/Upload_16x16.svg";
|
import UploadIcon from "../../../images/Upload_16x16.svg";
|
||||||
import { Resource } from "../../../src/Contracts/DataModels";
|
import { Resource } from "../../../src/Contracts/DataModels";
|
||||||
|
import * as NotificationConsoleUtils from "../../../src/Utils/NotificationConsoleUtils";
|
||||||
import { Areas } from "../../Common/Constants";
|
import { Areas } from "../../Common/Constants";
|
||||||
import { createDocument as createSqlDocuments } from "../../Common/dataAccess/createDocument";
|
import { createDocument as createSqlDocuments } from "../../Common/dataAccess/createDocument";
|
||||||
import { deleteDocument as deleteSqlDocument } from "../../Common/dataAccess/deleteDocument";
|
import { deleteDocument as deleteSqlDocument } from "../../Common/dataAccess/deleteDocument";
|
||||||
import { queryDocuments as querySqlDocuments } from "../../Common/dataAccess/queryDocuments";
|
import { queryDocuments as querySqlDocuments } from "../../Common/dataAccess/queryDocuments";
|
||||||
import { updateDocument as updateSqlDocuments } from "../../Common/dataAccess/updateDocument";
|
import { updateDocument as updateSqlDocuments } from "../../Common/dataAccess/updateDocument";
|
||||||
|
import { getEntityName } from "../../Common/DocumentUtility";
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
||||||
import * as HeadersUtility from "../../Common/HeadersUtility";
|
import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||||
import { logError } from "../../Common/Logger";
|
import { logError } from "../../Common/Logger";
|
||||||
@ -44,41 +46,32 @@ import ObjectId from "../Tree/ObjectId";
|
|||||||
import { useSelectedNode } from "../useSelectedNode";
|
import { useSelectedNode } from "../useSelectedNode";
|
||||||
import DocumentsTab from "./DocumentsTab";
|
import DocumentsTab from "./DocumentsTab";
|
||||||
import {
|
import {
|
||||||
|
assignTabButtonVisibility,
|
||||||
formatDocumentContent,
|
formatDocumentContent,
|
||||||
formatSqlDocumentContent,
|
formatSqlDocumentContent,
|
||||||
getConfirmationMessage,
|
|
||||||
getDocumentItems,
|
getDocumentItems,
|
||||||
getFilterPlaceholder,
|
getFilterPlaceholder,
|
||||||
getFilterSuggestions,
|
getFilterSuggestions,
|
||||||
getfilterText,
|
getfilterText,
|
||||||
getPartitionKeyDefinition,
|
getPartitionKeyDefinition,
|
||||||
hasShardKeySpecified,
|
hasShardKeySpecified,
|
||||||
IButton,
|
|
||||||
IDocumentsTabContentState,
|
IDocumentsTabContentState,
|
||||||
imageProps,
|
imageProps,
|
||||||
tabButtonVisibility,
|
|
||||||
} from "./DocumentTabUtils";
|
} from "./DocumentTabUtils";
|
||||||
|
|
||||||
const filterIcon: IIconProps = { iconName: "Filter" };
|
const filterIcon: IIconProps = { iconName: "Filter" };
|
||||||
|
let newDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
|
let saveNewDocumentButton = assignTabButtonVisibility(false, true);
|
||||||
|
let discardNewDocumentChangesButton = assignTabButtonVisibility(false, false);
|
||||||
|
let saveExisitingDocumentButton = assignTabButtonVisibility(false, false);
|
||||||
|
let discardExisitingDocumentChangesButton = assignTabButtonVisibility(false, false);
|
||||||
|
let deleteExisitingDocumentButton = assignTabButtonVisibility(false, false);
|
||||||
|
|
||||||
export default class DocumentsTabContent extends React.Component<DocumentsTab, IDocumentsTabContentState> {
|
export default class DocumentsTabContent extends React.Component<DocumentsTab, IDocumentsTabContentState> {
|
||||||
public newDocumentButton: IButton;
|
public initialDocumentContent: string;
|
||||||
public saveNewDocumentButton: IButton;
|
|
||||||
public discardNewDocumentChangesButton: IButton;
|
|
||||||
public saveExisitingDocumentButton: IButton;
|
|
||||||
public discardExisitingDocumentChangesButton: IButton;
|
|
||||||
public deleteExisitingDocumentButton: IButton;
|
|
||||||
public intitalDocumentContent: string;
|
|
||||||
|
|
||||||
constructor(props: DocumentsTab) {
|
constructor(props: DocumentsTab) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.newDocumentButton = tabButtonVisibility(true, true);
|
|
||||||
this.saveNewDocumentButton = tabButtonVisibility(false, true);
|
|
||||||
this.discardNewDocumentChangesButton = tabButtonVisibility(false, false);
|
|
||||||
this.saveExisitingDocumentButton = tabButtonVisibility(false, false);
|
|
||||||
this.discardExisitingDocumentChangesButton = tabButtonVisibility(false, false);
|
|
||||||
this.deleteExisitingDocumentButton = tabButtonVisibility(false, false);
|
|
||||||
const isPreferredApiMongoDB = userContext.apiType === "Mongo";
|
const isPreferredApiMongoDB = userContext.apiType === "Mongo";
|
||||||
|
|
||||||
const columns: IColumn[] = [
|
const columns: IColumn[] = [
|
||||||
@ -117,7 +110,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
this.intitalDocumentContent = `{ \n ${
|
this.initialDocumentContent = `{ \n ${
|
||||||
isPreferredApiMongoDB ? '"_id"' : '"id"'
|
isPreferredApiMongoDB ? '"_id"' : '"id"'
|
||||||
}: "replace_with_new_document_id" \n }`;
|
}: "replace_with_new_document_id" \n }`;
|
||||||
|
|
||||||
@ -130,10 +123,9 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
filter: "",
|
filter: "",
|
||||||
isFilterOptionVisible: true,
|
isFilterOptionVisible: true,
|
||||||
isEditorVisible: false,
|
isEditorVisible: false,
|
||||||
documentContent: this.intitalDocumentContent,
|
documentContent: this.initialDocumentContent,
|
||||||
documentIds: [],
|
documentIds: [],
|
||||||
documentSqlIds: [],
|
documentSqlIds: [],
|
||||||
editorKey: "",
|
|
||||||
isEditorContentEdited: false,
|
isEditorContentEdited: false,
|
||||||
isAllDocumentsVisible: false,
|
isAllDocumentsVisible: false,
|
||||||
};
|
};
|
||||||
@ -169,12 +161,12 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
const sqlQuery = querySqlDocuments(this.props.collection.databaseId, this.props.collection.id(), query, options);
|
const sqlQuery = querySqlDocuments(this.props.collection.databaseId, this.props.collection.id(), query, options);
|
||||||
const querySqlDocumentsData = await sqlQuery.fetchNext();
|
const querySqlDocumentsData = await sqlQuery.fetchNext();
|
||||||
this.setState({ documentSqlIds: querySqlDocumentsData.resources.length ? querySqlDocumentsData.resources : [] });
|
this.setState({ documentSqlIds: querySqlDocumentsData.resources.length ? querySqlDocumentsData.resources : [] });
|
||||||
this.props.isExecuting(false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.props.isExecuting(false);
|
|
||||||
this.props.isExecutionError(true);
|
this.props.isExecutionError(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
window.alert(errorMessage);
|
NotificationConsoleUtils.logConsoleError(errorMessage);
|
||||||
|
} finally {
|
||||||
|
this.props.isExecuting(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,7 +203,6 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
this.props.onLoadStartKey
|
this.props.onLoadStartKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.props.isExecuting(false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (this.props.onLoadStartKey !== undefined) {
|
if (this.props.onLoadStartKey !== undefined) {
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
@ -227,18 +218,25 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
this.props.onLoadStartKey
|
this.props.onLoadStartKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
this.props.isExecuting(false);
|
this.props.isExecuting(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleRow = (row: DocumentId | Resource): void => {
|
private handleRow = (row: DocumentId | Resource): void => {
|
||||||
if (this.state.isEditorContentEdited) {
|
if (this.state.isEditorContentEdited) {
|
||||||
const isChangesConfirmed = window.confirm("Your unsaved changes will be lost.");
|
this.props.collection.container.showOkCancelModalDialog(
|
||||||
if (isChangesConfirmed) {
|
"Are you sure you want to continue?",
|
||||||
|
"Your unsaved changes will be lost.",
|
||||||
|
"Okay",
|
||||||
|
() => {
|
||||||
this.handleRowContent(row);
|
this.handleRowContent(row);
|
||||||
this.setState({ isEditorContentEdited: false });
|
this.setState({ isEditorContentEdited: false });
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
|
"Cancel",
|
||||||
|
undefined
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.handleRowContent(row);
|
this.handleRowContent(row);
|
||||||
}
|
}
|
||||||
@ -249,11 +247,10 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
userContext.apiType === "Mongo"
|
userContext.apiType === "Mongo"
|
||||||
? formatDocumentContent(row as DocumentId)
|
? formatDocumentContent(row as DocumentId)
|
||||||
: formatSqlDocumentContent(row as Resource);
|
: formatSqlDocumentContent(row as Resource);
|
||||||
this.updateTabButtonVisibility();
|
|
||||||
|
|
||||||
userContext.apiType === "Mongo"
|
userContext.apiType === "Mongo"
|
||||||
? this.updateContent(row as DocumentId, formattedDocumentContent)
|
? this.updateContent(row as DocumentId, formattedDocumentContent)
|
||||||
: this.updateSqlContent(row as Resource, formattedDocumentContent);
|
: this.updateSqlContent(row as Resource, formattedDocumentContent);
|
||||||
|
this.setDefaultUpdateTabButtonVisibility();
|
||||||
};
|
};
|
||||||
|
|
||||||
private updateContent = (row: DocumentId, formattedDocumentContent: string): void => {
|
private updateContent = (row: DocumentId, formattedDocumentContent: string): void => {
|
||||||
@ -261,7 +258,6 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
{
|
{
|
||||||
documentContent: formattedDocumentContent,
|
documentContent: formattedDocumentContent,
|
||||||
isEditorVisible: true,
|
isEditorVisible: true,
|
||||||
editorKey: row.rid,
|
|
||||||
selectedDocumentId: row,
|
selectedDocumentId: row,
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
@ -275,7 +271,6 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
{
|
{
|
||||||
documentContent: formattedDocumentContent,
|
documentContent: formattedDocumentContent,
|
||||||
isEditorVisible: true,
|
isEditorVisible: true,
|
||||||
editorKey: row._rid,
|
|
||||||
selectedSqlDocumentId: row,
|
selectedSqlDocumentId: row,
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
@ -319,7 +314,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
this.querySqlDocumentsData();
|
this.querySqlDocumentsData();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.alert(getErrorMessage(error));
|
NotificationConsoleUtils.logConsoleError(getErrorMessage(error));
|
||||||
this.setTraceFail(Action.UpdateDocument, startKey, error);
|
this.setTraceFail(Action.UpdateDocument, startKey, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,15 +347,15 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
this.setTraceSuccess(Action.UpdateDocument, startKey);
|
this.setTraceSuccess(Action.UpdateDocument, startKey);
|
||||||
this.setState({ isEditorContentEdited: false });
|
this.setState({ isEditorContentEdited: false });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.alert(getErrorMessage(error));
|
NotificationConsoleUtils.logConsoleError(getErrorMessage(error));
|
||||||
this.setTraceFail(Action.UpdateDocument, startKey, error);
|
this.setTraceFail(Action.UpdateDocument, startKey, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
const label = userContext.apiType === "Mongo" ? "New Document" : "New Item";
|
const label = `New ${getEntityName()}`;
|
||||||
if (this.newDocumentButton.visible) {
|
if (newDocumentButton.visible) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: NewDocumentIcon,
|
iconSrc: NewDocumentIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@ -368,11 +363,11 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.newDocumentButton.enabled,
|
disabled: !newDocumentButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.saveNewDocumentButton.visible) {
|
if (saveNewDocumentButton.visible) {
|
||||||
const label = "Save";
|
const label = "Save";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
@ -381,11 +376,11 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.saveNewDocumentButton.enabled,
|
disabled: !saveNewDocumentButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.discardNewDocumentChangesButton.visible) {
|
if (discardNewDocumentChangesButton.visible) {
|
||||||
const label = "Discard";
|
const label = "Discard";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DiscardIcon,
|
iconSrc: DiscardIcon,
|
||||||
@ -394,11 +389,11 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.discardNewDocumentChangesButton.enabled,
|
disabled: !discardNewDocumentChangesButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.saveExisitingDocumentButton.visible) {
|
if (saveExisitingDocumentButton.visible) {
|
||||||
const label = "Update";
|
const label = "Update";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
@ -411,11 +406,11 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.saveExisitingDocumentButton.enabled,
|
disabled: !saveExisitingDocumentButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.discardExisitingDocumentChangesButton.visible) {
|
if (discardExisitingDocumentChangesButton.visible) {
|
||||||
const label = "Discard";
|
const label = "Discard";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
@ -426,11 +421,11 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.discardExisitingDocumentChangesButton.enabled,
|
disabled: !discardExisitingDocumentChangesButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.deleteExisitingDocumentButton.visible) {
|
if (deleteExisitingDocumentButton.visible) {
|
||||||
const label = "Delete";
|
const label = "Delete";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
@ -441,7 +436,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.deleteExisitingDocumentButton.enabled,
|
disabled: !deleteExisitingDocumentButton.enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (userContext.apiType !== "Mongo") {
|
if (userContext.apiType !== "Mongo") {
|
||||||
@ -468,10 +463,14 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async onDeleteExisitingDocumentClick(): Promise<void> {
|
private async onDeleteExisitingDocumentClick(): Promise<void> {
|
||||||
const confirmationMessage = getConfirmationMessage(userContext.apiType);
|
const confirmationMessage = `Are you sure you want to delete the selected ${getEntityName()} ?`;
|
||||||
const { isExecuting, collection, partitionKey, partitionKeyProperty } = this.props;
|
const { isExecuting, collection, partitionKey, partitionKeyProperty } = this.props;
|
||||||
const startKey: number = this.getStartKey(Action.DeleteDocument);
|
const startKey: number = this.getStartKey(Action.DeleteDocument);
|
||||||
if (window.confirm(confirmationMessage)) {
|
this.props.collection.container.showOkCancelModalDialog(
|
||||||
|
confirmationMessage,
|
||||||
|
`This ${getEntityName()} will be deleted immediately. You can't undo this action`,
|
||||||
|
"Delete",
|
||||||
|
async () => {
|
||||||
try {
|
try {
|
||||||
isExecuting(true);
|
isExecuting(true);
|
||||||
if (userContext.apiType === "Mongo") {
|
if (userContext.apiType === "Mongo") {
|
||||||
@ -500,7 +499,10 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setTraceFail(Action.DeleteDocument, startKey, error);
|
this.setTraceFail(Action.DeleteDocument, startKey, error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"Cancel",
|
||||||
|
undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRevertExisitingDocumentClick(): void {
|
private onRevertExisitingDocumentClick(): void {
|
||||||
@ -511,23 +513,24 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
: formatSqlDocumentContent(selectedSqlDocumentId);
|
: formatSqlDocumentContent(selectedSqlDocumentId);
|
||||||
this.setState({
|
this.setState({
|
||||||
documentContent: documentContent,
|
documentContent: documentContent,
|
||||||
editorKey: Math.random().toString(),
|
|
||||||
});
|
});
|
||||||
|
discardExisitingDocumentChangesButton = assignTabButtonVisibility(true, false);
|
||||||
|
saveExisitingDocumentButton = assignTabButtonVisibility(true, false);
|
||||||
|
this.updateTabButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onNewDocumentClick = () => {
|
private onNewDocumentClick = () => {
|
||||||
this.newDocumentButton = tabButtonVisibility(true, false);
|
newDocumentButton = assignTabButtonVisibility(true, false);
|
||||||
this.saveNewDocumentButton = tabButtonVisibility(true, true);
|
saveNewDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
this.discardNewDocumentChangesButton = tabButtonVisibility(true, true);
|
discardNewDocumentChangesButton = assignTabButtonVisibility(true, true);
|
||||||
this.saveExisitingDocumentButton = tabButtonVisibility(false, false);
|
saveExisitingDocumentButton = assignTabButtonVisibility(false, false);
|
||||||
this.discardExisitingDocumentChangesButton = tabButtonVisibility(false, false);
|
discardExisitingDocumentChangesButton = assignTabButtonVisibility(false, false);
|
||||||
this.deleteExisitingDocumentButton = tabButtonVisibility(false, false);
|
deleteExisitingDocumentButton = assignTabButtonVisibility(false, false);
|
||||||
|
|
||||||
this.updateTabButton();
|
this.updateTabButton();
|
||||||
this.setState({
|
this.setState({
|
||||||
documentContent: this.intitalDocumentContent,
|
documentContent: this.initialDocumentContent,
|
||||||
isEditorVisible: true,
|
isEditorVisible: true,
|
||||||
editorKey: this.intitalDocumentContent,
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -549,23 +552,23 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
const savedDocument = await createSqlDocuments(collection, document);
|
const savedDocument = await createSqlDocuments(collection, document);
|
||||||
if (savedDocument) {
|
if (savedDocument) {
|
||||||
this.handleRowContent(savedDocument as Resource);
|
this.handleRowContent(savedDocument as Resource);
|
||||||
this.updateTabButtonVisibility();
|
this.setDefaultUpdateTabButtonVisibility();
|
||||||
this.setTraceSuccess(Action.CreateDocument, startKey);
|
this.setTraceSuccess(Action.CreateDocument, startKey);
|
||||||
}
|
}
|
||||||
this.querySqlDocumentsData();
|
this.querySqlDocumentsData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.alert(getErrorMessage(error));
|
NotificationConsoleUtils.logConsoleError(getErrorMessage(error));
|
||||||
this.setTraceFail(Action.CreateDocument, startKey, error);
|
this.setTraceFail(Action.CreateDocument, startKey, error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private updateTabButtonVisibility = (): void => {
|
private setDefaultUpdateTabButtonVisibility = (): void => {
|
||||||
this.newDocumentButton = tabButtonVisibility(true, true);
|
newDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
this.saveNewDocumentButton = tabButtonVisibility(false, false);
|
saveNewDocumentButton = assignTabButtonVisibility(false, false);
|
||||||
this.discardNewDocumentChangesButton = tabButtonVisibility(false, false);
|
discardNewDocumentChangesButton = assignTabButtonVisibility(false, false);
|
||||||
this.saveExisitingDocumentButton = tabButtonVisibility(true, false);
|
saveExisitingDocumentButton = assignTabButtonVisibility(true, false);
|
||||||
this.discardExisitingDocumentChangesButton = tabButtonVisibility(true, false);
|
discardExisitingDocumentChangesButton = assignTabButtonVisibility(true, false);
|
||||||
this.deleteExisitingDocumentButton = tabButtonVisibility(true, true);
|
deleteExisitingDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
this.updateTabButton();
|
this.updateTabButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -603,7 +606,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
);
|
);
|
||||||
if (savedDocument) {
|
if (savedDocument) {
|
||||||
this.handleLoadMoreDocument();
|
this.handleLoadMoreDocument();
|
||||||
this.updateTabButtonVisibility();
|
this.setDefaultUpdateTabButtonVisibility();
|
||||||
this.setTraceSuccess(Action.CreateDocument, startKey);
|
this.setTraceSuccess(Action.CreateDocument, startKey);
|
||||||
}
|
}
|
||||||
this.setState({ isEditorContentEdited: false });
|
this.setState({ isEditorContentEdited: false });
|
||||||
@ -652,9 +655,9 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
};
|
};
|
||||||
|
|
||||||
private onRevertNewDocumentClick = () => {
|
private onRevertNewDocumentClick = () => {
|
||||||
this.newDocumentButton = tabButtonVisibility(true, true);
|
newDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
this.saveNewDocumentButton = tabButtonVisibility(true, false);
|
saveNewDocumentButton = assignTabButtonVisibility(true, false);
|
||||||
this.discardNewDocumentChangesButton = tabButtonVisibility(true, false);
|
discardNewDocumentChangesButton = assignTabButtonVisibility(true, false);
|
||||||
|
|
||||||
this.updateTabButton();
|
this.updateTabButton();
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -696,9 +699,9 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleDocumentContentChange = (newContent: string): void => {
|
private handleDocumentContentChange = (newContent: string): void => {
|
||||||
if (this.saveExisitingDocumentButton.visible) {
|
if (saveExisitingDocumentButton.visible && newContent !== this.state.documentContent) {
|
||||||
this.saveExisitingDocumentButton = tabButtonVisibility(true, true);
|
saveExisitingDocumentButton = assignTabButtonVisibility(true, true);
|
||||||
this.discardExisitingDocumentChangesButton = tabButtonVisibility(true, true);
|
discardExisitingDocumentChangesButton = assignTabButtonVisibility(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(
|
this.setState(
|
||||||
@ -723,16 +726,14 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
documentContent,
|
documentContent,
|
||||||
documentIds,
|
documentIds,
|
||||||
documentSqlIds,
|
documentSqlIds,
|
||||||
editorKey,
|
|
||||||
isAllDocumentsVisible,
|
isAllDocumentsVisible,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const isPreferredApiMongoDB = userContext.apiType === "Mongo";
|
const isPreferredApiMongoDB = userContext.apiType === "Mongo";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
{isFilterOptionVisible && (
|
{isFilterOptionVisible && (
|
||||||
<div>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<Stack horizontal verticalFill wrap>
|
<Stack horizontal verticalFill wrap>
|
||||||
{!isPreferredApiMongoDB && <Text className="queryText">SELECT * FROM c</Text>}
|
{!isPreferredApiMongoDB && <Text className="queryText">SELECT * FROM c</Text>}
|
||||||
@ -760,7 +761,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
<List items={getFilterSuggestions(isPreferredApiMongoDB)} onRenderCell={this.onRenderCell} />
|
<List items={getFilterSuggestions(isPreferredApiMongoDB)} onRenderCell={this.onRenderCell} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isFilterOptionVisible && (
|
{!isFilterOptionVisible && (
|
||||||
<Stack horizontal verticalFill wrap className="documentTabNoFilterView">
|
<Stack horizontal verticalFill wrap className="documentTabNoFilterView">
|
||||||
@ -794,7 +795,6 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
ariaLabel={"Document json"}
|
ariaLabel={"Document json"}
|
||||||
onContentChanged={this.handleDocumentContentChange}
|
onContentChanged={this.handleDocumentContentChange}
|
||||||
lineNumbers="on"
|
lineNumbers="on"
|
||||||
editorKey={editorKey}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@ -805,7 +805,7 @@ export default class DocumentsTabContent extends React.Component<DocumentsTab, I
|
|||||||
)}
|
)}
|
||||||
</SplitterLayout>
|
</SplitterLayout>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
88
src/Explorer/Tabs/DocumentsTabUtils.test.tsx
Normal file
88
src/Explorer/Tabs/DocumentsTabUtils.test.tsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import * as ko from "knockout";
|
||||||
|
import { PartitionKey, Resource } from "../../../src/Contracts/DataModels";
|
||||||
|
import DocumentId from "../Tree/DocumentId";
|
||||||
|
import * as DocumentTabUtils from "./DocumentTabUtils";
|
||||||
|
|
||||||
|
describe("DocumentTabUtils", () => {
|
||||||
|
describe("getfilterText()", () => {
|
||||||
|
it("Should return filter if isPreferredApiMongoDB is true and filter is applied ", () => {
|
||||||
|
const filteredText: string = DocumentTabUtils.getfilterText(true, `{"_id": "foo"}`);
|
||||||
|
expect(filteredText).toBe(`Filter : {"_id": "foo"}`);
|
||||||
|
});
|
||||||
|
it("Should return `No filter applied` if isPreferredApiMongoDB is true and filter is not applied ", () => {
|
||||||
|
const filteredText: string = DocumentTabUtils.getfilterText(true, "");
|
||||||
|
expect(filteredText).toBe("No filter applied");
|
||||||
|
});
|
||||||
|
it("Should return `Select * from C` with filter if isPreferredApiMongoDB is false and filter is applied ", () => {
|
||||||
|
const filteredText: string = DocumentTabUtils.getfilterText(false, `WHERE c.id = "foo"`);
|
||||||
|
expect(filteredText).toBe(`Select * from C WHERE c.id = "foo"`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formatDocumentContent()", () => {
|
||||||
|
const fakeDocumentData = {} as DocumentId;
|
||||||
|
fakeDocumentData.partitionKeyProperty = "test";
|
||||||
|
fakeDocumentData.id = ko.observable("id");
|
||||||
|
|
||||||
|
it("should return formatted content with new line each property.", () => {
|
||||||
|
fakeDocumentData.partitionKeyValue = "partitionValue";
|
||||||
|
const formattedContent: string = DocumentTabUtils.formatDocumentContent(fakeDocumentData);
|
||||||
|
expect(formattedContent).toBe(`{\n"_id":"id",\n"test":"partitionValue"\n}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return formatted content with empty partitionKeyValue when partitionKeyValue is undefined.", () => {
|
||||||
|
fakeDocumentData.partitionKeyValue = undefined;
|
||||||
|
const formattedContent: string = DocumentTabUtils.formatDocumentContent(fakeDocumentData);
|
||||||
|
expect(formattedContent).toBe(`{\n"_id":"id",\n"test":""\n}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formatSqlDocumentContent()", () => {
|
||||||
|
const fakeDocumentData = {} as Resource;
|
||||||
|
it("should return formatted content with new line each property.", () => {
|
||||||
|
fakeDocumentData.id = "testId";
|
||||||
|
fakeDocumentData._rid = "testRid";
|
||||||
|
fakeDocumentData._self = "testSelf";
|
||||||
|
fakeDocumentData._ts = "testTs";
|
||||||
|
fakeDocumentData._etag = "testEtag";
|
||||||
|
fakeDocumentData._partitionKeyValue = "testPartitionKeyValue";
|
||||||
|
const formattedContent: string = DocumentTabUtils.formatSqlDocumentContent(fakeDocumentData);
|
||||||
|
expect(formattedContent).toBe(
|
||||||
|
`{\n"id":"testId",\n"_rid":"testRid",\n"_self":"testSelf",\n"_ts":"testTs",\n"_etag":"testEtag",\n"_partitionKeyValue":"testPartitionKeyValue"\n}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return formatted content with empty value when key value is undefined.", () => {
|
||||||
|
fakeDocumentData.id = undefined;
|
||||||
|
fakeDocumentData._rid = undefined;
|
||||||
|
fakeDocumentData._self = undefined;
|
||||||
|
fakeDocumentData._ts = undefined;
|
||||||
|
fakeDocumentData._etag = undefined;
|
||||||
|
fakeDocumentData._partitionKeyValue = undefined;
|
||||||
|
const formattedContent: string = DocumentTabUtils.formatSqlDocumentContent(fakeDocumentData);
|
||||||
|
expect(formattedContent).toBe(
|
||||||
|
`{\n"id":"",\n"_rid":"",\n"_self":"",\n"_ts":"",\n"_etag":"",\n"_partitionKeyValue":""\n}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getPartitionKeyDefinition()", () => {
|
||||||
|
const partitionKey = {} as PartitionKey;
|
||||||
|
partitionKey.kind = "Hash";
|
||||||
|
partitionKey.version = 1;
|
||||||
|
partitionKey.systemKey = true;
|
||||||
|
const partitionKeyProperty = "testPartitionKey";
|
||||||
|
|
||||||
|
it("should return formatted partitionKey with formatted path.", () => {
|
||||||
|
partitionKey.paths = ["test"];
|
||||||
|
const formattedPartitionKey = DocumentTabUtils.getPartitionKeyDefinition(partitionKey, partitionKeyProperty);
|
||||||
|
expect(formattedPartitionKey).toEqual({ kind: "Hash", version: 1, systemKey: true, paths: ["test"] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return partitionKey with undefined paths if paths is undefined.", () => {
|
||||||
|
partitionKey.paths = undefined;
|
||||||
|
const formattedPartitionKey = DocumentTabUtils.getPartitionKeyDefinition(partitionKey, partitionKeyProperty);
|
||||||
|
expect(formattedPartitionKey).toEqual({ kind: "Hash", version: 1, systemKey: true, paths: undefined });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user