mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-04-17 12:00:40 +01:00
Localization second batch (#2410)
* Localization second batch * update test * fix tests * Fix test
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
|||||||
AddGlobalSecondaryIndexPanelProps,
|
AddGlobalSecondaryIndexPanelProps,
|
||||||
} from "Explorer/Panes/AddGlobalSecondaryIndexPanel/AddGlobalSecondaryIndexPanel";
|
} from "Explorer/Panes/AddGlobalSecondaryIndexPanel/AddGlobalSecondaryIndexPanel";
|
||||||
import { useDatabases } from "Explorer/useDatabases";
|
import { useDatabases } from "Explorer/useDatabases";
|
||||||
|
import { Keys } from "Localization/Keys.generated";
|
||||||
|
import { t } from "Localization/t";
|
||||||
import { isFabric, isFabricNative, openRestoreContainerDialog } from "Platform/Fabric/FabricUtil";
|
import { isFabric, isFabricNative, openRestoreContainerDialog } from "Platform/Fabric/FabricUtil";
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
|
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
|
||||||
@@ -24,6 +26,7 @@ import DeleteTriggerIcon from "../../images/DeleteTrigger.svg";
|
|||||||
import DeleteUDFIcon from "../../images/DeleteUDF.svg";
|
import DeleteUDFIcon from "../../images/DeleteUDF.svg";
|
||||||
import HostedTerminalIcon from "../../images/Hosted-Terminal.svg";
|
import HostedTerminalIcon from "../../images/Hosted-Terminal.svg";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
import { extractFeatures } from "../Platform/Hosted/extractFeatures";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
import { getCollectionName, getDatabaseName } from "../Utils/APITypeUtils";
|
import { getCollectionName, getDatabaseName } from "../Utils/APITypeUtils";
|
||||||
import { useSidePanel } from "../hooks/useSidePanel";
|
import { useSidePanel } from "../hooks/useSidePanel";
|
||||||
@@ -35,7 +38,6 @@ import StoredProcedure from "./Tree/StoredProcedure";
|
|||||||
import Trigger from "./Tree/Trigger";
|
import Trigger from "./Tree/Trigger";
|
||||||
import UserDefinedFunction from "./Tree/UserDefinedFunction";
|
import UserDefinedFunction from "./Tree/UserDefinedFunction";
|
||||||
import { useSelectedNode } from "./useSelectedNode";
|
import { useSelectedNode } from "./useSelectedNode";
|
||||||
import { extractFeatures } from "../Platform/Hosted/extractFeatures";
|
|
||||||
|
|
||||||
export interface CollectionContextMenuButtonParams {
|
export interface CollectionContextMenuButtonParams {
|
||||||
databaseId: string;
|
databaseId: string;
|
||||||
@@ -57,7 +59,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
|||||||
{
|
{
|
||||||
iconSrc: AddCollectionIcon,
|
iconSrc: AddCollectionIcon,
|
||||||
onClick: () => container.onNewCollectionClicked({ databaseId }),
|
onClick: () => container.onNewCollectionClicked({ databaseId }),
|
||||||
label: `New ${getCollectionName()}`,
|
label: t(Keys.contextMenu.newContainer, { containerName: getCollectionName() }),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
|||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddCollectionIcon,
|
iconSrc: AddCollectionIcon,
|
||||||
onClick: () => openRestoreContainerDialog(),
|
onClick: () => openRestoreContainerDialog(),
|
||||||
label: `Restore ${getCollectionName()}`,
|
label: t(Keys.contextMenu.restoreContainer, { containerName: getCollectionName() }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,11 +82,11 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
|||||||
useSidePanel
|
useSidePanel
|
||||||
.getState()
|
.getState()
|
||||||
.openSidePanel(
|
.openSidePanel(
|
||||||
"Delete " + getDatabaseName(),
|
t(Keys.contextMenu.deleteDatabase, { databaseName: getDatabaseName() }),
|
||||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => container.refreshAllDatabases()} />,
|
<DeleteDatabaseConfirmationPanel refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
label: `Delete ${getDatabaseName()}`,
|
label: t(Keys.contextMenu.deleteDatabase, { databaseName: getDatabaseName() }),
|
||||||
styleClass: "deleteDatabaseMenuItem",
|
styleClass: "deleteDatabaseMenuItem",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,7 +102,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddSqlQueryIcon,
|
iconSrc: AddSqlQueryIcon,
|
||||||
onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, undefined),
|
onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, undefined),
|
||||||
label: "New SQL Query",
|
label: t(Keys.contextMenu.newSqlQuery),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddSqlQueryIcon,
|
iconSrc: AddSqlQueryIcon,
|
||||||
onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, undefined),
|
onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, undefined),
|
||||||
label: "New Query",
|
label: t(Keys.contextMenu.newQuery),
|
||||||
});
|
});
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
@@ -123,8 +125,8 @@ export const createCollectionContextMenuButton = (
|
|||||||
},
|
},
|
||||||
label:
|
label:
|
||||||
useNotebook.getState().isShellEnabled || userContext.features.enableCloudShell
|
useNotebook.getState().isShellEnabled || userContext.features.enableCloudShell
|
||||||
? "Open Mongo Shell"
|
? t(Keys.contextMenu.openMongoShell)
|
||||||
: "New Shell",
|
: t(Keys.contextMenu.newShell),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
container.openNotebookTerminal(ViewModels.TerminalKind.Cassandra);
|
container.openNotebookTerminal(ViewModels.TerminalKind.Cassandra);
|
||||||
},
|
},
|
||||||
label: "Open Cassandra Shell",
|
label: t(Keys.contextMenu.openCassandraShell),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +152,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, undefined);
|
selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, undefined);
|
||||||
},
|
},
|
||||||
label: "New Stored Procedure",
|
label: t(Keys.contextMenu.newStoredProcedure),
|
||||||
});
|
});
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
@@ -158,7 +160,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection);
|
selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection);
|
||||||
},
|
},
|
||||||
label: "New UDF",
|
label: t(Keys.contextMenu.newUdf),
|
||||||
});
|
});
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
@@ -166,7 +168,7 @@ export const createCollectionContextMenuButton = (
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, undefined);
|
selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, undefined);
|
||||||
},
|
},
|
||||||
label: "New Trigger",
|
label: t(Keys.contextMenu.newTrigger),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,11 +181,11 @@ export const createCollectionContextMenuButton = (
|
|||||||
useSidePanel
|
useSidePanel
|
||||||
.getState()
|
.getState()
|
||||||
.openSidePanel(
|
.openSidePanel(
|
||||||
"Delete " + getCollectionName(),
|
t(Keys.contextMenu.deleteContainer, { containerName: getCollectionName() }),
|
||||||
<DeleteCollectionConfirmationPane refreshDatabases={() => container.refreshAllDatabases()} />,
|
<DeleteCollectionConfirmationPane refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
label: `Delete ${getCollectionName()}`,
|
label: t(Keys.contextMenu.deleteContainer, { containerName: getCollectionName() }),
|
||||||
styleClass: "deleteCollectionMenuItem",
|
styleClass: "deleteCollectionMenuItem",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -220,14 +222,14 @@ export const createSampleCollectionContextMenuButton = (): TreeNodeMenuItem[] =>
|
|||||||
useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot);
|
useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot);
|
||||||
traceOpen(Action.OpenQueryCopilotFromNewQuery, { apiType: userContext.apiType });
|
traceOpen(Action.OpenQueryCopilotFromNewQuery, { apiType: userContext.apiType });
|
||||||
},
|
},
|
||||||
label: "New SQL Query",
|
label: t(Keys.contextMenu.newSqlQuery),
|
||||||
});
|
});
|
||||||
} else if (copilotVersion === "v2.0") {
|
} else if (copilotVersion === "v2.0") {
|
||||||
const sampleCollection = useDatabases.getState().sampleDataResourceTokenCollection;
|
const sampleCollection = useDatabases.getState().sampleDataResourceTokenCollection;
|
||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddSqlQueryIcon,
|
iconSrc: AddSqlQueryIcon,
|
||||||
onClick: () => sampleCollection && sampleCollection.onNewQueryClick(sampleCollection, undefined),
|
onClick: () => sampleCollection && sampleCollection.onNewQueryClick(sampleCollection, undefined),
|
||||||
label: "New SQL Query",
|
label: t(Keys.contextMenu.newSqlQuery),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +249,7 @@ export const createStoreProcedureContextMenuItems = (
|
|||||||
{
|
{
|
||||||
iconSrc: DeleteSprocIcon,
|
iconSrc: DeleteSprocIcon,
|
||||||
onClick: () => storedProcedure.delete(),
|
onClick: () => storedProcedure.delete(),
|
||||||
label: "Delete Stored Procedure",
|
label: t(Keys.contextMenu.deleteStoredProcedure),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -261,7 +263,7 @@ export const createTriggerContextMenuItems = (container: Explorer, trigger: Trig
|
|||||||
{
|
{
|
||||||
iconSrc: DeleteTriggerIcon,
|
iconSrc: DeleteTriggerIcon,
|
||||||
onClick: () => trigger.delete(),
|
onClick: () => trigger.delete(),
|
||||||
label: "Delete Trigger",
|
label: t(Keys.contextMenu.deleteTrigger),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -278,7 +280,7 @@ export const createUserDefinedFunctionContextMenuItems = (
|
|||||||
{
|
{
|
||||||
iconSrc: DeleteUDFIcon,
|
iconSrc: DeleteUDFIcon,
|
||||||
onClick: () => userDefinedFunction.delete(),
|
onClick: () => userDefinedFunction.delete(),
|
||||||
label: "Delete User Defined Function",
|
label: t(Keys.contextMenu.deleteUdf),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import { queryConflicts } from "../../Common/dataAccess/queryConflicts";
|
|||||||
import { updateDocument } from "../../Common/dataAccess/updateDocument";
|
import { updateDocument } from "../../Common/dataAccess/updateDocument";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
|
import { Keys } from "../../Localization/Keys.generated";
|
||||||
|
import { t } from "../../Localization/t";
|
||||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
@@ -57,7 +59,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
|
|
||||||
private _documentsIterator: MinimalQueryIterator;
|
private _documentsIterator: MinimalQueryIterator;
|
||||||
private _container: Explorer;
|
private _container: Explorer;
|
||||||
private _acceptButtonLabel: ko.Observable<string> = ko.observable("Save");
|
private _acceptButtonLabel: ko.Observable<string> = ko.observable(t(Keys.common.save));
|
||||||
|
|
||||||
constructor(options: ViewModels.ConflictsTabOptions) {
|
constructor(options: ViewModels.ConflictsTabOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
@@ -213,9 +215,9 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
this.selectedConflictContent.subscribe((newContent: string) => this._onEditorContentChange(newContent));
|
this.selectedConflictContent.subscribe((newContent: string) => this._onEditorContentChange(newContent));
|
||||||
|
|
||||||
this.conflictOperation.subscribe((newOperationType: string) => {
|
this.conflictOperation.subscribe((newOperationType: string) => {
|
||||||
let operationLabel = "Save";
|
let operationLabel = t(Keys.common.save);
|
||||||
if (newOperationType === Constants.ConflictOperationType.Replace) {
|
if (newOperationType === Constants.ConflictOperationType.Replace) {
|
||||||
operationLabel = "Update";
|
operationLabel = t(Keys.common.update);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._acceptButtonLabel(operationLabel);
|
this._acceptButtonLabel(operationLabel);
|
||||||
@@ -229,7 +231,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
this._documentsIterator = this.createIterator();
|
this._documentsIterator = this.createIterator();
|
||||||
await this.loadNextPage();
|
await this.loadNextPage();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
useDialog.getState().showOkModalDialog("Refresh documents grid failed", getErrorMessage(error));
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.conflicts.refreshGridFailed), getErrorMessage(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,11 +259,11 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
useDialog
|
useDialog
|
||||||
.getState()
|
.getState()
|
||||||
.showOkCancelModalDialog(
|
.showOkCancelModalDialog(
|
||||||
"Unsaved changes",
|
t(Keys.tabs.conflicts.unsavedChanges),
|
||||||
"Changes will be lost. Do you want to continue?",
|
t(Keys.tabs.conflicts.changesWillBeLost),
|
||||||
"OK",
|
t(Keys.common.ok),
|
||||||
async () => await this.resolveConflict(),
|
async () => await this.resolveConflict(),
|
||||||
"Cancel",
|
t(Keys.common.cancel),
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -332,7 +334,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isExecutionError(true);
|
this.isExecutionError(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Resolve conflict failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.conflicts.resolveConflictFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.ResolveConflict,
|
Action.ResolveConflict,
|
||||||
{
|
{
|
||||||
@@ -386,7 +388,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isExecutionError(true);
|
this.isExecutionError(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Delete conflict failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.conflicts.deleteConflictFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.DeleteConflict,
|
Action.DeleteConflict,
|
||||||
{
|
{
|
||||||
@@ -617,7 +619,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.discardButton.visible()) {
|
if (this.discardButton.visible()) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DiscardIcon,
|
iconSrc: DiscardIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -630,7 +632,7 @@ export default class ConflictsTab extends TabsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.deleteButton.visible()) {
|
if (this.deleteButton.visible()) {
|
||||||
const label = "Delete";
|
const label = t(Keys.common.delete);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DeleteIcon,
|
iconSrc: DeleteIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import { usePrevious } from "Explorer/Tabs/DocumentsTabV2/SelectionHelper";
|
|||||||
import { CosmosFluentProvider, LayoutConstants, cosmosShorthands, tokens } from "Explorer/Theme/ThemeUtil";
|
import { CosmosFluentProvider, LayoutConstants, cosmosShorthands, tokens } from "Explorer/Theme/ThemeUtil";
|
||||||
import { useSelectedNode } from "Explorer/useSelectedNode";
|
import { useSelectedNode } from "Explorer/useSelectedNode";
|
||||||
import { KeyboardAction, KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
import { KeyboardAction, KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
||||||
|
import { Keys } from "Localization/Keys.generated";
|
||||||
|
import { t } from "Localization/t";
|
||||||
import { isFabric } from "Platform/Fabric/FabricUtil";
|
import { isFabric } from "Platform/Fabric/FabricUtil";
|
||||||
import { QueryConstants } from "Shared/Constants";
|
import { QueryConstants } from "Shared/Constants";
|
||||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
@@ -349,7 +351,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
const label = !isPreferredApiMongoDB ? "New Item" : "New Document";
|
const label = !isPreferredApiMongoDB ? t(Keys.tabs.documents.newItem) : t(Keys.tabs.documents.newDocument);
|
||||||
if (getNewDocumentButtonState(editorState).visible) {
|
if (getNewDocumentButtonState(editorState).visible) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: NewDocumentIcon,
|
iconSrc: NewDocumentIcon,
|
||||||
@@ -368,7 +370,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getSaveNewDocumentButtonState(editorState).visible) {
|
if (getSaveNewDocumentButtonState(editorState).visible) {
|
||||||
const label = "Save";
|
const label = t(Keys.common.save);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -386,7 +388,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getDiscardNewDocumentChangesButtonState(editorState).visible) {
|
if (getDiscardNewDocumentChangesButtonState(editorState).visible) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DiscardIcon,
|
iconSrc: DiscardIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -403,7 +405,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getSaveExistingDocumentButtonState(editorState).visible) {
|
if (getSaveExistingDocumentButtonState(editorState).visible) {
|
||||||
const label = "Update";
|
const label = t(Keys.common.update);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -421,7 +423,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getDiscardExistingDocumentChangesButtonState(editorState).visible) {
|
if (getDiscardExistingDocumentChangesButtonState(editorState).visible) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DiscardIcon,
|
iconSrc: DiscardIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -438,7 +440,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedRows.size > 0) {
|
if (selectedRows.size > 0) {
|
||||||
const label = "Delete";
|
const label = t(Keys.common.delete);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DeleteDocumentIcon,
|
iconSrc: DeleteDocumentIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -453,7 +455,7 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isPreferredApiMongoDB) {
|
if (!isPreferredApiMongoDB) {
|
||||||
const label = "Upload Item";
|
const label = t(Keys.tabs.documents.uploadItem);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
id: UPLOAD_BUTTON_ID,
|
id: UPLOAD_BUTTON_ID,
|
||||||
iconSrc: UploadIcon,
|
iconSrc: UploadIcon,
|
||||||
@@ -737,17 +739,18 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
} else if (result.statusCode >= 400) {
|
} else if (result.statusCode >= 400) {
|
||||||
newFailed.push(result.documentId);
|
newFailed.push(result.documentId);
|
||||||
logConsoleError(
|
logConsoleError(
|
||||||
`Failed to delete document ${result.documentId.id()} with status code ${result.statusCode}`,
|
t(Keys.tabs.documents.deleteDocumentFailedLog, {
|
||||||
|
documentId: result.documentId.id(),
|
||||||
|
statusCode: result.statusCode,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logConsoleInfo(`Successfully deleted ${newSuccessful.length} document(s)`);
|
logConsoleInfo(t(Keys.tabs.documents.deleteSuccessLog, { count: newSuccessful.length }));
|
||||||
|
|
||||||
if (newThrottled.length > 0) {
|
if (newThrottled.length > 0) {
|
||||||
logConsoleError(
|
logConsoleError(t(Keys.tabs.documents.deleteThrottledLog, { count: newThrottled.length }));
|
||||||
`Failed to delete ${newThrottled.length} document(s) due to "Request too large" (429) error. Retrying...`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update result of the bulk delete: method is called again, because the state variables changed
|
// Update result of the bulk delete: method is called again, because the state variables changed
|
||||||
@@ -917,11 +920,11 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
useDialog
|
useDialog
|
||||||
.getState()
|
.getState()
|
||||||
.showOkCancelModalDialog(
|
.showOkCancelModalDialog(
|
||||||
"Unsaved changes",
|
t(Keys.tabs.documents.unsavedChanges),
|
||||||
"Your unsaved changes will be lost. Do you want to continue?",
|
t(Keys.tabs.documents.unsavedChangesMessage),
|
||||||
"OK",
|
t(Keys.common.ok),
|
||||||
onDiscard,
|
onDiscard,
|
||||||
"Cancel",
|
t(Keys.common.cancel),
|
||||||
onCancelDiscard,
|
onCancelDiscard,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -1011,7 +1014,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
(error) => {
|
(error) => {
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Create document failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.createDocumentFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.CreateDocument,
|
Action.CreateDocument,
|
||||||
{
|
{
|
||||||
@@ -1097,7 +1100,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
selectedDocumentId.partitionKeyValue = originalPartitionKeyValue;
|
selectedDocumentId.partitionKeyValue = originalPartitionKeyValue;
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Update document failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.updateDocumentFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.UpdateDocument,
|
Action.UpdateDocument,
|
||||||
{
|
{
|
||||||
@@ -1174,7 +1177,12 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
// Remove the check for systemKey, remove call to deleteNoSqlDocument(). deleteNoSqlDocuments() should
|
// Remove the check for systemKey, remove call to deleteNoSqlDocument(). deleteNoSqlDocuments() should
|
||||||
// always be called for NoSQL.
|
// always be called for NoSQL.
|
||||||
deletePromise = deleteNoSqlDocument(_collection, toDeleteDocumentIds[0]).then(() => {
|
deletePromise = deleteNoSqlDocument(_collection, toDeleteDocumentIds[0]).then(() => {
|
||||||
useDialog.getState().showOkModalDialog("Delete document", "Document successfully deleted.");
|
useDialog
|
||||||
|
.getState()
|
||||||
|
.showOkModalDialog(
|
||||||
|
t(Keys.tabs.documents.deleteDocumentDialogTitle),
|
||||||
|
t(Keys.tabs.documents.documentDeleted),
|
||||||
|
);
|
||||||
return [toDeleteDocumentIds[0]];
|
return [toDeleteDocumentIds[0]];
|
||||||
});
|
});
|
||||||
// ----------------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------------
|
||||||
@@ -1251,17 +1259,20 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
useDialog
|
useDialog
|
||||||
.getState()
|
.getState()
|
||||||
.showOkModalDialog(
|
.showOkModalDialog(
|
||||||
"Delete documents",
|
t(Keys.tabs.documents.deleteDocumentsDialogTitle),
|
||||||
`Some documents failed to delete due to a rate limiting error. Please try again later. To prevent this in the future, consider increasing the throughput on your container or database.`,
|
t(Keys.tabs.documents.throttlingError),
|
||||||
{
|
{
|
||||||
linkText: "Learn More",
|
linkText: t(Keys.common.learnMore),
|
||||||
linkUrl: MONGO_THROTTLING_DOC_URL,
|
linkUrl: MONGO_THROTTLING_DOC_URL,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
useDialog
|
useDialog
|
||||||
.getState()
|
.getState()
|
||||||
.showOkModalDialog("Delete documents", `Deleting document(s) failed (${error.message})`);
|
.showOkModalDialog(
|
||||||
|
t(Keys.tabs.documents.deleteDocumentsDialogTitle),
|
||||||
|
t(Keys.tabs.documents.deleteFailed, { error: error.message }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -1275,21 +1286,21 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
const isPlural = selectedRows.size > 1;
|
const isPlural = selectedRows.size > 1;
|
||||||
const documentName = !isPreferredApiMongoDB
|
const documentName = !isPreferredApiMongoDB
|
||||||
? isPlural
|
? isPlural
|
||||||
? `the selected ${selectedRows.size} items`
|
? t(Keys.tabs.documents.selectedItems, { count: selectedRows.size })
|
||||||
: "the selected item"
|
: t(Keys.tabs.documents.selectedItem)
|
||||||
: isPlural
|
: isPlural
|
||||||
? `the selected ${selectedRows.size} documents`
|
? t(Keys.tabs.documents.selectedDocuments, { count: selectedRows.size })
|
||||||
: "the selected document";
|
: t(Keys.tabs.documents.selectedDocument);
|
||||||
const msg = `Are you sure you want to delete ${documentName}?`;
|
const msg = t(Keys.tabs.documents.confirmDelete, { documentName });
|
||||||
|
|
||||||
useDialog
|
useDialog
|
||||||
.getState()
|
.getState()
|
||||||
.showOkCancelModalDialog(
|
.showOkCancelModalDialog(
|
||||||
"Confirm delete",
|
t(Keys.tabs.documents.confirmDeleteTitle),
|
||||||
msg,
|
msg,
|
||||||
"Delete",
|
t(Keys.common.delete),
|
||||||
() => deleteDocuments(Array.from(selectedRows).map((index) => documentIds[index as number])),
|
() => deleteDocuments(Array.from(selectedRows).map((index) => documentIds[index as number])),
|
||||||
"Cancel",
|
t(Keys.common.cancel),
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
}, [deleteDocuments, documentIds, isPreferredApiMongoDB, selectedRows]);
|
}, [deleteDocuments, documentIds, isPreferredApiMongoDB, selectedRows]);
|
||||||
@@ -1823,8 +1834,8 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
|
|
||||||
const partitionKeyProperty = partitionKeyProperties?.[0];
|
const partitionKeyProperty = partitionKeyProperties?.[0];
|
||||||
if (partitionKeyProperty !== "_id" && !_hasShardKeySpecified(documentContent)) {
|
if (partitionKeyProperty !== "_id" && !_hasShardKeySpecified(documentContent)) {
|
||||||
const message = `The document is lacking the shard property: ${partitionKeyProperty}`;
|
const message = t(Keys.tabs.documents.missingShardProperty, { partitionKeyProperty });
|
||||||
useDialog.getState().showOkModalDialog("Create document failed", message);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.createDocumentFailed), message);
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.CreateDocument,
|
Action.CreateDocument,
|
||||||
@@ -1835,7 +1846,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
},
|
},
|
||||||
startKey,
|
startKey,
|
||||||
);
|
);
|
||||||
Logger.logError("Failed to save new document: Document shard key not defined", "MongoDocumentsTab");
|
Logger.logError(t(Keys.tabs.documents.missingShardKeyLog), "MongoDocumentsTab");
|
||||||
throw new Error("Document without shard key");
|
throw new Error("Document without shard key");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1878,7 +1889,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
(error) => {
|
(error) => {
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Create document failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.createDocumentFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.CreateDocument,
|
Action.CreateDocument,
|
||||||
{
|
{
|
||||||
@@ -1949,7 +1960,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
(error) => {
|
(error) => {
|
||||||
onExecutionErrorChange(true);
|
onExecutionErrorChange(true);
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
useDialog.getState().showOkModalDialog("Update document failed", errorMessage);
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.updateDocumentFailed), errorMessage);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.UpdateDocument,
|
Action.UpdateDocument,
|
||||||
{
|
{
|
||||||
@@ -2058,7 +2069,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
useDialog.getState().showOkModalDialog("Refresh documents grid failed", getErrorMessage(error));
|
useDialog.getState().showOkModalDialog(t(Keys.tabs.documents.refreshGridFailed), getErrorMessage(error));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[createIterator, filterContent],
|
[createIterator, filterContent],
|
||||||
@@ -2070,18 +2081,17 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
* @returns 429 warning message
|
* @returns 429 warning message
|
||||||
*/
|
*/
|
||||||
const get429WarningMessageNoSql = (): string => {
|
const get429WarningMessageNoSql = (): string => {
|
||||||
let message = 'Some delete requests failed due to a "Request too large" exception (429)';
|
let message = t(Keys.tabs.documents.requestTooLargeBase);
|
||||||
|
|
||||||
if (bulkDeleteOperation.count === bulkDeleteProcess.successfulIds.length) {
|
if (bulkDeleteOperation.count === bulkDeleteProcess.successfulIds.length) {
|
||||||
message += ", but were successfully retried.";
|
message += ", " + t(Keys.tabs.documents.retriedSuccessfully);
|
||||||
} else if (bulkDeleteMode === "inProgress" || bulkDeleteMode === "aborting") {
|
} else if (bulkDeleteMode === "inProgress" || bulkDeleteMode === "aborting") {
|
||||||
message += ". Retrying now.";
|
message += ". " + t(Keys.tabs.documents.retryingNow);
|
||||||
} else {
|
} else {
|
||||||
message += ".";
|
message += ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
return (message +=
|
return (message += " " + t(Keys.tabs.documents.increaseThroughputTip));
|
||||||
" To prevent this in the future, consider increasing the throughput on your container or database.");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onColumnSelectionChange = (newSelectedColumnIds: string[]): void => {
|
const onColumnSelectionChange = (newSelectedColumnIds: string[]): void => {
|
||||||
@@ -2128,7 +2138,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
const nonBlankLastFilters = lastFilterContents.filter((filter) => filter.trim() !== "");
|
const nonBlankLastFilters = lastFilterContents.filter((filter) => filter.trim() !== "");
|
||||||
if (nonBlankLastFilters.length > 0) {
|
if (nonBlankLastFilters.length > 0) {
|
||||||
options.push({
|
options.push({
|
||||||
label: "Saved filters",
|
label: t(Keys.tabs.documents.savedFilters),
|
||||||
options: nonBlankLastFilters,
|
options: nonBlankLastFilters,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2157,14 +2167,14 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
dropdownOptions={getFilterChoices()}
|
dropdownOptions={getFilterChoices()}
|
||||||
placeholder={
|
placeholder={
|
||||||
isPreferredApiMongoDB
|
isPreferredApiMongoDB
|
||||||
? "Type a query predicate (e.g., {´a´:´foo´}), or choose one from the drop down list, or leave empty to query all documents."
|
? t(Keys.tabs.documents.mongoFilterPlaceholder)
|
||||||
: "Type a query predicate (e.g., WHERE c.id=´1´), or choose one from the drop down list, or leave empty to query all documents."
|
: t(Keys.tabs.documents.sqlFilterPlaceholder)
|
||||||
}
|
}
|
||||||
title="Type a query predicate or choose one from the list."
|
title={t(Keys.tabs.documents.filterTooltip)}
|
||||||
value={filterContent}
|
value={filterContent}
|
||||||
onChange={updateFilterContent}
|
onChange={updateFilterContent}
|
||||||
onKeyDown={onFilterKeyDown}
|
onKeyDown={onFilterKeyDown}
|
||||||
bottomLink={{ text: "Learn more", url: DATA_EXPLORER_DOC_URL }}
|
bottomLink={{ text: t(Keys.common.learnMore), url: DATA_EXPLORER_DOC_URL }}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
appearance="primary"
|
appearance="primary"
|
||||||
@@ -2180,10 +2190,12 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={isExecuting && isPreferredApiMongoDB}
|
disabled={isExecuting && isPreferredApiMongoDB}
|
||||||
aria-label={!isExecuting || isPreferredApiMongoDB ? "Apply filter" : "Cancel"}
|
aria-label={
|
||||||
|
!isExecuting || isPreferredApiMongoDB ? t(Keys.tabs.documents.applyFilter) : t(Keys.common.cancel)
|
||||||
|
}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
{!isExecuting || isPreferredApiMongoDB ? "Apply Filter" : "Cancel"}
|
{!isExecuting || isPreferredApiMongoDB ? t(Keys.tabs.documents.applyFilter) : t(Keys.common.cancel)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Allotment
|
<Allotment
|
||||||
@@ -2227,14 +2239,14 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
</div>
|
</div>
|
||||||
{tableContainerSizePx?.width >= calculateOffset(selectedColumnIds.length) + 200 && (
|
{tableContainerSizePx?.width >= calculateOffset(selectedColumnIds.length) + 200 && (
|
||||||
<div
|
<div
|
||||||
title="Refresh"
|
title={t(Keys.common.refresh)}
|
||||||
className={styles.refreshBtn}
|
className={styles.refreshBtn}
|
||||||
role="button"
|
role="button"
|
||||||
onClick={() => refreshDocumentsGrid(false)}
|
onClick={() => refreshDocumentsGrid(false)}
|
||||||
aria-label="Refresh"
|
aria-label={t(Keys.common.refresh)}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<img src={RefreshIcon} alt="Refresh" />
|
<img src={RefreshIcon} alt={t(Keys.common.refresh)} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2247,7 +2259,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
onClick={() => loadNextPage(documentsIterator.iterator, false)}
|
onClick={() => loadNextPage(documentsIterator.iterator, false)}
|
||||||
onKeyDown={onLoadMoreKeyInput}
|
onKeyDown={onLoadMoreKeyInput}
|
||||||
>
|
>
|
||||||
Load more
|
{t(Keys.tabs.documents.loadMore)}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2259,7 +2271,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
language={"json"}
|
language={"json"}
|
||||||
content={selectedDocumentContent}
|
content={selectedDocumentContent}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
ariaLabel={"Document editor"}
|
ariaLabel={t(Keys.tabs.documents.documentEditor)}
|
||||||
lineNumbers={"on"}
|
lineNumbers={"on"}
|
||||||
theme={"_theme"}
|
theme={"_theme"}
|
||||||
onContentChanged={_onEditorContentChange}
|
onContentChanged={_onEditorContentChange}
|
||||||
@@ -2267,7 +2279,9 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{selectedRows.size > 1 && (
|
{selectedRows.size > 1 && (
|
||||||
<span style={{ margin: 10 }}>Number of selected documents: {selectedRows.size}</span>
|
<span style={{ margin: 10 }}>
|
||||||
|
{t(Keys.tabs.documents.numberOfSelectedDocuments, { count: selectedRows.size })}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Allotment.Pane>
|
</Allotment.Pane>
|
||||||
@@ -2276,42 +2290,43 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
{bulkDeleteOperation && (
|
{bulkDeleteOperation && (
|
||||||
<ProgressModalDialog
|
<ProgressModalDialog
|
||||||
isOpen={isBulkDeleteDialogOpen}
|
isOpen={isBulkDeleteDialogOpen}
|
||||||
dismissText="Abort"
|
dismissText={t(Keys.tabs.documents.abort)}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
setIsBulkDeleteDialogOpen(false);
|
setIsBulkDeleteDialogOpen(false);
|
||||||
setBulkDeleteOperation(undefined);
|
setBulkDeleteOperation(undefined);
|
||||||
}}
|
}}
|
||||||
onCancel={() => setBulkDeleteMode("aborting")}
|
onCancel={() => setBulkDeleteMode("aborting")}
|
||||||
title={`Deleting ${bulkDeleteOperation.count} document(s)`}
|
title={t(Keys.tabs.documents.deletingDocuments, { count: bulkDeleteOperation.count })}
|
||||||
message={`Successfully deleted ${bulkDeleteProcess.successfulIds.length} document(s).`}
|
message={t(Keys.tabs.documents.deletedDocumentsSuccess, { count: bulkDeleteProcess.successfulIds.length })}
|
||||||
maxValue={bulkDeleteOperation.count}
|
maxValue={bulkDeleteOperation.count}
|
||||||
value={bulkDeleteProcess.successfulIds.length}
|
value={bulkDeleteProcess.successfulIds.length}
|
||||||
mode={bulkDeleteMode}
|
mode={bulkDeleteMode}
|
||||||
>
|
>
|
||||||
<div className={styles.deleteProgressContent}>
|
<div className={styles.deleteProgressContent}>
|
||||||
{(bulkDeleteMode === "aborting" || bulkDeleteMode === "aborted") && (
|
{(bulkDeleteMode === "aborting" || bulkDeleteMode === "aborted") && (
|
||||||
<div style={{ paddingBottom: tokens.spacingVerticalL }}>Deleting document(s) was aborted.</div>
|
<div style={{ paddingBottom: tokens.spacingVerticalL }}>{t(Keys.tabs.documents.deleteAborted)}</div>
|
||||||
)}
|
)}
|
||||||
{(bulkDeleteProcess.failedIds.length > 0 ||
|
{(bulkDeleteProcess.failedIds.length > 0 ||
|
||||||
(bulkDeleteProcess.throttledIds.length > 0 && bulkDeleteMode !== "inProgress")) && (
|
(bulkDeleteProcess.throttledIds.length > 0 && bulkDeleteMode !== "inProgress")) && (
|
||||||
<MessageBar intent="error" style={{ marginBottom: tokens.spacingVerticalL }}>
|
<MessageBar intent="error" style={{ marginBottom: tokens.spacingVerticalL }}>
|
||||||
<MessageBarBody>
|
<MessageBarBody>
|
||||||
<MessageBarTitle>Error</MessageBarTitle>
|
<MessageBarTitle>{t(Keys.tabs.documents.error)}</MessageBarTitle>
|
||||||
Failed to delete{" "}
|
{t(Keys.tabs.documents.failedToDeleteDocuments, {
|
||||||
{bulkDeleteMode === "inProgress"
|
count:
|
||||||
? bulkDeleteProcess.failedIds.length
|
bulkDeleteMode === "inProgress"
|
||||||
: bulkDeleteProcess.failedIds.length + bulkDeleteProcess.throttledIds.length}{" "}
|
? bulkDeleteProcess.failedIds.length
|
||||||
document(s).
|
: bulkDeleteProcess.failedIds.length + bulkDeleteProcess.throttledIds.length,
|
||||||
|
})}
|
||||||
</MessageBarBody>
|
</MessageBarBody>
|
||||||
</MessageBar>
|
</MessageBar>
|
||||||
)}
|
)}
|
||||||
{bulkDeleteProcess.hasBeenThrottled && (
|
{bulkDeleteProcess.hasBeenThrottled && (
|
||||||
<MessageBar intent="warning">
|
<MessageBar intent="warning">
|
||||||
<MessageBarBody>
|
<MessageBarBody>
|
||||||
<MessageBarTitle>Warning</MessageBarTitle>
|
<MessageBarTitle>{t(Keys.tabs.documents.warning)}</MessageBarTitle>
|
||||||
{get429WarningMessageNoSql()}{" "}
|
{get429WarningMessageNoSql()}{" "}
|
||||||
<Link href={NO_SQL_THROTTLING_DOC_URL} target="_blank">
|
<Link href={NO_SQL_THROTTLING_DOC_URL} target="_blank">
|
||||||
Learn More
|
{t(Keys.common.learnMore)}
|
||||||
</Link>
|
</Link>
|
||||||
</MessageBarBody>
|
</MessageBarBody>
|
||||||
</MessageBar>
|
</MessageBar>
|
||||||
|
|||||||
@@ -44,13 +44,13 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
}
|
}
|
||||||
onChange={[Function]}
|
onChange={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
placeholder="Type a query predicate (e.g., WHERE c.id=´1´), or choose one from the drop down list, or leave empty to query all documents."
|
placeholder="Type a query predicate (e.g., WHERE c.id="1"), or choose one from the drop down list, or leave empty to query all documents."
|
||||||
title="Type a query predicate or choose one from the list."
|
title="Type a query predicate or choose one from the list."
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
appearance="primary"
|
appearance="primary"
|
||||||
aria-label="Apply filter"
|
aria-label="Apply Filter"
|
||||||
data-test="DocumentsTab/ApplyFilter"
|
data-test="DocumentsTab/ApplyFilter"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { configContext } from "../../../ConfigContext";
|
import { configContext } from "../../../ConfigContext";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import { Keys } from "../../../Localization/Keys.generated";
|
||||||
|
import { t } from "../../../Localization/t";
|
||||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { userContext } from "../../../UserContext";
|
import { userContext } from "../../../UserContext";
|
||||||
@@ -212,7 +214,7 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
src={this.state.url}
|
src={this.state.url}
|
||||||
id={this.props.tabsBaseInstance.tabId}
|
id={this.props.tabsBaseInstance.tabId}
|
||||||
onLoad={(event) => this.setContentFocus(event)}
|
onLoad={(event) => this.setContentFocus(event)}
|
||||||
title="Mongo Shell"
|
title={t(Keys.tabs.mongoShell.title)}
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
></iframe>
|
></iframe>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import { QueryTabStyles, useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles
|
|||||||
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
|
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
|
||||||
import { useSelectedNode } from "Explorer/useSelectedNode";
|
import { useSelectedNode } from "Explorer/useSelectedNode";
|
||||||
import { KeyboardAction } from "KeyboardShortcuts";
|
import { KeyboardAction } from "KeyboardShortcuts";
|
||||||
|
import { Keys } from "Localization/Keys.generated";
|
||||||
|
import { t } from "Localization/t";
|
||||||
import { QueryConstants } from "Shared/Constants";
|
import { QueryConstants } from "Shared/Constants";
|
||||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
@@ -315,7 +317,9 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
};
|
};
|
||||||
|
|
||||||
public onSaveQueryClick = (): void => {
|
public onSaveQueryClick = (): void => {
|
||||||
useSidePanel.getState().openSidePanel("Save Query", <SaveQueryPane explorer={this.props.collection.container} />);
|
useSidePanel
|
||||||
|
.getState()
|
||||||
|
.openSidePanel(t(Keys.tabs.query.saveQuery), <SaveQueryPane explorer={this.props.collection.container} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
public launchQueryCopilotChat = (): void => {
|
public launchQueryCopilotChat = (): void => {
|
||||||
@@ -325,7 +329,10 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
public onSavedQueriesClick = (): void => {
|
public onSavedQueriesClick = (): void => {
|
||||||
useSidePanel
|
useSidePanel
|
||||||
.getState()
|
.getState()
|
||||||
.openSidePanel("Open Saved Queries", <BrowseQueriesPane explorer={this.props.collection.container} />);
|
.openSidePanel(
|
||||||
|
t(Keys.tabs.query.openSavedQueries),
|
||||||
|
<BrowseQueriesPane explorer={this.props.collection.container} />,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
public toggleResult(): void {
|
public toggleResult(): void {
|
||||||
@@ -473,7 +480,8 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
if (this.executeQueryButton.visible) {
|
if (this.executeQueryButton.visible) {
|
||||||
const label = this.state.selectedContent?.length > 0 ? "Execute Selection" : "Execute Query";
|
const label =
|
||||||
|
this.state.selectedContent?.length > 0 ? t(Keys.tabs.query.executeSelection) : t(Keys.tabs.query.executeQuery);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: ExecuteQueryIcon,
|
iconSrc: ExecuteQueryIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -490,7 +498,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
|
|
||||||
if (this.saveQueryButton.visible) {
|
if (this.saveQueryButton.visible) {
|
||||||
if (configContext.platform !== Platform.Fabric) {
|
if (configContext.platform !== Platform.Fabric) {
|
||||||
const label = "Save Query";
|
const label = t(Keys.tabs.query.saveQuery);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveQueryIcon,
|
iconSrc: SaveQueryIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -507,11 +515,11 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
|
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DownloadQueryIcon,
|
iconSrc: DownloadQueryIcon,
|
||||||
iconAlt: "Download Query",
|
iconAlt: t(Keys.tabs.query.downloadQuery),
|
||||||
keyboardAction: KeyboardAction.DOWNLOAD_ITEM,
|
keyboardAction: KeyboardAction.DOWNLOAD_ITEM,
|
||||||
onCommandClick: this.onDownloadQueryClick,
|
onCommandClick: this.onDownloadQueryClick,
|
||||||
commandButtonLabel: "Download Query",
|
commandButtonLabel: t(Keys.tabs.query.downloadQuery),
|
||||||
ariaLabel: "Download Query",
|
ariaLabel: t(Keys.tabs.query.downloadQuery),
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.saveQueryButton.enabled,
|
disabled: !this.saveQueryButton.enabled,
|
||||||
});
|
});
|
||||||
@@ -568,7 +576,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (!this.props.isPreferredApiMongoDB && this.state.isExecuting) {
|
if (!this.props.isPreferredApiMongoDB && this.state.isExecuting) {
|
||||||
const label = "Cancel query";
|
const label = t(Keys.tabs.query.cancelQuery);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: CancelQueryIcon,
|
iconSrc: CancelQueryIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -589,23 +597,23 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
const verticalButton: CommandButtonComponentProps = {
|
const verticalButton: CommandButtonComponentProps = {
|
||||||
isSelected: this.state.queryResultsView === SplitterDirection.Vertical,
|
isSelected: this.state.queryResultsView === SplitterDirection.Vertical,
|
||||||
iconSrc: this.state.queryResultsView === SplitterDirection.Vertical ? CheckIcon : undefined,
|
iconSrc: this.state.queryResultsView === SplitterDirection.Vertical ? CheckIcon : undefined,
|
||||||
commandButtonLabel: "Vertical",
|
commandButtonLabel: t(Keys.tabs.query.vertical),
|
||||||
ariaLabel: "Vertical",
|
ariaLabel: t(Keys.tabs.query.vertical),
|
||||||
onCommandClick: () => this._setViewLayout(SplitterDirection.Vertical),
|
onCommandClick: () => this._setViewLayout(SplitterDirection.Vertical),
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
};
|
};
|
||||||
const horizontalButton: CommandButtonComponentProps = {
|
const horizontalButton: CommandButtonComponentProps = {
|
||||||
isSelected: this.state.queryResultsView === SplitterDirection.Horizontal,
|
isSelected: this.state.queryResultsView === SplitterDirection.Horizontal,
|
||||||
iconSrc: this.state.queryResultsView === SplitterDirection.Horizontal ? CheckIcon : undefined,
|
iconSrc: this.state.queryResultsView === SplitterDirection.Horizontal ? CheckIcon : undefined,
|
||||||
commandButtonLabel: "Horizontal",
|
commandButtonLabel: t(Keys.tabs.query.horizontal),
|
||||||
ariaLabel: "Horizontal",
|
ariaLabel: t(Keys.tabs.query.horizontal),
|
||||||
onCommandClick: () => this._setViewLayout(SplitterDirection.Horizontal),
|
onCommandClick: () => this._setViewLayout(SplitterDirection.Horizontal),
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
commandButtonLabel: "View",
|
commandButtonLabel: t(Keys.tabs.query.view),
|
||||||
ariaLabel: "View",
|
ariaLabel: t(Keys.tabs.query.view),
|
||||||
hasPopup: true,
|
hasPopup: true,
|
||||||
children: [verticalButton, horizontalButton],
|
children: [verticalButton, horizontalButton],
|
||||||
};
|
};
|
||||||
@@ -782,7 +790,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
modelMarkers={this.state.modelMarkers}
|
modelMarkers={this.state.modelMarkers}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
wordWrap={"on"}
|
wordWrap={"on"}
|
||||||
ariaLabel={"Editing Query"}
|
ariaLabel={t(Keys.tabs.query.editingQuery)}
|
||||||
lineNumbers={"on"}
|
lineNumbers={"on"}
|
||||||
theme={this.props.monacoTheme}
|
theme={this.props.monacoTheme}
|
||||||
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
|
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { createStoredProcedure } from "../../../Common/dataAccess/createStoredPr
|
|||||||
import { ExecuteSprocResult } from "../../../Common/dataAccess/executeStoredProcedure";
|
import { ExecuteSprocResult } from "../../../Common/dataAccess/executeStoredProcedure";
|
||||||
import { updateStoredProcedure } from "../../../Common/dataAccess/updateStoredProcedure";
|
import { updateStoredProcedure } from "../../../Common/dataAccess/updateStoredProcedure";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import { Keys } from "../../../Localization/Keys.generated";
|
||||||
|
import { t } from "../../../Localization/t";
|
||||||
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
|
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
|
||||||
import { useTabs } from "../../../hooks/useTabs";
|
import { useTabs } from "../../../hooks/useTabs";
|
||||||
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
||||||
@@ -133,7 +135,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
this.collection = this.props.collection;
|
this.collection = this.props.collection;
|
||||||
this.executeResultsEditorId = `executestoredprocedureresults${this.props.scriptTabBaseInstance.tabId}`;
|
this.executeResultsEditorId = `executestoredprocedureresults${this.props.scriptTabBaseInstance.tabId}`;
|
||||||
this.executeLogsEditorId = `executestoredprocedurelogs${this.props.scriptTabBaseInstance.tabId}`;
|
this.executeLogsEditorId = `executestoredprocedurelogs${this.props.scriptTabBaseInstance.tabId}`;
|
||||||
this.props.scriptTabBaseInstance.ariaLabel("Stored Procedure Body");
|
this.props.scriptTabBaseInstance.ariaLabel(t(Keys.tabs.storedProcedure.body));
|
||||||
|
|
||||||
this.props.iStorProcTabComponentAccessor({
|
this.props.iStorProcTabComponentAccessor({
|
||||||
onExecuteSprocsResultEvent: this.onExecuteSprocsResult.bind(this),
|
onExecuteSprocsResultEvent: this.onExecuteSprocsResult.bind(this),
|
||||||
@@ -318,7 +320,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
|
|
||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
const label = "Save";
|
const label = t(Keys.common.save);
|
||||||
if (this.state.saveButton.visible) {
|
if (this.state.saveButton.visible) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
@@ -333,7 +335,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.updateButton.visible) {
|
if (this.state.updateButton.visible) {
|
||||||
const label = "Update";
|
const label = t(Keys.common.update);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -347,7 +349,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.discardButton.visible) {
|
if (this.state.discardButton.visible) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: DiscardIcon,
|
iconSrc: DiscardIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -361,7 +363,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.executeButton.visible) {
|
if (this.state.executeButton.visible) {
|
||||||
const label = "Execute";
|
const label = t(Keys.common.execute);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: ExecuteQueryIcon,
|
iconSrc: ExecuteQueryIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
@@ -519,7 +521,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
<div className="tab-pane flexContainer stored-procedure-tab" role="tabpanel">
|
<div className="tab-pane flexContainer stored-procedure-tab" role="tabpanel">
|
||||||
<div className="storedTabForm flexContainer">
|
<div className="storedTabForm flexContainer">
|
||||||
<div className="formTitleFirst">
|
<div className="formTitleFirst">
|
||||||
Stored Procedure Id
|
{t(Keys.tabs.storedProcedure.id)}
|
||||||
<span className="mandatoryStar" style={{ color: "#ff0707", fontSize: "14px", fontWeight: "bold" }}>
|
<span className="mandatoryStar" style={{ color: "#ff0707", fontSize: "14px", fontWeight: "bold" }}>
|
||||||
*
|
*
|
||||||
</span>
|
</span>
|
||||||
@@ -531,28 +533,28 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
required
|
required
|
||||||
pattern={ValidCosmosDbIdInputPattern.source}
|
pattern={ValidCosmosDbIdInputPattern.source}
|
||||||
title={ValidCosmosDbIdDescription}
|
title={ValidCosmosDbIdDescription}
|
||||||
aria-label="Stored procedure id"
|
aria-label={t(Keys.tabs.storedProcedure.idAriaLabel)}
|
||||||
placeholder="Enter the new stored procedure id"
|
placeholder={t(Keys.tabs.storedProcedure.idPlaceholder)}
|
||||||
size={40}
|
size={40}
|
||||||
value={this.state.id}
|
value={this.state.id}
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => this.handleIdOnChange(event)}
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => this.handleIdOnChange(event)}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<div className="spUdfTriggerHeader">Stored Procedure Body</div>
|
<div className="spUdfTriggerHeader">{t(Keys.tabs.storedProcedure.body)}</div>
|
||||||
<EditorReact
|
<EditorReact
|
||||||
language={"javascript"}
|
language={"javascript"}
|
||||||
content={this.state.sProcEditorContent}
|
content={this.state.sProcEditorContent}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
ariaLabel={"Stored procedure body"}
|
ariaLabel={t(Keys.tabs.storedProcedure.bodyAriaLabel)}
|
||||||
lineNumbers={"on"}
|
lineNumbers={"on"}
|
||||||
theme={"_theme"}
|
theme={"_theme"}
|
||||||
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
|
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
|
||||||
/>
|
/>
|
||||||
{this.state.hasResults && (
|
{this.state.hasResults && (
|
||||||
<div className="results-container">
|
<div className="results-container">
|
||||||
<Pivot aria-label="Successful execution of stored procedure" style={{ height: "100%" }}>
|
<Pivot aria-label={t(Keys.tabs.storedProcedure.successfulExecution)} style={{ height: "100%" }}>
|
||||||
<PivotItem
|
<PivotItem
|
||||||
headerText="Result"
|
headerText={t(Keys.common.result)}
|
||||||
headerButtonProps={{
|
headerButtonProps={{
|
||||||
"data-order": 1,
|
"data-order": 1,
|
||||||
"data-title": "Result",
|
"data-title": "Result",
|
||||||
@@ -563,11 +565,11 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
language={"javascript"}
|
language={"javascript"}
|
||||||
content={this.state.resultData}
|
content={this.state.resultData}
|
||||||
isReadOnly={true}
|
isReadOnly={true}
|
||||||
ariaLabel={"Execute stored procedure result"}
|
ariaLabel={t(Keys.tabs.storedProcedure.resultAriaLabel)}
|
||||||
/>
|
/>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
<PivotItem
|
<PivotItem
|
||||||
headerText="console.log"
|
headerText={t(Keys.tabs.storedProcedure.consoleLogTab)}
|
||||||
headerButtonProps={{
|
headerButtonProps={{
|
||||||
"data-order": 2,
|
"data-order": 2,
|
||||||
"data-title": "console.log",
|
"data-title": "console.log",
|
||||||
@@ -578,7 +580,7 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
language={"javascript"}
|
language={"javascript"}
|
||||||
content={this.state.logsData}
|
content={this.state.logsData}
|
||||||
isReadOnly={true}
|
isReadOnly={true}
|
||||||
ariaLabel={"Execute stored procedure logs"}
|
ariaLabel={t(Keys.tabs.storedProcedure.logsAriaLabel)}
|
||||||
/>
|
/>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
</Pivot>
|
</Pivot>
|
||||||
@@ -586,16 +588,16 @@ export default class StoredProcedureTabComponent extends React.Component<
|
|||||||
)}
|
)}
|
||||||
{this.state.hasErrors && (
|
{this.state.hasErrors && (
|
||||||
<div className="errors-container">
|
<div className="errors-container">
|
||||||
<div className="errors-header">Errors:</div>
|
<div className="errors-header">{t(Keys.tabs.storedProcedure.errors)}</div>
|
||||||
<div className="errorContent">
|
<div className="errorContent">
|
||||||
<span className="errorMessage">{this.state.error}</span>
|
<span className="errorMessage">{this.state.error}</span>
|
||||||
<span className="errorDetailsLink">
|
<span className="errorDetailsLink">
|
||||||
<a
|
<a
|
||||||
aria-label="Error details link"
|
aria-label={t(Keys.tabs.storedProcedure.errorDetailsAriaLabel)}
|
||||||
onClick={() => this.onErrorDetailsClick()}
|
onClick={() => this.onErrorDetailsClick()}
|
||||||
onKeyPress={(event: React.KeyboardEvent<HTMLAnchorElement>) => this.onErrorDetailsKeyPress(event)}
|
onKeyPress={(event: React.KeyboardEvent<HTMLAnchorElement>) => this.onErrorDetailsKeyPress(event)}
|
||||||
>
|
>
|
||||||
More details
|
{t(Keys.tabs.storedProcedure.moreDetails)}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"
|
|||||||
import { createTrigger } from "../../Common/dataAccess/createTrigger";
|
import { createTrigger } from "../../Common/dataAccess/createTrigger";
|
||||||
import { updateTrigger } from "../../Common/dataAccess/updateTrigger";
|
import { updateTrigger } from "../../Common/dataAccess/updateTrigger";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
|
import { Keys } from "../../Localization/Keys.generated";
|
||||||
|
import { t } from "../../Localization/t";
|
||||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
|
import { SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
|
||||||
@@ -19,8 +21,8 @@ import { EditorReact } from "../Controls/Editor/EditorReact";
|
|||||||
import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter";
|
import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
import TriggerTab from "./TriggerTab";
|
import TriggerTab from "./TriggerTab";
|
||||||
const triggerTypeOptions: IDropdownOption[] = [
|
const triggerTypeOptions: IDropdownOption[] = [
|
||||||
{ key: "Pre", text: "Pre" },
|
{ key: "Pre", text: t(Keys.tabs.trigger.pre) },
|
||||||
{ key: "Post", text: "Post" },
|
{ key: "Post", text: t(Keys.tabs.trigger.post) },
|
||||||
];
|
];
|
||||||
|
|
||||||
const dropdownStyles: Partial<IDropdownStyles> = {
|
const dropdownStyles: Partial<IDropdownStyles> = {
|
||||||
@@ -147,10 +149,10 @@ const dropdownStyles: Partial<IDropdownStyles> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const triggerOperationOptions: IDropdownOption[] = [
|
const triggerOperationOptions: IDropdownOption[] = [
|
||||||
{ key: "All", text: "All" },
|
{ key: "All", text: t(Keys.tabs.trigger.all) },
|
||||||
{ key: "Create", text: "Create" },
|
{ key: "Create", text: t(Keys.tabs.trigger.operationCreate) },
|
||||||
{ key: "Delete", text: "Delete" },
|
{ key: "Delete", text: t(Keys.tabs.trigger.operationDelete) },
|
||||||
{ key: "Replace", text: "Replace" },
|
{ key: "Replace", text: t(Keys.tabs.trigger.operationReplace) },
|
||||||
];
|
];
|
||||||
|
|
||||||
interface Ibutton {
|
interface Ibutton {
|
||||||
@@ -334,7 +336,7 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
|
|
||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
const label = "Save";
|
const label = t(Keys.common.save);
|
||||||
if (this.saveButton.visible) {
|
if (this.saveButton.visible) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
setState: this.setState,
|
setState: this.setState,
|
||||||
@@ -351,7 +353,7 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.updateButton.visible) {
|
if (this.updateButton.visible) {
|
||||||
const label = "Update";
|
const label = t(Keys.common.update);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
@@ -366,7 +368,7 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.discardButton.visible) {
|
if (this.discardButton.visible) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
setState: this.setState,
|
setState: this.setState,
|
||||||
...this,
|
...this,
|
||||||
@@ -415,14 +417,14 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
<div className="tab-pane flexContainer trigger-form" role="tabpanel">
|
<div className="tab-pane flexContainer trigger-form" role="tabpanel">
|
||||||
<TextField
|
<TextField
|
||||||
className="trigger-field"
|
className="trigger-field"
|
||||||
label="Trigger Id"
|
label={t(Keys.tabs.trigger.id)}
|
||||||
id="entityTimeId"
|
id="entityTimeId"
|
||||||
autoFocus
|
autoFocus
|
||||||
required
|
required
|
||||||
type="text"
|
type="text"
|
||||||
pattern={ValidCosmosDbIdInputPattern.source}
|
pattern={ValidCosmosDbIdInputPattern.source}
|
||||||
title={ValidCosmosDbIdDescription}
|
title={ValidCosmosDbIdDescription}
|
||||||
placeholder="Enter the new trigger id"
|
placeholder={t(Keys.tabs.trigger.idPlaceholder)}
|
||||||
size={40}
|
size={40}
|
||||||
value={triggerId}
|
value={triggerId}
|
||||||
readOnly={!isIdEditable}
|
readOnly={!isIdEditable}
|
||||||
@@ -446,8 +448,8 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
placeholder="Trigger Type"
|
placeholder={t(Keys.tabs.trigger.type)}
|
||||||
label="Trigger Type"
|
label={t(Keys.tabs.trigger.type)}
|
||||||
options={triggerTypeOptions}
|
options={triggerTypeOptions}
|
||||||
selectedKey={triggerType}
|
selectedKey={triggerType}
|
||||||
className="trigger-field"
|
className="trigger-field"
|
||||||
@@ -455,8 +457,8 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
styles={dropdownStyles}
|
styles={dropdownStyles}
|
||||||
/>
|
/>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
placeholder="Trigger Operation"
|
placeholder={t(Keys.tabs.trigger.operation)}
|
||||||
label="Trigger Operation"
|
label={t(Keys.tabs.trigger.operation)}
|
||||||
selectedKey={triggerOperation}
|
selectedKey={triggerOperation}
|
||||||
options={triggerOperationOptions}
|
options={triggerOperationOptions}
|
||||||
className="trigger-field"
|
className="trigger-field"
|
||||||
@@ -465,12 +467,12 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
|
|||||||
}
|
}
|
||||||
styles={dropdownStyles}
|
styles={dropdownStyles}
|
||||||
/>
|
/>
|
||||||
<Label className="trigger-field">Trigger Body</Label>
|
<Label className="trigger-field">{t(Keys.tabs.trigger.body)}</Label>
|
||||||
<EditorReact
|
<EditorReact
|
||||||
language={"json"}
|
language={"json"}
|
||||||
content={triggerBody}
|
content={triggerBody}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
ariaLabel={"Graph JSON"}
|
ariaLabel={t(Keys.tabs.trigger.bodyAriaLabel)}
|
||||||
onContentChanged={this.handleTriggerBodyChange}
|
onContentChanged={this.handleTriggerBodyChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"
|
|||||||
import { createUserDefinedFunction } from "../../Common/dataAccess/createUserDefinedFunction";
|
import { createUserDefinedFunction } from "../../Common/dataAccess/createUserDefinedFunction";
|
||||||
import { updateUserDefinedFunction } from "../../Common/dataAccess/updateUserDefinedFunction";
|
import { updateUserDefinedFunction } from "../../Common/dataAccess/updateUserDefinedFunction";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
|
import { Keys } from "../../Localization/Keys.generated";
|
||||||
|
import { t } from "../../Localization/t";
|
||||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
@@ -82,7 +84,7 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
|
|
||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
const label = "Save";
|
const label = t(Keys.common.save);
|
||||||
if (this.saveButton.visible) {
|
if (this.saveButton.visible) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
@@ -99,7 +101,7 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.updateButton.visible) {
|
if (this.updateButton.visible) {
|
||||||
const label = "Update";
|
const label = t(Keys.common.update);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
...this,
|
...this,
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
@@ -114,7 +116,7 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.discardButton.visible) {
|
if (this.discardButton.visible) {
|
||||||
const label = "Discard";
|
const label = t(Keys.common.discard);
|
||||||
buttons.push({
|
buttons.push({
|
||||||
setState: this.setState,
|
setState: this.setState,
|
||||||
...this,
|
...this,
|
||||||
@@ -265,7 +267,7 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
<FluentProvider theme={currentTheme}>
|
<FluentProvider theme={currentTheme}>
|
||||||
<TextField
|
<TextField
|
||||||
className="trigger-field"
|
className="trigger-field"
|
||||||
label="User Defined Function Id"
|
label={t(Keys.tabs.udf.id)}
|
||||||
id="entityTimeId"
|
id="entityTimeId"
|
||||||
autoFocus
|
autoFocus
|
||||||
required
|
required
|
||||||
@@ -273,7 +275,7 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
type="text"
|
type="text"
|
||||||
pattern={ValidCosmosDbIdInputPattern.source}
|
pattern={ValidCosmosDbIdInputPattern.source}
|
||||||
title={ValidCosmosDbIdDescription}
|
title={ValidCosmosDbIdDescription}
|
||||||
placeholder="Enter the new user defined function id"
|
placeholder={t(Keys.tabs.udf.idPlaceholder)}
|
||||||
size={40}
|
size={40}
|
||||||
value={udfId}
|
value={udfId}
|
||||||
onChange={this.handleUdfIdChange}
|
onChange={this.handleUdfIdChange}
|
||||||
@@ -299,12 +301,12 @@ export default class UserDefinedFunctionTabContent extends Component<
|
|||||||
}}
|
}}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
</FluentProvider>
|
</FluentProvider>
|
||||||
<Label className="trigger-field">User Defined Function Body</Label>
|
<Label className="trigger-field">{t(Keys.tabs.udf.body)}</Label>
|
||||||
<EditorReact
|
<EditorReact
|
||||||
language={"javascript"}
|
language={"javascript"}
|
||||||
content={udfBody}
|
content={udfBody}
|
||||||
isReadOnly={false}
|
isReadOnly={false}
|
||||||
ariaLabel={"User defined function body"}
|
ariaLabel={t(Keys.tabs.udf.bodyAriaLabel)}
|
||||||
onContentChanged={this.handleUdfBodyChange}
|
onContentChanged={this.handleUdfBodyChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -291,5 +291,126 @@
|
|||||||
"errorCreateContainer": "Failed to create container: {{error}}",
|
"errorCreateContainer": "Failed to create container: {{error}}",
|
||||||
"errorImportData": "Failed to import data: {{error}}"
|
"errorImportData": "Failed to import data: {{error}}"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"contextMenu": {
|
||||||
|
"newContainer": "New {{containerName}}",
|
||||||
|
"restoreContainer": "Restore {{containerName}}",
|
||||||
|
"deleteDatabase": "Delete {{databaseName}}",
|
||||||
|
"deleteContainer": "Delete {{containerName}}",
|
||||||
|
"newSqlQuery": "New SQL Query",
|
||||||
|
"newQuery": "New Query",
|
||||||
|
"openMongoShell": "Open Mongo Shell",
|
||||||
|
"newShell": "New Shell",
|
||||||
|
"openCassandraShell": "Open Cassandra Shell",
|
||||||
|
"newStoredProcedure": "New Stored Procedure",
|
||||||
|
"newUdf": "New UDF",
|
||||||
|
"newTrigger": "New Trigger",
|
||||||
|
"deleteStoredProcedure": "Delete Stored Procedure",
|
||||||
|
"deleteTrigger": "Delete Trigger",
|
||||||
|
"deleteUdf": "Delete User Defined Function"
|
||||||
|
},
|
||||||
|
"tabs": {
|
||||||
|
"documents": {
|
||||||
|
"newItem": "New Item",
|
||||||
|
"newDocument": "New Document",
|
||||||
|
"uploadItem": "Upload Item",
|
||||||
|
"applyFilter": "Apply Filter",
|
||||||
|
"unsavedChanges": "Unsaved changes",
|
||||||
|
"unsavedChangesMessage": "Your unsaved changes will be lost. Do you want to continue?",
|
||||||
|
"createDocumentFailed": "Create document failed",
|
||||||
|
"updateDocumentFailed": "Update document failed",
|
||||||
|
"documentDeleted": "Document successfully deleted.",
|
||||||
|
"deleteDocumentDialogTitle": "Delete document",
|
||||||
|
"deleteDocumentsDialogTitle": "Delete documents",
|
||||||
|
"throttlingError": "Some documents failed to delete due to a rate limiting error. Please try again later. To prevent this in the future, consider increasing the throughput on your container or database.",
|
||||||
|
"deleteFailed": "Deleting document(s) failed ({{error}})",
|
||||||
|
"missingShardProperty": "The document is lacking the shard property: {{partitionKeyProperty}}",
|
||||||
|
"refreshGridFailed": "Refresh documents grid failed",
|
||||||
|
"confirmDelete": "Are you sure you want to delete {{documentName}}?",
|
||||||
|
"confirmDeleteTitle": "Confirm delete",
|
||||||
|
"selectedItems": "the selected {{count}} items",
|
||||||
|
"selectedItem": "the selected item",
|
||||||
|
"selectedDocuments": "the selected {{count}} documents",
|
||||||
|
"selectedDocument": "the selected document",
|
||||||
|
"deleteDocumentFailedLog": "Failed to delete document {{documentId}} with status code {{statusCode}}",
|
||||||
|
"deleteSuccessLog": "Successfully deleted {{count}} document(s)",
|
||||||
|
"deleteThrottledLog": "Failed to delete {{count}} document(s) due to \"Request too large\" (429) error. Retrying...",
|
||||||
|
"missingShardKeyLog": "Failed to save new document: Document shard key not defined",
|
||||||
|
"filterTooltip": "Type a query predicate or choose one from the list.",
|
||||||
|
"loadMore": "Load more",
|
||||||
|
"documentEditor": "Document editor",
|
||||||
|
"savedFilters": "Saved filters",
|
||||||
|
"defaultFilters": "Default filters",
|
||||||
|
"abort": "Abort",
|
||||||
|
"deletingDocuments": "Deleting {{count}} document(s)",
|
||||||
|
"deletedDocumentsSuccess": "Successfully deleted {{count}} document(s).",
|
||||||
|
"deleteAborted": "Deleting document(s) was aborted.",
|
||||||
|
"failedToDeleteDocuments": "Failed to delete {{count}} document(s).",
|
||||||
|
"requestTooLargeBase": "Some delete requests failed due to a \"Request too large\" exception (429)",
|
||||||
|
"retriedSuccessfully": "but were successfully retried.",
|
||||||
|
"retryingNow": "Retrying now.",
|
||||||
|
"increaseThroughputTip": "To prevent this in the future, consider increasing the throughput on your container or database.",
|
||||||
|
"numberOfSelectedDocuments": "Number of selected documents: {{count}}",
|
||||||
|
"mongoFilterPlaceholder": "Type a query predicate (e.g., {\"id\":\"foo\"}), or choose one from the drop down list, or leave empty to query all documents.",
|
||||||
|
"sqlFilterPlaceholder": "Type a query predicate (e.g., WHERE c.id=\"1\"), or choose one from the drop down list, or leave empty to query all documents.",
|
||||||
|
"error": "Error",
|
||||||
|
"warning": "Warning"
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"executeQuery": "Execute Query",
|
||||||
|
"executeSelection": "Execute Selection",
|
||||||
|
"saveQuery": "Save Query",
|
||||||
|
"downloadQuery": "Download Query",
|
||||||
|
"cancelQuery": "Cancel query",
|
||||||
|
"openSavedQueries": "Open Saved Queries",
|
||||||
|
"vertical": "Vertical",
|
||||||
|
"horizontal": "Horizontal",
|
||||||
|
"view": "View",
|
||||||
|
"editingQuery": "Editing Query"
|
||||||
|
},
|
||||||
|
"storedProcedure": {
|
||||||
|
"id": "Stored Procedure Id",
|
||||||
|
"idPlaceholder": "Enter the new stored procedure id",
|
||||||
|
"idAriaLabel": "Stored procedure id",
|
||||||
|
"body": "Stored Procedure Body",
|
||||||
|
"bodyAriaLabel": "Stored procedure body",
|
||||||
|
"successfulExecution": "Successful execution of stored procedure",
|
||||||
|
"resultAriaLabel": "Execute stored procedure result",
|
||||||
|
"logsAriaLabel": "Execute stored procedure logs",
|
||||||
|
"errors": "Errors:",
|
||||||
|
"errorDetailsAriaLabel": "Error details link",
|
||||||
|
"moreDetails": "More details",
|
||||||
|
"consoleLogTab": "console.log"
|
||||||
|
},
|
||||||
|
"trigger": {
|
||||||
|
"id": "Trigger Id",
|
||||||
|
"idPlaceholder": "Enter the new trigger id",
|
||||||
|
"type": "Trigger Type",
|
||||||
|
"operation": "Trigger Operation",
|
||||||
|
"body": "Trigger Body",
|
||||||
|
"bodyAriaLabel": "Trigger body",
|
||||||
|
"pre": "Pre",
|
||||||
|
"post": "Post",
|
||||||
|
"all": "All",
|
||||||
|
"operationCreate": "Create",
|
||||||
|
"operationDelete": "Delete",
|
||||||
|
"operationReplace": "Replace"
|
||||||
|
},
|
||||||
|
"udf": {
|
||||||
|
"id": "User Defined Function Id",
|
||||||
|
"idPlaceholder": "Enter the new user defined function id",
|
||||||
|
"body": "User Defined Function Body",
|
||||||
|
"bodyAriaLabel": "User defined function body"
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"unsavedChanges": "Unsaved changes",
|
||||||
|
"changesWillBeLost": "Changes will be lost. Do you want to continue?",
|
||||||
|
"resolveConflictFailed": "Resolve conflict failed",
|
||||||
|
"deleteConflictFailed": "Delete conflict failed",
|
||||||
|
"refreshGridFailed": "Refresh documents grid failed"
|
||||||
|
},
|
||||||
|
"mongoShell": {
|
||||||
|
"title": "Mongo Shell"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ import Adapter from "enzyme-adapter-react-16";
|
|||||||
import "jest-canvas-mock";
|
import "jest-canvas-mock";
|
||||||
import enableHooks from "jest-react-hooks-shallow";
|
import enableHooks from "jest-react-hooks-shallow";
|
||||||
import { TextDecoder, TextEncoder } from "util";
|
import { TextDecoder, TextEncoder } from "util";
|
||||||
|
import i18n from "./i18n";
|
||||||
|
import enResources from "./Localization/en/Resources.json";
|
||||||
configure({ adapter: new Adapter() });
|
configure({ adapter: new Adapter() });
|
||||||
initializeIcons();
|
initializeIcons();
|
||||||
|
|
||||||
|
// Load English translations synchronously so t() returns real values in tests
|
||||||
|
i18n.addResourceBundle("en", "Resources", enResources, true, true);
|
||||||
|
|
||||||
if (typeof window.URL.createObjectURL === "undefined") {
|
if (typeof window.URL.createObjectURL === "undefined") {
|
||||||
Object.defineProperty(window.URL, "createObjectURL", { value: () => {} });
|
Object.defineProperty(window.URL, "createObjectURL", { value: () => {} });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user