From 503f044a70df3ec9fa4b19969c6affc3c5a13f7e Mon Sep 17 00:00:00 2001 From: Steve Faulkner Date: Thu, 6 May 2021 12:35:24 -0500 Subject: [PATCH 1/5] Update strict mode files (#753) --- tsconfig.strict.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tsconfig.strict.json b/tsconfig.strict.json index 736631ee4..15c304aec 100644 --- a/tsconfig.strict.json +++ b/tsconfig.strict.json @@ -43,6 +43,7 @@ "./src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts", "./src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts", "./src/Explorer/Graph/GraphExplorerComponent/GraphData.ts", + "./src/Explorer/LazyMonaco.ts", "./src/Explorer/Notebook/FileSystemUtil.ts", "./src/Explorer/Notebook/NTeractUtil.ts", "./src/Explorer/Notebook/NotebookComponent/actions.ts", @@ -54,6 +55,8 @@ "./src/Explorer/Notebook/NotebookRenderer/AzureTheme.tsx", "./src/Explorer/Notebook/NotebookRenderer/decorators/CellCreator.tsx", "./src/Explorer/Notebook/NotebookUtil.ts", + "./src/Explorer/OpenFullScreen.test.tsx", + "./src/Explorer/OpenFullScreen.tsx", "./src/Explorer/Panes/PaneComponents.ts", "./src/Explorer/Panes/PanelFooterComponent.tsx", "./src/Explorer/Panes/PanelLoadingScreen.tsx", @@ -70,6 +73,7 @@ "./src/HostedExplorerChildFrame.ts", "./src/Index.ts", "./src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts", + "./src/Platform/Hosted/Authorization.ts", "./src/Platform/Hosted/Components/SignInButton.tsx", "./src/Platform/Hosted/extractFeatures.test.ts", "./src/Platform/Hosted/extractFeatures.ts", @@ -87,6 +91,7 @@ "./src/Shared/StringUtility.ts", "./src/Shared/appInsights.ts", "./src/UserContext.ts", + "./src/Utils/APITypeUtils.ts", "./src/Utils/AutoPilotUtils.ts", "./src/Utils/Base64Utils.test.ts", "./src/Utils/Base64Utils.ts", @@ -97,15 +102,19 @@ "./src/Utils/MessageValidation.ts", "./src/Utils/PricingUtils.ts", "./src/Utils/StringUtils.ts", + "./src/Utils/StyleUtils.ts", "./src/Utils/WindowUtils.test.ts", "./src/Utils/WindowUtils.ts", "./src/hooks/useDirectories.tsx", + "./src/hooks/useFullScreenURLs.tsx", + "./src/hooks/useObservable.ts", "./src/i18n.ts", "./src/quickstart.ts", "./src/setupTests.ts", "./src/userContext.test.ts" ], "include": [ + "src/CellOutputViewer/transforms/**/*", "src/Controls/**/*", "src/Definitions/**/*", "src/Explorer/Controls/ErrorDisplayComponent/**/*", From 5606ef3266cfb8c512465b611743c3743564c0ef Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Thu, 6 May 2021 16:51:22 -0700 Subject: [PATCH 2/5] Fix table edit entity bug and add collection panel bug for connection string users (#757) * Fix table edit entity bug and add collection panel bug for connection string users * Remove parseInt for int64 --- src/Explorer/Panes/AddCollectionPanel.tsx | 4 ++-- src/Explorer/Tables/TableEntityProcessor.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Explorer/Panes/AddCollectionPanel.tsx b/src/Explorer/Panes/AddCollectionPanel.tsx index ffbea654a..89eae59fb 100644 --- a/src/Explorer/Panes/AddCollectionPanel.tsx +++ b/src/Explorer/Panes/AddCollectionPanel.tsx @@ -525,7 +525,7 @@ export class AddCollectionPanel extends React.Component - {userContext.databaseAccount.properties.capabilities.find((c) => c.name === "EnableMongo") && ( + {userContext.databaseAccount.properties?.capabilities?.find((c) => c.name === "EnableMongo") && ( @@ -851,7 +851,7 @@ export class AddCollectionPanel extends React.Component capability.name === Constants.CapabilityNames.EnableStorageAnalytics ); } diff --git a/src/Explorer/Tables/TableEntityProcessor.ts b/src/Explorer/Tables/TableEntityProcessor.ts index f26d2c38d..c18f7bab9 100644 --- a/src/Explorer/Tables/TableEntityProcessor.ts +++ b/src/Explorer/Tables/TableEntityProcessor.ts @@ -183,12 +183,14 @@ export function convertEntityToNewDocument(entity: Entities.ITableEntityForTable parsedValue = DateTimeUtilities.convertJSDateToTicksWithPadding(propertyValue); break; case Constants.TableType.Boolean: - parsedValue = propertyValue.toLowerCase() === "true"; + parsedValue = propertyValue.toString().toLowerCase() === "true"; break; case Constants.TableType.Int32: - case Constants.TableType.Int64: parsedValue = parseInt(propertyValue, 10); break; + case Constants.TableType.Int64: + parsedValue = propertyValue.toString(); + break; case Constants.TableType.Double: parsedValue = parseFloat(propertyValue); break; From a91ea6c1e461b470e873e90b17b21a2e0126b033 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Yadav <79906609+sunilyadav840@users.noreply.github.com> Date: Fri, 7 May 2021 05:21:45 +0530 Subject: [PATCH 3/5] Remove old Add/Edit Table Entity code (#755) --- .eslintignore | 4 - src/Explorer/ComponentRegisterer.ts | 2 - src/Explorer/Panes/PaneComponents.ts | 19 -- .../Panes/Tables/EditTableEntityPane.ts | 225 -------------- .../Panes/Tables/EntityPropertyViewModel.ts | 164 ---------- .../Panes/Tables/TableAddEntityPane.html | 190 ------------ .../Panes/Tables/TableEditEntityPane.html | 187 ------------ src/Explorer/Panes/Tables/TableEntityPane.ts | 279 ------------------ 8 files changed, 1070 deletions(-) delete mode 100644 src/Explorer/Panes/Tables/EditTableEntityPane.ts delete mode 100644 src/Explorer/Panes/Tables/EntityPropertyViewModel.ts delete mode 100644 src/Explorer/Panes/Tables/TableAddEntityPane.html delete mode 100644 src/Explorer/Panes/Tables/TableEditEntityPane.html delete mode 100644 src/Explorer/Panes/Tables/TableEntityPane.ts diff --git a/.eslintignore b/.eslintignore index 430f7bcc3..050bbc0dc 100644 --- a/.eslintignore +++ b/.eslintignore @@ -119,14 +119,10 @@ src/Explorer/Panes/ContextualPaneBase.ts src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts src/Explorer/Panes/GraphStylingPane.ts -# src/Explorer/Panes/NewVertexPane.ts src/Explorer/Panes/PaneComponents.ts src/Explorer/Panes/RenewAdHocAccessPane.ts src/Explorer/Panes/SetupNotebooksPane.ts src/Explorer/Panes/SwitchDirectoryPane.ts -src/Explorer/Panes/Tables/EditTableEntityPane.ts -src/Explorer/Panes/Tables/EntityPropertyViewModel.ts -src/Explorer/Panes/Tables/TableEntityPane.ts src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts diff --git a/src/Explorer/ComponentRegisterer.ts b/src/Explorer/ComponentRegisterer.ts index af9ef47a7..0ec97eb49 100644 --- a/src/Explorer/ComponentRegisterer.ts +++ b/src/Explorer/ComponentRegisterer.ts @@ -22,6 +22,4 @@ ko.components.register("throughput-input-autopilot-v3", ThroughputInputComponent ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent()); ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent()); ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPaneComponent()); -ko.components.register("table-add-entity-pane", new PaneComponents.TableAddEntityPaneComponent()); -ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEntityPaneComponent()); ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent()); diff --git a/src/Explorer/Panes/PaneComponents.ts b/src/Explorer/Panes/PaneComponents.ts index d0a9704b6..9d730887d 100644 --- a/src/Explorer/Panes/PaneComponents.ts +++ b/src/Explorer/Panes/PaneComponents.ts @@ -2,8 +2,6 @@ import AddCollectionPaneTemplate from "./AddCollectionPane.html"; import AddDatabasePaneTemplate from "./AddDatabasePane.html"; import CassandraAddCollectionPaneTemplate from "./CassandraAddCollectionPane.html"; import GraphStylingPaneTemplate from "./GraphStylingPane.html"; -import TableAddEntityPaneTemplate from "./Tables/TableAddEntityPane.html"; -import TableEditEntityPaneTemplate from "./Tables/TableEditEntityPane.html"; export class PaneComponent { constructor(data: any) { @@ -38,23 +36,6 @@ export class GraphStylingPaneComponent { } } -export class TableAddEntityPaneComponent { - constructor() { - return { - viewModel: PaneComponent, - template: TableAddEntityPaneTemplate, - }; - } -} - -export class TableEditEntityPaneComponent { - constructor() { - return { - viewModel: PaneComponent, - template: TableEditEntityPaneTemplate, - }; - } -} export class CassandraAddCollectionPaneComponent { constructor() { return { diff --git a/src/Explorer/Panes/Tables/EditTableEntityPane.ts b/src/Explorer/Panes/Tables/EditTableEntityPane.ts deleted file mode 100644 index 5b69fcd35..000000000 --- a/src/Explorer/Panes/Tables/EditTableEntityPane.ts +++ /dev/null @@ -1,225 +0,0 @@ -import * as ko from "knockout"; -import _ from "underscore"; -import * as ViewModels from "../../../Contracts/ViewModels"; -import { userContext } from "../../../UserContext"; -import Explorer from "../../Explorer"; -import * as TableConstants from "../../Tables/Constants"; -import * as Entities from "../../Tables/Entities"; -import { CassandraAPIDataClient, CassandraTableKey } from "../../Tables/TableDataClient"; -import * as TableEntityProcessor from "../../Tables/TableEntityProcessor"; -import * as Utilities from "../../Tables/Utilities"; -import EntityPropertyViewModel from "./EntityPropertyViewModel"; -import TableEntityPane from "./TableEntityPane"; - -export default class EditTableEntityPane extends TableEntityPane { - container: Explorer; - visible: ko.Observable; - - public originEntity: Entities.ITableEntity; - public originalNumberOfProperties: number; - private originalDocument: any; - - constructor(options: ViewModels.PaneOptions) { - super(options); - this.submitButtonText("Update Entity"); - if (userContext.apiType === "Cassandra") { - this.submitButtonText("Update Row"); - } - this.scrollId = ko.observable("editEntityScroll"); - } - - public submit() { - if (!this.canApply()) { - return; - } - let entity: Entities.ITableEntity = this.updateEntity(this.displayedAttributes()); - this.container.tableDataClient - .updateDocument(this.tableViewModel.queryTablesTab.collection, this.originalDocument, entity) - .then((newEntity: Entities.ITableEntity) => { - var numberOfProperties = 0; - for (var property in newEntity) { - if ( - property !== TableEntityProcessor.keyProperties.attachments && - property !== TableEntityProcessor.keyProperties.etag && - property !== TableEntityProcessor.keyProperties.resourceId && - property !== TableEntityProcessor.keyProperties.self && - (userContext.apiType !== "Cassandra" || property !== TableConstants.EntityKeyNames.RowKey) - ) { - numberOfProperties++; - } - } - - var propertiesDelta = numberOfProperties - this.originalNumberOfProperties; - - return this.tableViewModel - .updateCachedEntity(newEntity) - .then(() => { - if (!this.tryInsertNewHeaders(this.tableViewModel, newEntity)) { - this.tableViewModel.redrawTableThrottled(); - } - }) - .then(() => { - // Selecting updated entity - this.tableViewModel.selected.removeAll(); - this.tableViewModel.selected.push(newEntity); - }); - }); - this.close(); - } - - public open() { - this.displayedAttributes(this.constructDisplayedAttributes(this.originEntity)); - if (userContext.apiType === "Tables") { - this.originalDocument = TableEntityProcessor.convertEntitiesToDocuments( - [this.originEntity], - this.tableViewModel.queryTablesTab.collection - )[0]; // TODO change for Cassandra - this.originalDocument.id = ko.observable(this.originalDocument.id); - } else { - this.originalDocument = this.originEntity; - } - this.updateIsActionEnabled(); - super.open(); - } - - private constructDisplayedAttributes(entity: Entities.ITableEntity): EntityPropertyViewModel[] { - var displayedAttributes: EntityPropertyViewModel[] = []; - const keys = Object.keys(entity); - keys && - keys.forEach((key: string) => { - if ( - key !== TableEntityProcessor.keyProperties.attachments && - key !== TableEntityProcessor.keyProperties.etag && - key !== TableEntityProcessor.keyProperties.resourceId && - key !== TableEntityProcessor.keyProperties.self && - (userContext.apiType !== "Cassandra" || key !== TableConstants.EntityKeyNames.RowKey) - ) { - if (userContext.apiType === "Cassandra") { - const cassandraKeys = this.tableViewModel.queryTablesTab.collection.cassandraKeys.partitionKeys - .concat(this.tableViewModel.queryTablesTab.collection.cassandraKeys.clusteringKeys) - .map((key) => key.property); - var entityAttribute: Entities.ITableEntityAttribute = entity[key]; - var entityAttributeType: string = entityAttribute.$; - var displayValue: any = this.getPropertyDisplayValue(entity, key, entityAttributeType); - var removable: boolean = false; - // TODO figure out validation story for blob and Inet so we can allow adding/editing them - const nonEditableType: boolean = - entityAttributeType === TableConstants.CassandraType.Blob || - entityAttributeType === TableConstants.CassandraType.Inet; - - displayedAttributes.push( - new EntityPropertyViewModel( - this, - key, - entityAttributeType, - displayValue, - /* namePlaceholder */ undefined, - /* valuePlaceholder */ undefined, - false, - /* default valid name */ true, - /* default valid value */ true, - /* isRequired */ false, - removable, - /*value editable*/ !_.contains(cassandraKeys, key) && !nonEditableType - ) - ); - } else { - var entityAttribute: Entities.ITableEntityAttribute = entity[key]; - var entityAttributeType: string = entityAttribute.$; - var displayValue: any = this.getPropertyDisplayValue(entity, key, entityAttributeType); - var editable: boolean = this.isAttributeEditable(key, entityAttributeType); - // As per VSO:189935, Binary properties are read-only, we still want to be able to remove them. - var removable: boolean = editable || entityAttributeType === TableConstants.TableType.Binary; - - displayedAttributes.push( - new EntityPropertyViewModel( - this, - key, - entityAttributeType, - displayValue, - /* namePlaceholder */ undefined, - /* valuePlaceholder */ undefined, - editable, - /* default valid name */ true, - /* default valid value */ true, - /* isRequired */ false, - removable - ) - ); - } - } - }); - if (userContext.apiType === "Cassandra") { - (this.container.tableDataClient) - .getTableSchema(this.tableViewModel.queryTablesTab.collection) - .then((properties: CassandraTableKey[]) => { - properties && - properties.forEach((property) => { - if (!_.contains(keys, property.property)) { - this.insertAttribute(property.property, property.type); - } - }); - }); - } - return displayedAttributes; - } - - private updateEntity(displayedAttributes: EntityPropertyViewModel[]): Entities.ITableEntity { - var updatedEntity: any = {}; - displayedAttributes && - displayedAttributes.forEach((attribute: EntityPropertyViewModel) => { - if (attribute.name() && (userContext.apiType !== "Cassandra" || attribute.value() !== "")) { - var value = attribute.getPropertyValue(); - var type = attribute.type(); - if (type === TableConstants.TableType.Int64) { - value = Utilities.padLongWithZeros(value); - } - updatedEntity[attribute.name()] = { - _: value, - $: type, - }; - } - }); - return updatedEntity; - } - - private isAttributeEditable(attributeName: string, entityAttributeType: string) { - return !( - attributeName === TableConstants.EntityKeyNames.PartitionKey || - attributeName === TableConstants.EntityKeyNames.RowKey || - attributeName === TableConstants.EntityKeyNames.Timestamp || - // As per VSO:189935, Making Binary properties read-only in Edit Entity dialog until we have a full story for it. - entityAttributeType === TableConstants.TableType.Binary - ); - } - - private getPropertyDisplayValue(entity: Entities.ITableEntity, name: string, type: string): any { - var attribute: Entities.ITableEntityAttribute = entity[name]; - var displayValue: any = attribute._; - var isBinary: boolean = type === TableConstants.TableType.Binary; - - // Showing the value in base64 for binary properties since that is what the Azure Storage Client Library expects. - // This means that, even if the Azure Storage API returns a byte[] of binary content, it needs that same array - // *base64 - encoded * as the value for the updated property or the whole update operation will fail. - if (isBinary && displayValue && $.isArray(displayValue.data)) { - var bytes: number[] = displayValue.data; - displayValue = this.getBase64DisplayValue(bytes); - } - - return displayValue; - } - - private getBase64DisplayValue(bytes: number[]): string { - var displayValue: string = null; - - try { - var chars: string[] = bytes.map((byte: number) => String.fromCharCode(byte)); - var toEncode: string = chars.join(""); - displayValue = window.btoa(toEncode); - } catch (error) { - // Error - } - - return displayValue; - } -} diff --git a/src/Explorer/Panes/Tables/EntityPropertyViewModel.ts b/src/Explorer/Panes/Tables/EntityPropertyViewModel.ts deleted file mode 100644 index 9fd007683..000000000 --- a/src/Explorer/Panes/Tables/EntityPropertyViewModel.ts +++ /dev/null @@ -1,164 +0,0 @@ -import * as ko from "knockout"; - -import * as DateTimeUtilities from "../../Tables/QueryBuilder/DateTimeUtilities"; -import * as EntityPropertyNameValidator from "./Validators/EntityPropertyNameValidator"; -import EntityPropertyValueValidator from "./Validators/EntityPropertyValueValidator"; -import * as Constants from "../../Tables/Constants"; -import * as Utilities from "../../Tables/Utilities"; -import TableEntityPane from "./TableEntityPane"; - -export interface IValidationResult { - isInvalid: boolean; - help: string; -} - -export interface IActionEnabledDialog { - updateIsActionEnabled: () => void; -} - -/** - * View model for an entity proprety - */ -export default class EntityPropertyViewModel { - /* Constants */ - public static noTooltip = ""; - // Maximum number of custom properties, see Azure Service Data Model - // At https://msdn.microsoft.com/library/azure/dd179338.aspx - public static maximumNumberOfProperties = 252; - - // Labels - public closeButtonLabel: string = "Close"; // localize - - /* Observables */ - public name: ko.Observable; - public type: ko.Observable; - public value: ko.Observable; - public inputType: ko.Computed; - - public nameTooltip: ko.Observable; - public isInvalidName: ko.Observable; - - public valueTooltip: ko.Observable; - public isInvalidValue: ko.Observable; - - public namePlaceholder: ko.Observable; - public valuePlaceholder: ko.Observable; - - public hasFocus: ko.Observable; - public valueHasFocus: ko.Observable; - public isDateType: ko.Computed; - - public editable: boolean; // If a property's name or type is editable, these two are always the same regarding editability. - public valueEditable: boolean; // If a property's value is editable, could be different from name or type. - public removable: boolean; // If a property is removable, usually, PartitionKey, RowKey and TimeStamp (if applicable) are not removable. - public isRequired: boolean; // If a property's value is required, used to differentiate the place holder label. - public ignoreEmptyValue: boolean; - - /* Members */ - private tableEntityPane: TableEntityPane; - private _validator: EntityPropertyValueValidator; - - constructor( - tableEntityPane: TableEntityPane, - name: string, - type: string, - value: any, - namePlaceholder: string = "", - valuePlaceholder: string = "", - editable: boolean = false, - defaultValidName: boolean = true, - defaultValidValue: boolean = false, - isRequired: boolean = false, - removable: boolean = editable, - valueEditable: boolean = editable, - ignoreEmptyValue: boolean = false - ) { - this.name = ko.observable(name); - this.type = ko.observable(type); - this.isDateType = ko.pureComputed(() => this.type() === Constants.TableType.DateTime); - if (this.isDateType()) { - value = value ? DateTimeUtilities.getLocalDateTime(value) : value; - } - this.value = ko.observable(value); - this.inputType = ko.pureComputed(() => { - if (!this.valueHasFocus() && !this.value() && this.isDateType()) { - return Constants.InputType.Text; - } - return Utilities.getInputTypeFromDisplayedName(this.type()); - }); - - this.namePlaceholder = ko.observable(namePlaceholder); - this.valuePlaceholder = ko.observable(valuePlaceholder); - - this.editable = editable; - this.isRequired = isRequired; - this.removable = removable; - this.valueEditable = valueEditable; - - this._validator = new EntityPropertyValueValidator(isRequired); - - this.tableEntityPane = tableEntityPane; - - this.nameTooltip = ko.observable(EntityPropertyViewModel.noTooltip); - this.isInvalidName = ko.observable(!defaultValidName); - this.name.subscribe((name: string) => this.validateName(name)); - if (!defaultValidName) { - this.validateName(name); - } - - this.valueTooltip = ko.observable(EntityPropertyViewModel.noTooltip); - this.isInvalidValue = ko.observable(!defaultValidValue); - this.value.subscribe((value: string) => this.validateValue(value, this.type())); - if (!defaultValidValue) { - this.validateValue(value, type); - } - - this.type.subscribe((type: string) => this.validateValue(this.value(), type)); - - this.hasFocus = ko.observable(false); - this.valueHasFocus = ko.observable(false); - } - - /** - * Gets the Javascript value of the entity property based on its EDM type. - */ - public getPropertyValue(): any { - var value: string = this.value(); - if (this.type() === Constants.TableType.DateTime) { - value = DateTimeUtilities.getUTCDateTime(value); - } - return this._validator.parseValue(value, this.type()); - } - - private validateName(name: string): void { - var result: IValidationResult = this.isInvalidNameInput(name); - - this.isInvalidName(result.isInvalid); - this.nameTooltip(result.help); - this.namePlaceholder(result.help); - this.tableEntityPane.updateIsActionEnabled(); - } - - private validateValue(value: string, type: string): void { - var result: IValidationResult = this.isInvalidValueInput(value, type); - if (!result) { - return; - } - - this.isInvalidValue(result.isInvalid); - this.valueTooltip(result.help); - this.valuePlaceholder(result.help); - this.tableEntityPane.updateIsActionEnabled(); - } - - private isInvalidNameInput(name: string): IValidationResult { - return EntityPropertyNameValidator.validate(name); - } - - private isInvalidValueInput(value: string, type: string): IValidationResult { - if (this.ignoreEmptyValue && this.value() === "") { - return { isInvalid: false, help: "" }; - } - return this._validator.validate(value, type); - } -} diff --git a/src/Explorer/Panes/Tables/TableAddEntityPane.html b/src/Explorer/Panes/Tables/TableAddEntityPane.html deleted file mode 100644 index cf8a6cf98..000000000 --- a/src/Explorer/Panes/Tables/TableAddEntityPane.html +++ /dev/null @@ -1,190 +0,0 @@ -
-
-
- -
-
- -
- -
- Close -
-
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
- -
- -
- - -
- -
- -
- - Edit - - - Cancel - -
-
-
-
-
-
- - Insert attribute - - -
-
-
-
-
-
-
- -
-
-
-
- - - - -
-
diff --git a/src/Explorer/Panes/Tables/TableEditEntityPane.html b/src/Explorer/Panes/Tables/TableEditEntityPane.html deleted file mode 100644 index 44cbc6c9a..000000000 --- a/src/Explorer/Panes/Tables/TableEditEntityPane.html +++ /dev/null @@ -1,187 +0,0 @@ -
-
-
- -
-
- -
- -
- Close -
-
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
- -
- -
- - -
- -
- -
- - Edit attribute - - - Remove attribute - -
-
-
-
-
-
- - Add attribute - - -
-
-
-
-
-
-
- -
-
-
-
- - - - -
-
diff --git a/src/Explorer/Panes/Tables/TableEntityPane.ts b/src/Explorer/Panes/Tables/TableEntityPane.ts deleted file mode 100644 index 23eafff11..000000000 --- a/src/Explorer/Panes/Tables/TableEntityPane.ts +++ /dev/null @@ -1,279 +0,0 @@ -import * as ko from "knockout"; -import _ from "underscore"; -import { KeyCodes } from "../../../Common/Constants"; -import * as ViewModels from "../../../Contracts/ViewModels"; -import { userContext } from "../../../UserContext"; -import * as TableConstants from "../../Tables/Constants"; -import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities"; -import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel"; -import * as Entities from "../../Tables/Entities"; -import * as TableEntityProcessor from "../../Tables/TableEntityProcessor"; -import * as Utilities from "../../Tables/Utilities"; -import { ContextualPaneBase } from "../ContextualPaneBase"; -import EntityPropertyViewModel from "./EntityPropertyViewModel"; - -// Class with variables and functions that are common to both adding and editing entities -export default abstract class TableEntityPane extends ContextualPaneBase { - protected static requiredFieldsForTablesAPI: string[] = [ - TableConstants.EntityKeyNames.PartitionKey, - TableConstants.EntityKeyNames.RowKey, - ]; - - /* Labels */ - public attributeNameLabel = "Property Name"; // localize - public dataTypeLabel = "Type"; // localize - public attributeValueLabel = "Value"; // localize - - /* Controls */ - public removeButtonLabel = "Remove"; // localize - public editButtonLabel = "Edit"; // localize - public addButtonLabel = "Add Property"; // localize - - public edmTypes: ko.ObservableArray = ko.observableArray([ - TableConstants.TableType.String, - TableConstants.TableType.Boolean, - TableConstants.TableType.Binary, - TableConstants.TableType.DateTime, - TableConstants.TableType.Double, - TableConstants.TableType.Guid, - TableConstants.TableType.Int32, - TableConstants.TableType.Int64, - ]); - - public canAdd: ko.Computed; - public canApply: ko.Observable; - public displayedAttributes = ko.observableArray(); - public editingProperty = ko.observable(); - public isEditing = ko.observable(false); - public submitButtonText = ko.observable(); - - public tableViewModel: TableEntityListViewModel; - - protected scrollId: ko.Observable; - - constructor(options: ViewModels.PaneOptions) { - super(options); - if (userContext.apiType === "Cassandra") { - this.edmTypes([ - TableConstants.CassandraType.Text, - TableConstants.CassandraType.Ascii, - TableConstants.CassandraType.Bigint, - TableConstants.CassandraType.Blob, - TableConstants.CassandraType.Boolean, - TableConstants.CassandraType.Decimal, - TableConstants.CassandraType.Double, - TableConstants.CassandraType.Float, - TableConstants.CassandraType.Int, - TableConstants.CassandraType.Uuid, - TableConstants.CassandraType.Varchar, - TableConstants.CassandraType.Varint, - TableConstants.CassandraType.Inet, - TableConstants.CassandraType.Smallint, - TableConstants.CassandraType.Tinyint, - ]); - } - - this.canAdd = ko.computed(() => { - // Cassandra can't add since the schema can't be changed once created - if (userContext.apiType === "Cassandra") { - return false; - } - // Adding '2' to the maximum to take into account PartitionKey and RowKey - return this.displayedAttributes().length < EntityPropertyViewModel.maximumNumberOfProperties + 2; - }); - this.canApply = ko.observable(true); - this.editingProperty(this.displayedAttributes()[0]); - } - - public removeAttribute = (index: number, data: any): void => { - this.displayedAttributes.splice(index, 1); - this.updateIsActionEnabled(); - document.getElementById("addProperty").focus(); - }; - - public editAttribute = (index: number, data: EntityPropertyViewModel): void => { - this.editingProperty(data); - this.isEditing(true); - document.getElementById("textAreaEditProperty").focus(); - }; - - public finishEditingAttribute = (): void => { - this.isEditing(false); - this.editingProperty(null); - }; - - public onKeyUp = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = Utilities.onEsc(event, ($sourceElement: JQuery) => { - this.finishEditingAttribute(); - }); - - return !handled; - }; - - public onAddPropertyKeyDown = (source: any, event: KeyboardEvent): boolean => { - if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { - this.insertAttribute(); - event.stopPropagation(); - return false; - } - - return true; - }; - - public onEditPropertyKeyDown = ( - index: number, - data: EntityPropertyViewModel, - event: KeyboardEvent, - source: any - ): boolean => { - if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { - this.editAttribute(index, data); - event.stopPropagation(); - return false; - } - - return true; - }; - - public onDeletePropertyKeyDown = ( - index: number, - data: EntityPropertyViewModel, - event: KeyboardEvent, - source: any - ): boolean => { - if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { - this.removeAttribute(index, data); - event.stopPropagation(); - return false; - } - - return true; - }; - - public onBackButtonKeyDown = (source: any, event: KeyboardEvent): boolean => { - if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { - this.finishEditingAttribute(); - event.stopPropagation(); - return false; - } - - return true; - }; - - public insertAttribute = (name?: string, type?: string): void => { - let entityProperty: EntityPropertyViewModel; - if (!!name && !!type && userContext.apiType === "Cassandra") { - // TODO figure out validation story for blob and Inet so we can allow adding/editing them - const nonEditableType: boolean = - type === TableConstants.CassandraType.Blob || type === TableConstants.CassandraType.Inet; - entityProperty = new EntityPropertyViewModel( - this, - name, - type, - "", // default to empty string - /* namePlaceholder */ undefined, - /* valuePlaceholder */ undefined, - /* editable */ false, - /* default valid name */ false, - /* default valid value */ true, - /* isRequired */ false, - /* removable */ false, - /*value editable*/ !nonEditableType - ); - } else { - entityProperty = new EntityPropertyViewModel( - this, - "", - this.edmTypes()[0], // default to the first Edm type: 'string' - "", // default to empty string - /* namePlaceholder */ undefined, - /* valuePlaceholder */ undefined, - /* editable */ true, - /* default valid name */ false, - /* default valid value */ true - ); - } - - this.displayedAttributes.push(entityProperty); - this.updateIsActionEnabled(); - this.scrollToBottom(); - - entityProperty.hasFocus(true); - }; - - public updateIsActionEnabled(needRequiredFields: boolean = true): void { - var properties: EntityPropertyViewModel[] = this.displayedAttributes() || []; - var disable: boolean = _.some(properties, (property: EntityPropertyViewModel) => { - return property.isInvalidName() || property.isInvalidValue(); - }); - - this.canApply(!disable); - } - - protected entityFromAttributes(displayedAttributes: EntityPropertyViewModel[]): Entities.ITableEntity { - var entity: any = {}; - - displayedAttributes && - displayedAttributes.forEach((attribute: EntityPropertyViewModel) => { - if (attribute.name() && (attribute.value() !== "" || attribute.isRequired)) { - var value = attribute.getPropertyValue(); - var type = attribute.type(); - if (type === TableConstants.TableType.Int64) { - value = Utilities.padLongWithZeros(value); - } - entity[attribute.name()] = { - _: value, - $: type, - }; - } - }); - - return entity; - } - - // Removing Binary from Add Entity dialog until we have a full story for it. - protected setOptionDisable(option: Node, value: string): void { - ko.applyBindingsToNode(option, { disable: value === TableConstants.TableType.Binary }, value); - } - - /** - * Parse the updated entity to see if there are any new attributes that old headers don't have. - * In this case, add these attributes names as new headers. - * Remarks: adding new headers will automatically trigger table redraw. - */ - protected tryInsertNewHeaders(viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean { - var newHeaders: string[] = []; - const keys = Object.keys(newEntity); - keys && - keys.forEach((key: string) => { - if ( - !_.contains(viewModel.headers, key) && - key !== TableEntityProcessor.keyProperties.attachments && - key !== TableEntityProcessor.keyProperties.etag && - key !== TableEntityProcessor.keyProperties.resourceId && - key !== TableEntityProcessor.keyProperties.self && - (userContext.apiType !== "Cassandra" || key !== TableConstants.EntityKeyNames.RowKey) - ) { - newHeaders.push(key); - } - }); - - var newHeadersInserted: boolean = false; - if (newHeaders.length) { - if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) { - newHeaders = viewModel.headers.concat(newHeaders); - } - viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false); - newHeadersInserted = true; - } - return newHeadersInserted; - } - - protected scrollToBottom(): void { - var scrollBox = document.getElementById(this.scrollId()); - var isScrolledToBottom = scrollBox.scrollHeight - scrollBox.clientHeight <= scrollBox.scrollHeight + 1; - if (isScrolledToBottom) { - scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight; - } - } -} From 78eafe1aec9d312ee53c554936527ab78752b178 Mon Sep 17 00:00:00 2001 From: Jordi Bunster Date: Thu, 6 May 2021 17:20:25 -0700 Subject: [PATCH 4/5] Remove NotebookViewerTab (#749) [Preview this branch](https://cosmos-explorer-preview.azurewebsites.net/pull/749) --- src/Explorer/Explorer.tsx | 36 +----------- src/Explorer/Tabs/NotebookViewerTab.tsx | 73 ------------------------- 2 files changed, 1 insertion(+), 108 deletions(-) delete mode 100644 src/Explorer/Tabs/NotebookViewerTab.tsx diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 47af1ae40..223ab657c 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -1,6 +1,5 @@ -import * as ko from "knockout"; import { IChoiceGroupProps } from "@fluentui/react"; -import * as path from "path"; +import * as ko from "knockout"; import Q from "q"; import React from "react"; import _ from "underscore"; @@ -1843,39 +1842,6 @@ export default class Explorer { } } - public async openNotebookViewer(notebookUrl: string) { - const title = path.basename(notebookUrl); - const hashLocation = notebookUrl; - const NotebookViewerTab = await ( - await import(/* webpackChunkName: "NotebookViewerTab" */ "./Tabs/NotebookViewerTab") - ).default; - - const notebookViewerTab = this.tabsManager.getTabs(ViewModels.CollectionTabKind.NotebookV2).find((tab) => { - return tab.hashLocation() == hashLocation && tab instanceof NotebookViewerTab && tab.notebookUrl === notebookUrl; - }); - - if (notebookViewerTab) { - this.tabsManager.activateNewTab(notebookViewerTab); - } else { - const notebookViewerTab = new NotebookViewerTab({ - account: userContext.databaseAccount, - tabKind: ViewModels.CollectionTabKind.NotebookViewer, - node: null, - title: title, - tabPath: title, - collection: null, - hashLocation: hashLocation, - isTabsContentExpanded: ko.observable(true), - onLoadStartKey: null, - onUpdateTabsButtons: this.onUpdateTabsButtons, - container: this, - notebookUrl, - }); - - this.tabsManager.activateNewTab(notebookViewerTab); - } - } - public onNewCollectionClicked(databaseId?: string): void { if (userContext.apiType === "Cassandra") { this.cassandraAddCollectionPane.open(); diff --git a/src/Explorer/Tabs/NotebookViewerTab.tsx b/src/Explorer/Tabs/NotebookViewerTab.tsx deleted file mode 100644 index 677ca21a8..000000000 --- a/src/Explorer/Tabs/NotebookViewerTab.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as ko from "knockout"; -import * as React from "react"; -import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; -import { DatabaseAccount } from "../../Contracts/DataModels"; -import * as ViewModels from "../../Contracts/ViewModels"; -import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; -import { - NotebookViewerComponent, - NotebookViewerComponentProps, -} from "../Controls/NotebookViewer/NotebookViewerComponent"; -import Explorer from "../Explorer"; -import TabsBase from "./TabsBase"; - -interface NotebookViewerTabOptions extends ViewModels.TabOptions { - account: DatabaseAccount; - container: Explorer; - notebookUrl: string; -} - -/** - * Notebook Viewer tab - */ -class NotebookViewerComponentAdapter implements ReactAdapter { - // parameters: true: show, false: hide - public parameters: ko.Computed; - constructor(private notebookUrl: string) {} - - public renderComponent(): JSX.Element { - const props: NotebookViewerComponentProps = { - notebookUrl: this.notebookUrl, - backNavigationText: undefined, - onBackClick: undefined, - onTagClick: undefined, - }; - - return this.parameters() ? : <>; - } -} - -export default class NotebookViewerTab extends TabsBase { - public readonly html = '
'; - private container: Explorer; - public notebookUrl: string; - - public notebookViewerComponentAdapter: NotebookViewerComponentAdapter; - - constructor(options: NotebookViewerTabOptions) { - super(options); - this.container = options.container; - this.notebookUrl = options.notebookUrl; - - this.notebookViewerComponentAdapter = new NotebookViewerComponentAdapter(options.notebookUrl); - - this.notebookViewerComponentAdapter.parameters = ko.computed(() => { - if (this.isTemplateReady() && this.container.isNotebookEnabled()) { - return true; - } - return false; - }); - } - - public getContainer(): Explorer { - return this.container; - } - - protected getTabsButtons(): CommandButtonComponentProps[] { - return []; - } - - protected buildCommandBarOptions(): void { - this.updateNavbarWithTabsButtons(); - } -} From d62baf327b6f60ebc13dbe7ccee1905201c857c4 Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Thu, 6 May 2021 19:27:47 -0700 Subject: [PATCH 5/5] Change create wildcard index default value to false for mongo 3.2 (#759) * Change create wildcard index default value to false for mongo 3.2 * Update snapshots --- .../__snapshots__/SettingsComponent.test.tsx.snap | 8 ++++++++ src/Explorer/Panes/AddCollectionPane.html | 2 +- src/Explorer/Panes/AddCollectionPane.ts | 4 ++++ src/Explorer/Panes/AddCollectionPanel.tsx | 5 +++-- .../__snapshots__/GitHubReposPanel.test.tsx.snap | 2 ++ .../__snapshots__/StringInputPane.test.tsx.snap | 2 ++ .../DeleteDatabaseConfirmationPanel.test.tsx.snap | 2 ++ src/Utils/CapabilityUtils.ts | 4 ++++ 8 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/Utils/CapabilityUtils.ts diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap index 63d6712b8..671725d4f 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap @@ -103,6 +103,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -253,6 +254,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -1379,6 +1381,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -1529,6 +1532,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -2668,6 +2672,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -2818,6 +2823,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -3944,6 +3950,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -4094,6 +4101,7 @@ exports[`SettingsComponent renders 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], diff --git a/src/Explorer/Panes/AddCollectionPane.html b/src/Explorer/Panes/AddCollectionPane.html index 4bba48d36..2d0cfe8ba 100644 --- a/src/Explorer/Panes/AddCollectionPane.html +++ b/src/Explorer/Panes/AddCollectionPane.html @@ -438,7 +438,7 @@ -
+

Indexing

diff --git a/src/Explorer/Panes/AddCollectionPane.ts b/src/Explorer/Panes/AddCollectionPane.ts index c626f151a..17aef98fa 100644 --- a/src/Explorer/Panes/AddCollectionPane.ts +++ b/src/Explorer/Panes/AddCollectionPane.ts @@ -14,6 +14,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import { userContext } from "../../UserContext"; import * as AutoPilotUtils from "../../Utils/AutoPilotUtils"; +import { isCapabilityEnabled } from "../../Utils/CapabilityUtils"; import * as PricingUtils from "../../Utils/PricingUtils"; import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent"; import { ContextualPaneBase } from "./ContextualPaneBase"; @@ -95,6 +96,7 @@ export default class AddCollectionPane extends ContextualPaneBase { public shouldCreateMongoWildcardIndex: ko.Observable; private _isSynapseLinkEnabled: ko.Computed; + private isEnableMongoCapabilityEnabled: ko.Observable; constructor(options: AddCollectionPaneOptions) { super(options); @@ -634,6 +636,8 @@ export default class AddCollectionPane extends ContextualPaneBase { }); }); + this.isEnableMongoCapabilityEnabled = ko.observable(isCapabilityEnabled("EnableMongo")); + this.shouldCreateMongoWildcardIndex = ko.observable(this.container.isMongoIndexingEnabled()); } diff --git a/src/Explorer/Panes/AddCollectionPanel.tsx b/src/Explorer/Panes/AddCollectionPanel.tsx index 89eae59fb..89cf46d6c 100644 --- a/src/Explorer/Panes/AddCollectionPanel.tsx +++ b/src/Explorer/Panes/AddCollectionPanel.tsx @@ -25,6 +25,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import { userContext } from "../../UserContext"; import { getCollectionName } from "../../Utils/APITypeUtils"; +import { isCapabilityEnabled } from "../../Utils/CapabilityUtils"; import { getUpsellMessage } from "../../Utils/PricingUtils"; import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent"; import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput"; @@ -80,7 +81,7 @@ export class AddCollectionPanel extends React.Component - {userContext.databaseAccount.properties?.capabilities?.find((c) => c.name === "EnableMongo") && ( + {isCapabilityEnabled("EnableMongo") && ( diff --git a/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap b/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap index 233653711..21eb5eaac 100644 --- a/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap +++ b/src/Explorer/Panes/GitHubReposPanel/__snapshots__/GitHubReposPanel.test.tsx.snap @@ -92,6 +92,7 @@ exports[`GitHub Repos Panel should render Default properly 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -242,6 +243,7 @@ exports[`GitHub Repos Panel should render Default properly 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], diff --git a/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap b/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap index 7cbfacdd1..54de722ba 100644 --- a/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap +++ b/src/Explorer/Panes/StringInputPane/__snapshots__/StringInputPane.test.tsx.snap @@ -82,6 +82,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -232,6 +233,7 @@ exports[`StringInput Pane should render Create new directory properly 1`] = ` "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], diff --git a/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap b/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap index 3ec737551..0084a4cd7 100644 --- a/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap +++ b/src/Explorer/Panes/__snapshots__/DeleteDatabaseConfirmationPanel.test.tsx.snap @@ -80,6 +80,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], @@ -230,6 +231,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database "id": "addcollectionpane", "isAnalyticalStorageOn": [Function], "isAutoPilotSelected": [Function], + "isEnableMongoCapabilityEnabled": [Function], "isExecuting": [Function], "isFixedStorageSelected": [Function], "isFreeTierAccount": [Function], diff --git a/src/Utils/CapabilityUtils.ts b/src/Utils/CapabilityUtils.ts new file mode 100644 index 000000000..8e04e044c --- /dev/null +++ b/src/Utils/CapabilityUtils.ts @@ -0,0 +1,4 @@ +import { userContext } from "../UserContext"; + +export const isCapabilityEnabled = (capabilityName: string): boolean => + userContext.databaseAccount?.properties?.capabilities?.some((capability) => capability.name === capabilityName);