Refactor code that uses the _rid and _self of a database or collection (#267)

This commit is contained in:
victor-meng 2020-10-13 13:29:39 -07:00 committed by GitHub
parent cfb9a0b321
commit d525afa142
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 159 additions and 226 deletions

View File

@ -85,7 +85,7 @@ export interface Database extends TreeNode {
collapseDatabase(): void; collapseDatabase(): void;
loadCollections(): Promise<void>; loadCollections(): Promise<void>;
findCollectionWithId(collectionRid: string): Collection; findCollectionWithId(collectionId: string): Collection;
openAddCollection(database: Database, event: MouseEvent): void; openAddCollection(database: Database, event: MouseEvent): void;
onDeleteDatabaseContextMenuClick(source: Database, event: MouseEvent | KeyboardEvent): void; onDeleteDatabaseContextMenuClick(source: Database, event: MouseEvent | KeyboardEvent): void;
onSettingsClick: () => void; onSettingsClick: () => void;
@ -266,7 +266,6 @@ export interface TabOptions {
tabKind: CollectionTabKind; tabKind: CollectionTabKind;
title: string; title: string;
tabPath: string; tabPath: string;
selfLink: string;
isActive: ko.Observable<boolean>; isActive: ko.Observable<boolean>;
hashLocation: string; hashLocation: string;
onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void; onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void;
@ -305,7 +304,6 @@ export interface QueryTabOptions extends TabOptions {
export interface ScriptTabOption extends TabOptions { export interface ScriptTabOption extends TabOptions {
resource: any; resource: any;
isNew: boolean; isNew: boolean;
collectionSelfLink?: string;
partitionKey?: DataModels.PartitionKey; partitionKey?: DataModels.PartitionKey;
} }

View File

@ -33,7 +33,6 @@ describe("SettingsComponent", () => {
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
node: undefined, node: undefined,
selfLink: undefined,
hashLocation: "settings", hashLocation: "settings",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: undefined onUpdateTabsButtons: undefined

View File

@ -1861,7 +1861,7 @@ export default class Explorer {
return null; return null;
} }
if (this.selectedNode().nodeKind === "Database") { if (this.selectedNode().nodeKind === "Database") {
return _.find(this.databases(), (database: ViewModels.Database) => database.rid === this.selectedNode().rid); return _.find(this.databases(), (database: ViewModels.Database) => database.id() === this.selectedNode().id());
} }
return this.findSelectedCollection().database; return this.findSelectedCollection().database;
} }
@ -1957,11 +1957,9 @@ export default class Explorer {
} }
public findSelectedCollection(): ViewModels.Collection { public findSelectedCollection(): ViewModels.Collection {
if (this.selectedNode().nodeKind === "Collection") { return (this.selectedNode().nodeKind === "Collection"
return this.findSelectedCollectionForSelectedNode(); ? this.selectedNode()
} else { : this.selectedNode().collection) as ViewModels.Collection;
return this.findSelectedCollectionForSubNode();
}
} }
// TODO: Refactor below methods, minimize dependencies and add unit tests where necessary // TODO: Refactor below methods, minimize dependencies and add unit tests where necessary
@ -2078,11 +2076,11 @@ export default class Explorer {
}); });
databasesToLoad.forEach(async (database: ViewModels.Database) => { databasesToLoad.forEach(async (database: ViewModels.Database) => {
await database.loadCollections(); await database.loadCollections();
const isNewDatabase: boolean = _.some(newDatabases, (db: ViewModels.Database) => db.rid === database.rid); const isNewDatabase: boolean = _.some(newDatabases, (db: ViewModels.Database) => db.id() === database.id());
if (isNewDatabase) { if (isNewDatabase) {
database.expandDatabase(); database.expandDatabase();
} }
this.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.getDatabase().rid === database.rid); this.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.getDatabase().id() === database.id());
}); });
Q.all(loadCollectionPromises).done( Q.all(loadCollectionPromises).done(
@ -2194,21 +2192,11 @@ export default class Explorer {
} }
} }
private findSelectedCollectionForSelectedNode(): ViewModels.Collection { public findCollection(databaseId: string, collectionId: string): ViewModels.Collection {
return this.findCollection(this.selectedNode().rid); const database: ViewModels.Database = this.databases().find(
} (database: ViewModels.Database) => database.id() === databaseId
);
public findCollection(rid: string): ViewModels.Collection { return database?.collections().find((collection: ViewModels.Collection) => collection.id() === collectionId);
for (let i = 0; i < this.databases().length; i++) {
const database = this.databases()[i];
for (let j = 0; j < database.collections().length; j++) {
const collection = database.collections()[j];
if (collection.rid === rid) {
return collection;
}
}
}
return null;
} }
public isLastCollection(): boolean { public isLastCollection(): boolean {
@ -2232,7 +2220,7 @@ export default class Explorer {
const newDatabases: DataModels.Database[] = _.filter(updatedDatabaseList, (database: DataModels.Database) => { const newDatabases: DataModels.Database[] = _.filter(updatedDatabaseList, (database: DataModels.Database) => {
const databaseExists = _.some( const databaseExists = _.some(
this.databases(), this.databases(),
(existingDatabase: ViewModels.Database) => existingDatabase.rid === database._rid (existingDatabase: ViewModels.Database) => existingDatabase.id() === database.id
); );
return !databaseExists; return !databaseExists;
}); });
@ -2244,7 +2232,7 @@ export default class Explorer {
ko.utils.arrayForEach(this.databases(), (database: ViewModels.Database) => { ko.utils.arrayForEach(this.databases(), (database: ViewModels.Database) => {
const databasePresentInUpdatedList = _.some( const databasePresentInUpdatedList = _.some(
updatedDatabaseList, updatedDatabaseList,
(db: DataModels.Database) => db._rid === database.rid (db: DataModels.Database) => db.id === database.id()
); );
if (!databasePresentInUpdatedList) { if (!databasePresentInUpdatedList) {
databasesToDelete.push(database); databasesToDelete.push(database);
@ -2266,7 +2254,7 @@ export default class Explorer {
const databasesToKeep: ViewModels.Database[] = []; const databasesToKeep: ViewModels.Database[] = [];
ko.utils.arrayForEach(this.databases(), (database: ViewModels.Database) => { ko.utils.arrayForEach(this.databases(), (database: ViewModels.Database) => {
const shouldRemoveDatabase = _.some(databasesToRemove, (db: ViewModels.Database) => db.rid === database.rid); const shouldRemoveDatabase = _.some(databasesToRemove, (db: ViewModels.Database) => db.id === database.id);
if (!shouldRemoveDatabase) { if (!shouldRemoveDatabase) {
databasesToKeep.push(database); databasesToKeep.push(database);
} }
@ -2275,19 +2263,6 @@ export default class Explorer {
this.databases(databasesToKeep); this.databases(databasesToKeep);
} }
private findSelectedCollectionForSubNode(): ViewModels.Collection {
for (let i = 0; i < this.databases().length; i++) {
const database = this.databases()[i];
for (let j = 0; j < database.collections().length; j++) {
const collection = database.collections()[j];
if (this.selectedNode().collection && collection.rid === this.selectedNode().collection.rid) {
return collection;
}
}
}
return null;
}
public uploadFile(name: string, content: string, parent: NotebookContentItem): Promise<NotebookContentItem> { public uploadFile(name: string, content: string, parent: NotebookContentItem): Promise<NotebookContentItem> {
if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) { if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) {
const error = "Attempt to upload notebook, but notebook is not enabled"; const error = "Attempt to upload notebook, but notebook is not enabled";
@ -2447,7 +2422,6 @@ export default class Explorer {
title: notebookContentItem.name, title: notebookContentItem.name,
tabPath: notebookContentItem.path, tabPath: notebookContentItem.path,
collection: null, collection: null,
selfLink: null,
masterKey: userContext.masterKey || "", masterKey: userContext.masterKey || "",
hashLocation: "notebooks", hashLocation: "notebooks",
isActive: ko.observable(false), isActive: ko.observable(false),
@ -2899,7 +2873,6 @@ export default class Explorer {
title: title, title: title,
tabPath: title, tabPath: title,
collection: null, collection: null,
selfLink: null,
hashLocation: hashLocation, hashLocation: hashLocation,
isActive: ko.observable(false), isActive: ko.observable(false),
isTabsContentExpanded: ko.observable(true), isTabsContentExpanded: ko.observable(true),
@ -2943,7 +2916,6 @@ export default class Explorer {
title: title, title: title,
tabPath: title, tabPath: title,
documentClientUtility: null, documentClientUtility: null,
selfLink: null,
isActive: ko.observable(false), isActive: ko.observable(false),
hashLocation: hashLocation, hashLocation: hashLocation,
onUpdateTabsButtons: this.onUpdateTabsButtons, onUpdateTabsButtons: this.onUpdateTabsButtons,
@ -2986,7 +2958,6 @@ export default class Explorer {
tabPath: title, tabPath: title,
documentClientUtility: null, documentClientUtility: null,
collection: null, collection: null,
selfLink: null,
hashLocation: hashLocation, hashLocation: hashLocation,
isActive: ko.observable(false), isActive: ko.observable(false),
isTabsContentExpanded: ko.observable(true), isTabsContentExpanded: ko.observable(true),

View File

@ -141,8 +141,6 @@ describe("getPkIdFromDocumentId", () => {
}); });
describe("GraphExplorer", () => { describe("GraphExplorer", () => {
const COLLECTION_RID = "collectionRid";
const COLLECTION_SELF_LINK = "collectionSelfLink";
const gremlinRU = 789.12; const gremlinRU = 789.12;
const createMockProps = (): GraphExplorerProps => { const createMockProps = (): GraphExplorerProps => {
@ -160,8 +158,6 @@ describe("GraphExplorer", () => {
onIsValidQueryChange: (isValidQuery: boolean): void => {}, onIsValidQueryChange: (isValidQuery: boolean): void => {},
collectionPartitionKeyProperty: "collectionPartitionKeyProperty", collectionPartitionKeyProperty: "collectionPartitionKeyProperty",
collectionRid: COLLECTION_RID,
collectionSelfLink: COLLECTION_SELF_LINK,
graphBackendEndpoint: "graphBackendEndpoint", graphBackendEndpoint: "graphBackendEndpoint",
databaseId: "databaseId", databaseId: "databaseId",
collectionId: "collectionId", collectionId: "collectionId",

View File

@ -47,8 +47,6 @@ export interface GraphExplorerProps {
onIsValidQueryChange: (isValidQuery: boolean) => void; onIsValidQueryChange: (isValidQuery: boolean) => void;
collectionPartitionKeyProperty: string; collectionPartitionKeyProperty: string;
collectionRid: string;
collectionSelfLink: string;
graphBackendEndpoint: string; graphBackendEndpoint: string;
databaseId: string; databaseId: string;
collectionId: string; collectionId: string;
@ -1761,7 +1759,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${queryInfoStr}`); const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${queryInfoStr}`);
return queryDocumentsPage( return queryDocumentsPage(
this.props.collectionRid, this.props.collectionId,
this.currentDocDBQueryInfo.iterator, this.currentDocDBQueryInfo.iterator,
this.currentDocDBQueryInfo.index, this.currentDocDBQueryInfo.index,
{ {

View File

@ -17,8 +17,6 @@ interface Parameter {
graphConfig?: GraphConfig; graphConfig?: GraphConfig;
collectionPartitionKeyProperty: string; collectionPartitionKeyProperty: string;
collectionRid: string;
collectionSelfLink: string;
graphBackendEndpoint: string; graphBackendEndpoint: string;
databaseId: string; databaseId: string;
collectionId: string; collectionId: string;
@ -49,8 +47,6 @@ export class GraphExplorerAdapter implements ReactAdapter {
onIsGraphDisplayed={this.params.onIsGraphDisplayed} onIsGraphDisplayed={this.params.onIsGraphDisplayed}
onResetDefaultGraphConfigValues={this.params.onResetDefaultGraphConfigValues} onResetDefaultGraphConfigValues={this.params.onResetDefaultGraphConfigValues}
collectionPartitionKeyProperty={this.params.collectionPartitionKeyProperty} collectionPartitionKeyProperty={this.params.collectionPartitionKeyProperty}
collectionRid={this.params.collectionRid}
collectionSelfLink={this.params.collectionSelfLink}
graphBackendEndpoint={this.params.graphBackendEndpoint} graphBackendEndpoint={this.params.graphBackendEndpoint}
databaseId={this.params.databaseId} databaseId={this.params.databaseId}
collectionId={this.params.collectionId} collectionId={this.params.collectionId}

View File

@ -15,7 +15,10 @@ export interface OpenNotebookItem {
path: string; path: string;
} }
export type OpenCollectionItem = string; export interface OpenCollectionItem {
databaseId: string;
collectionId: string;
}
export interface Item { export interface Item {
type: Type; type: Type;
@ -121,7 +124,11 @@ export class MostRecentActivity {
public onItemClicked(item: Item) { public onItemClicked(item: Item) {
switch (item.type) { switch (item.type) {
case Type.OpenCollection: { case Type.OpenCollection: {
const collection = this.container.findCollection(item.data as OpenCollectionItem); const openCollectionitem = item.data as OpenCollectionItem;
const collection = this.container.findCollection(
openCollectionitem.databaseId,
openCollectionitem.collectionId
);
if (collection) { if (collection) {
collection.openTab(); collection.openTab();
} }

View File

@ -66,7 +66,11 @@ export default class DeleteCollectionConfirmationPane extends ContextualPaneBase
this.isExecuting(false); this.isExecuting(false);
this.close(); this.close();
this.container.selectedNode(selectedCollection.database); this.container.selectedNode(selectedCollection.database);
this.container.tabsManager?.closeTabsByComparator(tab => tab.node && tab.node.rid === selectedCollection.rid); this.container.tabsManager?.closeTabsByComparator(
tab =>
tab.node?.id() === selectedCollection.id() &&
(tab.node as ViewModels.Collection).databaseId === selectedCollection.databaseId
);
this.container.refreshAllDatabases(); this.container.refreshAllDatabases();
this.resetData(); this.resetData();
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(

View File

@ -69,12 +69,16 @@ export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {
this.isExecuting(false); this.isExecuting(false);
this.close(); this.close();
this.container.refreshAllDatabases(); this.container.refreshAllDatabases();
this.container.tabsManager.closeTabsByComparator(tab => tab.node && tab.node.rid === selectedDatabase.rid); this.container.tabsManager.closeTabsByComparator(tab => tab.node?.id() === selectedDatabase.id());
this.container.selectedNode(null); this.container.selectedNode(null);
selectedDatabase selectedDatabase
.collections() .collections()
.forEach((collection: ViewModels.Collection) => .forEach((collection: ViewModels.Collection) =>
this.container.tabsManager.closeTabsByComparator(tab => tab.node && tab.node.rid === collection.rid) this.container.tabsManager.closeTabsByComparator(
tab =>
tab.node?.id() === collection.id() &&
(tab.node as ViewModels.Collection).databaseId === collection.databaseId
)
); );
this.resetData(); this.resetData();
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(

View File

@ -58,7 +58,6 @@ 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("Save");
protected _selfLink: string;
constructor(options: ViewModels.ConflictsTabOptions) { constructor(options: ViewModels.ConflictsTabOptions) {
super(options); super(options);
@ -74,7 +73,6 @@ export default class ConflictsTab extends TabsBase {
this.selectedConflictCurrent = editable.observable<any>(""); this.selectedConflictCurrent = editable.observable<any>("");
this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey); this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey);
this.conflictIds = options.conflictIds; this.conflictIds = options.conflictIds;
this._selfLink = options.selfLink || (this.collection && this.collection.self);
this.partitionKeyPropertyHeader = this.partitionKeyPropertyHeader =
(this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader(); (this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader();
this.partitionKeyProperty = !!this.partitionKeyPropertyHeader this.partitionKeyProperty = !!this.partitionKeyPropertyHeader

View File

@ -15,7 +15,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
@ -89,7 +88,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
@ -107,7 +105,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
@ -125,7 +122,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
@ -143,7 +139,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
@ -161,7 +156,6 @@ describe("Documents tab", () => {
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),

View File

@ -70,7 +70,6 @@ export default class DocumentsTab extends TabsBase {
private _documentsIterator: QueryIterator<ItemDefinition & Resource>; private _documentsIterator: QueryIterator<ItemDefinition & Resource>;
private _resourceTokenPartitionKey: string; private _resourceTokenPartitionKey: string;
protected _selfLink: string;
constructor(options: ViewModels.DocumentsTabOptions) { constructor(options: ViewModels.DocumentsTabOptions) {
super(options); super(options);
@ -91,7 +90,6 @@ export default class DocumentsTab extends TabsBase {
this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey); this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey);
this._resourceTokenPartitionKey = options.resourceTokenPartitionKey; this._resourceTokenPartitionKey = options.resourceTokenPartitionKey;
this.documentIds = options.documentIds; this.documentIds = options.documentIds;
this._selfLink = options.selfLink || (this.collection && this.collection.self);
this.partitionKeyPropertyHeader = this.partitionKeyPropertyHeader =
(this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader(); (this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader();

View File

@ -91,8 +91,6 @@ export default class GraphTab extends TabsBase {
onIsFilterQueryLoading: (isFilterQueryLoading: boolean): void => this.isFilterQueryLoading(isFilterQueryLoading), onIsFilterQueryLoading: (isFilterQueryLoading: boolean): void => this.isFilterQueryLoading(isFilterQueryLoading),
onIsValidQuery: (isValidQuery: boolean): void => this.isValidQuery(isValidQuery), onIsValidQuery: (isValidQuery: boolean): void => this.isValidQuery(isValidQuery),
collectionPartitionKeyProperty: options.collectionPartitionKeyProperty, collectionPartitionKeyProperty: options.collectionPartitionKeyProperty,
collectionRid: this.rid,
collectionSelfLink: options.selfLink,
graphBackendEndpoint: GraphTab.getGremlinEndpoint(options.account), graphBackendEndpoint: GraphTab.getGremlinEndpoint(options.account),
databaseId: options.databaseId, databaseId: options.databaseId,
collectionId: options.collectionId, collectionId: options.collectionId,

View File

@ -24,7 +24,6 @@ describe("Query Tab", () => {
database: database, database: database,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
hashLocation: "", hashLocation: "",
onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {}

View File

@ -55,7 +55,6 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
protected monacoSettings: ViewModels.MonacoEditorSettings; protected monacoSettings: ViewModels.MonacoEditorSettings;
private _executeQueryButtonTitle: ko.Observable<string>; private _executeQueryButtonTitle: ko.Observable<string>;
protected _iterator: MinimalQueryIterator; protected _iterator: MinimalQueryIterator;
private _selfLink: string;
private _isSaveQueriesEnabled: ko.Computed<boolean>; private _isSaveQueriesEnabled: ko.Computed<boolean>;
private _resourceTokenPartitionKey: string; private _resourceTokenPartitionKey: string;
@ -86,7 +85,6 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
this.errors = ko.observableArray<ViewModels.QueryError>([]); this.errors = ko.observableArray<ViewModels.QueryError>([]);
this._partitionKey = options.partitionKey; this._partitionKey = options.partitionKey;
this._resourceTokenPartitionKey = options.resourceTokenPartitionKey; this._resourceTokenPartitionKey = options.resourceTokenPartitionKey;
this._selfLink = options.selfLink;
this.splitterId = this.tabId + "_splitter"; this.splitterId = this.tabId + "_splitter";
this.isPreferredApiMongoDB = false; this.isPreferredApiMongoDB = false;
this.aggregatedQueryMetrics = ko.observable<DataModels.QueryMetrics>(); this.aggregatedQueryMetrics = ko.observable<DataModels.QueryMetrics>();

View File

@ -64,7 +64,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection( collection: new Collection(
@ -187,7 +186,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -209,8 +207,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -227,8 +223,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -265,8 +259,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -281,8 +273,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -306,8 +296,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null),
@ -380,8 +368,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: getCollection(defaultApi, partitionKeyOption), collection: getCollection(defaultApi, partitionKeyOption),
@ -520,8 +506,6 @@ describe("Settings tab", () => {
tabKind: ViewModels.CollectionTabKind.Settings, tabKind: ViewModels.CollectionTabKind.Settings,
title: "Scale & Settings", title: "Scale & Settings",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable(false), isActive: ko.observable(false),
collection: getCollection(autoPilotTier), collection: getCollection(autoPilotTier),

View File

@ -50,7 +50,6 @@ describe("Tabs manager tests", () => {
database, database,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
hashLocation: "", hashLocation: "",
onUpdateTabsButtons: undefined onUpdateTabsButtons: undefined
@ -63,7 +62,6 @@ describe("Tabs manager tests", () => {
collection, collection,
title: "", title: "",
tabPath: "", tabPath: "",
selfLink: "",
hashLocation: "", hashLocation: "",
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
onUpdateTabsButtons: undefined onUpdateTabsButtons: undefined

View File

@ -239,7 +239,9 @@ export default class Collection implements ViewModels.Collection {
this.expandCollection(); this.expandCollection();
} }
this.container.onUpdateTabsButtons([]); this.container.onUpdateTabsButtons([]);
this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); this.container.tabsManager.refreshActiveTab(
tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
);
} }
public collapseCollection() { public collapseCollection() {
@ -290,7 +292,7 @@ export default class Collection implements ViewModels.Collection {
const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs( const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.Documents, ViewModels.CollectionTabKind.Documents,
tab => tab.collection && tab.collection.rid === this.rid tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
) as DocumentsTab[]; ) as DocumentsTab[];
let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0]; let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0];
@ -312,8 +314,6 @@ export default class Collection implements ViewModels.Collection {
documentIds: ko.observableArray<DocumentId>([]), documentIds: ko.observableArray<DocumentId>([]),
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "Items", title: "Items",
selfLink: this.self,
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
collection: this, collection: this,
node: this, node: this,
@ -341,7 +341,7 @@ export default class Collection implements ViewModels.Collection {
const conflictsTabs: ConflictsTab[] = this.container.tabsManager.getTabs( const conflictsTabs: ConflictsTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.Conflicts, ViewModels.CollectionTabKind.Conflicts,
tab => tab.collection && tab.collection.rid === this.rid tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
) as ConflictsTab[]; ) as ConflictsTab[];
let conflictsTab: ConflictsTab = conflictsTabs && conflictsTabs[0]; let conflictsTab: ConflictsTab = conflictsTabs && conflictsTabs[0];
@ -363,8 +363,6 @@ export default class Collection implements ViewModels.Collection {
conflictIds: ko.observableArray<ConflictId>([]), conflictIds: ko.observableArray<ConflictId>([]),
tabKind: ViewModels.CollectionTabKind.Conflicts, tabKind: ViewModels.CollectionTabKind.Conflicts,
title: "Conflicts", title: "Conflicts",
selfLink: this.self,
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
collection: this, collection: this,
node: this, node: this,
@ -398,7 +396,7 @@ export default class Collection implements ViewModels.Collection {
const queryTablesTabs: QueryTablesTab[] = this.container.tabsManager.getTabs( const queryTablesTabs: QueryTablesTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.QueryTables, ViewModels.CollectionTabKind.QueryTables,
tab => tab.collection && tab.collection.rid === this.rid tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
) as QueryTablesTab[]; ) as QueryTablesTab[];
let queryTablesTab: QueryTablesTab = queryTablesTabs && queryTablesTabs[0]; let queryTablesTab: QueryTablesTab = queryTablesTabs && queryTablesTabs[0];
@ -427,7 +425,6 @@ export default class Collection implements ViewModels.Collection {
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/entities`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/entities`,
isActive: ko.observable(false), isActive: ko.observable(false),
onLoadStartKey: startKey, onLoadStartKey: startKey,
@ -452,7 +449,7 @@ export default class Collection implements ViewModels.Collection {
const graphTabs: GraphTab[] = this.container.tabsManager.getTabs( const graphTabs: GraphTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.Graph, ViewModels.CollectionTabKind.Graph,
tab => tab.collection && tab.collection.rid === this.rid tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
) as GraphTab[]; ) as GraphTab[];
let graphTab: GraphTab = graphTabs && graphTabs[0]; let graphTab: GraphTab = graphTabs && graphTabs[0];
@ -478,7 +475,6 @@ export default class Collection implements ViewModels.Collection {
tabPath: "", tabPath: "",
collection: this, collection: this,
selfLink: this.self,
masterKey: userContext.masterKey || "", masterKey: userContext.masterKey || "",
collectionPartitionKeyProperty: this.partitionKeyProperty, collectionPartitionKeyProperty: this.partitionKeyProperty,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/graphs`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/graphs`,
@ -508,7 +504,7 @@ export default class Collection implements ViewModels.Collection {
const mongoDocumentsTabs: MongoDocumentsTab[] = this.container.tabsManager.getTabs( const mongoDocumentsTabs: MongoDocumentsTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.Documents, ViewModels.CollectionTabKind.Documents,
tab => tab.collection && tab.collection.rid === this.rid tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
) as MongoDocumentsTab[]; ) as MongoDocumentsTab[];
let mongoDocumentsTab: MongoDocumentsTab = mongoDocumentsTabs && mongoDocumentsTabs[0]; let mongoDocumentsTab: MongoDocumentsTab = mongoDocumentsTabs && mongoDocumentsTabs[0];
@ -535,7 +531,6 @@ export default class Collection implements ViewModels.Collection {
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoDocuments`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoDocuments`,
isActive: ko.observable(false), isActive: ko.observable(false),
onLoadStartKey: startKey, onLoadStartKey: startKey,
@ -561,7 +556,7 @@ export default class Collection implements ViewModels.Collection {
const tabTitle = !this.offer() ? "Settings" : "Scale & Settings"; const tabTitle = !this.offer() ? "Settings" : "Scale & Settings";
const pendingNotificationsPromise: Q.Promise<DataModels.Notification> = this._getPendingThroughputSplitNotification(); const pendingNotificationsPromise: Q.Promise<DataModels.Notification> = this._getPendingThroughputSplitNotification();
const matchingTabs = this.container.tabsManager.getTabs(ViewModels.CollectionTabKind.Settings, tab => { const matchingTabs = this.container.tabsManager.getTabs(ViewModels.CollectionTabKind.Settings, tab => {
return tab.collection && tab.collection.rid === this.rid; return tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id();
}); });
const traceStartData = { const traceStartData = {
@ -579,7 +574,6 @@ export default class Collection implements ViewModels.Collection {
tabPath: "", tabPath: "",
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/settings`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/settings`,
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
@ -672,7 +666,6 @@ export default class Collection implements ViewModels.Collection {
tabPath: "", tabPath: "",
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/query`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/query`,
isActive: ko.observable(false), isActive: ko.observable(false),
queryText: queryText, queryText: queryText,
@ -704,7 +697,6 @@ export default class Collection implements ViewModels.Collection {
tabPath: "", tabPath: "",
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoQuery`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoQuery`,
isActive: ko.observable(false), isActive: ko.observable(false),
partitionKey: collection.partitionKey, partitionKey: collection.partitionKey,
@ -735,7 +727,6 @@ export default class Collection implements ViewModels.Collection {
title: title, title: title,
tabPath: "", tabPath: "",
collection: this, collection: this,
selfLink: this.self,
masterKey: userContext.masterKey || "", masterKey: userContext.masterKey || "",
collectionPartitionKeyProperty: this.partitionKeyProperty, collectionPartitionKeyProperty: this.partitionKeyProperty,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/graphs`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/graphs`,
@ -759,7 +750,6 @@ export default class Collection implements ViewModels.Collection {
collection: this, collection: this,
node: this, node: this,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/mongoShell`,
selfLink: this.self,
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
}); });
@ -822,7 +812,9 @@ export default class Collection implements ViewModels.Collection {
} else { } else {
this.expandStoredProcedures(); this.expandStoredProcedures();
} }
this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); this.container.tabsManager.refreshActiveTab(
tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
);
} }
public expandStoredProcedures() { public expandStoredProcedures() {
@ -879,7 +871,9 @@ export default class Collection implements ViewModels.Collection {
} else { } else {
this.expandUserDefinedFunctions(); this.expandUserDefinedFunctions();
} }
this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); this.container.tabsManager.refreshActiveTab(
tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
);
} }
public expandUserDefinedFunctions() { public expandUserDefinedFunctions() {
@ -936,7 +930,9 @@ export default class Collection implements ViewModels.Collection {
} else { } else {
this.expandTriggers(); this.expandTriggers();
} }
this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); this.container.tabsManager.refreshActiveTab(
tab => tab.collection && tab.collection.databaseId === this.databaseId && tab.collection.id() === this.id()
);
} }
public expandTriggers() { public expandTriggers() {
@ -1029,26 +1025,6 @@ export default class Collection implements ViewModels.Collection {
this.uploadFiles(event.originalEvent.dataTransfer.files); this.uploadFiles(event.originalEvent.dataTransfer.files);
} }
public isCollectionNodeSelected(): boolean {
return (
this.isSubNodeSelected(ViewModels.CollectionTabKind.Query) ||
(!this.isCollectionExpanded() &&
this.container.selectedNode &&
this.container.selectedNode() &&
this.container.selectedNode().rid === this.rid &&
this.container.selectedNode().nodeKind === "Collection")
);
}
public isSubNodeSelected(nodeKind: ViewModels.CollectionTabKind): boolean {
return (
this.container.selectedNode &&
this.container.selectedNode() &&
this.container.selectedNode().rid === this.rid &&
this.selectedSubnodeKind() === nodeKind
);
}
public onDeleteCollectionContextMenuClick(source: ViewModels.Collection, event: MouseEvent | KeyboardEvent) { public onDeleteCollectionContextMenuClick(source: ViewModels.Collection, event: MouseEvent | KeyboardEvent) {
this.container.deleteCollectionConfirmationPane.open(); this.container.deleteCollectionConfirmationPane.open();
} }
@ -1284,10 +1260,6 @@ export default class Collection implements ViewModels.Collection {
}); });
} }
protected _getOfferForCollection(offers: DataModels.Offer[], collection: DataModels.Collection): DataModels.Offer {
return _.find(offers, (offer: DataModels.Offer) => offer.resource.indexOf(collection._rid) >= 0);
}
/** /**
* Top-level method that will open the correct tab type depending on account API * Top-level method that will open the correct tab type depending on account API
*/ */

View File

@ -57,7 +57,7 @@ export default class Database implements ViewModels.Database {
const pendingNotificationsPromise: Q.Promise<DataModels.Notification> = this._getPendingThroughputSplitNotification(); const pendingNotificationsPromise: Q.Promise<DataModels.Notification> = this._getPendingThroughputSplitNotification();
const matchingTabs = this.container.tabsManager.getTabs( const matchingTabs = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.DatabaseSettings, ViewModels.CollectionTabKind.DatabaseSettings,
tab => tab.rid === this.rid tab => tab.node?.id() === this.id()
); );
let settingsTab: DatabaseSettingsTab = matchingTabs && (matchingTabs[0] as DatabaseSettingsTab); let settingsTab: DatabaseSettingsTab = matchingTabs && (matchingTabs[0] as DatabaseSettingsTab);
if (!settingsTab) { if (!settingsTab) {
@ -79,7 +79,6 @@ export default class Database implements ViewModels.Database {
rid: this.rid, rid: this.rid,
database: this, database: this,
hashLocation: `${Constants.HashRoutePrefixes.databasesWithId(this.id())}/settings`, hashLocation: `${Constants.HashRoutePrefixes.databasesWithId(this.id())}/settings`,
selfLink: this.self,
isActive: ko.observable(false), isActive: ko.observable(false),
onLoadStartKey: startKey, onLoadStartKey: startKey,
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
@ -128,8 +127,8 @@ export default class Database implements ViewModels.Database {
!this.isDatabaseExpanded() && !this.isDatabaseExpanded() &&
this.container.selectedNode && this.container.selectedNode &&
this.container.selectedNode() && this.container.selectedNode() &&
this.container.selectedNode().rid === this.rid && this.container.selectedNode().nodeKind === "Database" &&
this.container.selectedNode().nodeKind === "Database" this.container.selectedNode().id() === this.id()
); );
} }
@ -266,7 +265,7 @@ export default class Database implements ViewModels.Database {
(collection: DataModels.Collection) => { (collection: DataModels.Collection) => {
const collectionExists = _.some( const collectionExists = _.some(
this.collections(), this.collections(),
(existingCollection: Collection) => existingCollection.rid === collection._rid (existingCollection: Collection) => existingCollection.id() === collection.id
); );
return !collectionExists; return !collectionExists;
} }
@ -276,7 +275,7 @@ export default class Database implements ViewModels.Database {
ko.utils.arrayForEach(this.collections(), (collection: Collection) => { ko.utils.arrayForEach(this.collections(), (collection: Collection) => {
const collectionPresentInUpdatedList = _.some( const collectionPresentInUpdatedList = _.some(
updatedCollectionsList, updatedCollectionsList,
(coll: DataModels.Collection) => coll._rid === collection.rid (coll: DataModels.Collection) => coll.id === collection.id()
); );
if (!collectionPresentInUpdatedList) { if (!collectionPresentInUpdatedList) {
collectionsToDelete.push(collection); collectionsToDelete.push(collection);
@ -302,7 +301,7 @@ export default class Database implements ViewModels.Database {
const collectionsToKeep: Collection[] = []; const collectionsToKeep: Collection[] = [];
ko.utils.arrayForEach(this.collections(), (collection: Collection) => { ko.utils.arrayForEach(this.collections(), (collection: Collection) => {
const shouldRemoveCollection = _.some(collectionsToRemove, (coll: Collection) => coll.rid === collection.rid); const shouldRemoveCollection = _.some(collectionsToRemove, (coll: Collection) => coll.id() === collection.id());
if (!shouldRemoveCollection) { if (!shouldRemoveCollection) {
collectionsToKeep.push(collection); collectionsToKeep.push(collection);
} }

View File

@ -94,7 +94,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
tabPath: "", tabPath: "",
collection: this, collection: this,
node: this, node: this,
selfLink: this.self,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/query`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(this.databaseId, this.id())}/query`,
isActive: ko.observable(false), isActive: ko.observable(false),
queryText: queryText, queryText: queryText,
@ -121,7 +120,9 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs( const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs(
ViewModels.CollectionTabKind.Documents, ViewModels.CollectionTabKind.Documents,
(tab: TabsBase) => tab.collection && tab.collection.rid === this.rid (tab: TabsBase) =>
tab.collection?.id() === this.id() &&
(tab.collection as ViewModels.CollectionBase).databaseId === this.databaseId
) as DocumentsTab[]; ) as DocumentsTab[];
let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0]; let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0];
@ -143,7 +144,6 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
documentIds: ko.observableArray<DocumentId>([]), documentIds: ko.observableArray<DocumentId>([]),
tabKind: ViewModels.CollectionTabKind.Documents, tabKind: ViewModels.CollectionTabKind.Documents,
title: "Items", title: "Items",
selfLink: this.self,
isActive: ko.observable<boolean>(false), isActive: ko.observable<boolean>(false),
collection: this, collection: this,
node: this, node: this,

View File

@ -51,11 +51,11 @@ describe("ResourceTreeAdapter", () => {
explorer.selectedNode(({ explorer.selectedNode(({
nodeKind: "Database", nodeKind: "Database",
rid: "dbrid", rid: "dbrid",
id: ko.observable<string>("id"), id: ko.observable<string>("dbid"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind) selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode); } as unknown) as ViewModels.TreeNode);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer); const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbrid", "Database", [ const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbid", undefined, [
ViewModels.CollectionTabKind.Documents ViewModels.CollectionTabKind.Documents
]); ]);
expect(isDataNodeSelected).toBeTruthy(); expect(isDataNodeSelected).toBeTruthy();
@ -70,11 +70,12 @@ describe("ResourceTreeAdapter", () => {
explorer.selectedNode(({ explorer.selectedNode(({
nodeKind: "Collection", nodeKind: "Collection",
rid: "collrid", rid: "collrid",
id: ko.observable<string>("id"), databaseId: "dbid",
id: ko.observable<string>("collid"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind) selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode); } as unknown) as ViewModels.TreeNode);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer); const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
let isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]); let isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbid", "collid", [subNodeKind]);
expect(isDataNodeSelected).toBeTruthy(); expect(isDataNodeSelected).toBeTruthy();
subNodeKind = ViewModels.CollectionTabKind.Graph; subNodeKind = ViewModels.CollectionTabKind.Graph;
@ -84,10 +85,11 @@ describe("ResourceTreeAdapter", () => {
explorer.selectedNode(({ explorer.selectedNode(({
nodeKind: "Collection", nodeKind: "Collection",
rid: "collrid", rid: "collrid",
id: ko.observable<string>("id"), databaseId: "dbid",
id: ko.observable<string>("collid"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind) selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
} as unknown) as ViewModels.TreeNode); } as unknown) as ViewModels.TreeNode);
isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]); isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbid", "collid", [subNodeKind]);
expect(isDataNodeSelected).toBeTruthy(); expect(isDataNodeSelected).toBeTruthy();
}); });
@ -96,14 +98,15 @@ describe("ResourceTreeAdapter", () => {
explorer.selectedNode(({ explorer.selectedNode(({
nodeKind: "Collection", nodeKind: "Collection",
rid: "collrid", rid: "collrid",
id: ko.observable<string>("id"), databaseId: "dbid",
id: ko.observable<string>("collid"),
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(ViewModels.CollectionTabKind.Documents) selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(ViewModels.CollectionTabKind.Documents)
} as unknown) as ViewModels.TreeNode); } as unknown) as ViewModels.TreeNode);
explorer.tabsManager.activeTab({ explorer.tabsManager.activeTab({
tabKind: ViewModels.CollectionTabKind.Documents tabKind: ViewModels.CollectionTabKind.Documents
} as TabsBase); } as TabsBase);
const resourceTreeAdapter = new ResourceTreeAdapter(explorer); const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [ const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbid", "collid", [
ViewModels.CollectionTabKind.Settings ViewModels.CollectionTabKind.Settings
]); ]);
expect(isDataNodeSelected).toBeFalsy(); expect(isDataNodeSelected).toBeFalsy();

View File

@ -195,7 +195,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
isExpanded: false, isExpanded: false,
className: "databaseHeader", className: "databaseHeader",
children: [], children: [],
isSelected: () => this.isDataNodeSelected(database.rid, "Database", undefined), isSelected: () => this.isDataNodeSelected(database.id()),
contextMenu: ResourceTreeContextMenuButtonFactory.createDatabaseContextMenu(this.container), contextMenu: ResourceTreeContextMenuButtonFactory.createDatabaseContextMenu(this.container),
onClick: async isExpanded => { onClick: async isExpanded => {
// Rewritten version of expandCollapseDatabase(): // Rewritten version of expandCollapseDatabase():
@ -210,9 +210,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
databaseNode.isLoading = false; databaseNode.isLoading = false;
database.selectDatabase(); database.selectDatabase();
this.container.onUpdateTabsButtons([]); this.container.onUpdateTabsButtons([]);
this.container.tabsManager.refreshActiveTab( this.container.tabsManager.refreshActiveTab((tab: TabsBase) => tab.collection?.databaseId === database.id());
(tab: TabsBase) => tab.collection && tab.collection.getDatabase().rid === database.rid
);
}, },
onContextMenuOpen: () => this.container.selectedNode(database) onContextMenuOpen: () => this.container.selectedNode(database)
}; };
@ -221,7 +219,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
databaseNode.children.push({ databaseNode.children.push({
label: "Scale", label: "Scale",
isSelected: () => isSelected: () =>
this.isDataNodeSelected(database.rid, "Database", [ViewModels.CollectionTabKind.DatabaseSettings]), this.isDataNodeSelected(database.id(), undefined, [ViewModels.CollectionTabKind.DatabaseSettings]),
onClick: database.onSettingsClick.bind(database) onClick: database.onSettingsClick.bind(database)
}); });
} }
@ -268,11 +266,14 @@ export class ResourceTreeAdapter implements ReactAdapter {
type: MostRecentActivity.Type.OpenCollection, type: MostRecentActivity.Type.OpenCollection,
title: collection.id(), title: collection.id(),
description: "Data", description: "Data",
data: collection.rid data: {
databaseId: collection.databaseId,
collectionId: collection.id()
}
}); });
}, },
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ this.isDataNodeSelected(collection.databaseId, collection.id(), [
ViewModels.CollectionTabKind.Documents, ViewModels.CollectionTabKind.Documents,
ViewModels.CollectionTabKind.Graph ViewModels.CollectionTabKind.Graph
]), ]),
@ -282,7 +283,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
children.push({ children.push({
label: database.isDatabaseShared() || this.container.isServerlessEnabled() ? "Settings" : "Scale & Settings", label: database.isDatabaseShared() || this.container.isServerlessEnabled() ? "Settings" : "Scale & Settings",
onClick: collection.onSettingsClick.bind(collection), onClick: collection.onSettingsClick.bind(collection),
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Settings]) isSelected: () =>
this.isDataNodeSelected(collection.databaseId, collection.id(), [ViewModels.CollectionTabKind.Settings])
}); });
if (ResourceTreeAdapter.showScriptNodes(this.container)) { if (ResourceTreeAdapter.showScriptNodes(this.container)) {
@ -305,7 +307,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: "Conflicts", label: "Conflicts",
onClick: collection.onConflictsClick.bind(collection), onClick: collection.onConflictsClick.bind(collection),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Conflicts]) this.isDataNodeSelected(collection.databaseId, collection.id(), [ViewModels.CollectionTabKind.Conflicts])
}); });
} }
@ -321,7 +323,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
this.container.selectedNode(collection); this.container.selectedNode(collection);
this.container.onUpdateTabsButtons([]); this.container.onUpdateTabsButtons([]);
this.container.tabsManager.refreshActiveTab( this.container.tabsManager.refreshActiveTab(
(tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid (tab: TabsBase) =>
tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId
); );
}, },
onExpanded: () => { onExpanded: () => {
@ -331,7 +334,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
collection.loadTriggers(); collection.loadTriggers();
} }
}, },
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", undefined), isSelected: () => this.isDataNodeSelected(collection.databaseId, collection.id()),
onContextMenuOpen: () => this.container.selectedNode(collection) onContextMenuOpen: () => this.container.selectedNode(collection)
}; };
} }
@ -343,13 +346,16 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: sp.id(), label: sp.id(),
onClick: sp.open.bind(sp), onClick: sp.open.bind(sp),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.StoredProcedures]), this.isDataNodeSelected(collection.databaseId, collection.id(), [
ViewModels.CollectionTabKind.StoredProcedures
]),
contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp) contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp)
})), })),
onClick: () => { onClick: () => {
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.StoredProcedures); collection.selectedSubnodeKind(ViewModels.CollectionTabKind.StoredProcedures);
this.container.tabsManager.refreshActiveTab( this.container.tabsManager.refreshActiveTab(
(tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid (tab: TabsBase) =>
tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId
); );
} }
}; };
@ -362,13 +368,16 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: udf.id(), label: udf.id(),
onClick: udf.open.bind(udf), onClick: udf.open.bind(udf),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.UserDefinedFunctions]), this.isDataNodeSelected(collection.databaseId, collection.id(), [
ViewModels.CollectionTabKind.UserDefinedFunctions
]),
contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf) contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf)
})), })),
onClick: () => { onClick: () => {
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.UserDefinedFunctions); collection.selectedSubnodeKind(ViewModels.CollectionTabKind.UserDefinedFunctions);
this.container.tabsManager.refreshActiveTab( this.container.tabsManager.refreshActiveTab(
(tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid (tab: TabsBase) =>
tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId
); );
} }
}; };
@ -381,13 +390,14 @@ export class ResourceTreeAdapter implements ReactAdapter {
label: trigger.id(), label: trigger.id(),
onClick: trigger.open.bind(trigger), onClick: trigger.open.bind(trigger),
isSelected: () => isSelected: () =>
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Triggers]), this.isDataNodeSelected(collection.databaseId, collection.id(), [ViewModels.CollectionTabKind.Triggers]),
contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger) contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger)
})), })),
onClick: () => { onClick: () => {
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Triggers); collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Triggers);
this.container.tabsManager.refreshActiveTab( this.container.tabsManager.refreshActiveTab(
(tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid (tab: TabsBase) =>
tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId
); );
} }
}; };
@ -741,35 +751,42 @@ export class ResourceTreeAdapter implements ReactAdapter {
/** /**
* public for testing purposes * public for testing purposes
* @param rid * @param databaseId
* @param nodeKind * @param collectionId
* @param subnodeKinds * @param subnodeKinds
*/ */
public isDataNodeSelected(rid: string, nodeKind: string, subnodeKinds: ViewModels.CollectionTabKind[]): boolean { public isDataNodeSelected(
databaseId: string,
collectionId?: string,
subnodeKinds?: ViewModels.CollectionTabKind[]
): boolean {
if (!this.container.selectedNode || !this.container.selectedNode()) { if (!this.container.selectedNode || !this.container.selectedNode()) {
return false; return false;
} }
const selectedNode = this.container.selectedNode(); const selectedNode = this.container.selectedNode();
const isNodeSelected = collectionId
? (selectedNode as ViewModels.Collection).databaseId === databaseId && selectedNode.id() === collectionId
: selectedNode.id() === databaseId;
if (!isNodeSelected) {
return false;
}
if (subnodeKinds === undefined || !Array.isArray(subnodeKinds)) { if (subnodeKinds === undefined || !Array.isArray(subnodeKinds)) {
return selectedNode.rid === rid && selectedNode.nodeKind === nodeKind; return true;
} else {
const activeTab = this.container.tabsManager.activeTab();
let selectedSubnodeKind;
if (nodeKind === "Database" && (selectedNode as ViewModels.Database).selectedSubnodeKind) {
selectedSubnodeKind = (selectedNode as ViewModels.Database).selectedSubnodeKind();
} else if (nodeKind === "Collection" && (selectedNode as ViewModels.Collection).selectedSubnodeKind) {
selectedSubnodeKind = (selectedNode as ViewModels.Collection).selectedSubnodeKind();
}
return (
activeTab &&
subnodeKinds.includes(activeTab.tabKind) &&
selectedNode.rid === rid &&
selectedSubnodeKind !== undefined &&
subnodeKinds.includes(selectedSubnodeKind)
);
} }
const activeTab = this.container.tabsManager.activeTab();
const selectedSubnodeKind = collectionId
? (selectedNode as ViewModels.Collection).selectedSubnodeKind()
: (selectedNode as ViewModels.Database).selectedSubnodeKind();
return (
activeTab &&
subnodeKinds.includes(activeTab.tabKind) &&
selectedSubnodeKind !== undefined &&
subnodeKinds.includes(selectedSubnodeKind)
);
} }
// *************** watch all nested ko's inside database // *************** watch all nested ko's inside database

View File

@ -48,10 +48,14 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter {
type: MostRecentActivity.Type.OpenCollection, type: MostRecentActivity.Type.OpenCollection,
title: collection.id(), title: collection.id(),
description: "Data", description: "Data",
data: collection.rid data: {
databaseId: collection.databaseId,
collectionId: collection.id()
}
}); });
}, },
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Documents) isSelected: () =>
this.isDataNodeSelected(collection.databaseId, collection.id(), ViewModels.CollectionTabKind.Documents)
}); });
const collectionNode: TreeNode = { const collectionNode: TreeNode = {
@ -64,9 +68,11 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter {
// Rewritten version of expandCollapseCollection // Rewritten version of expandCollapseCollection
this.container.selectedNode(collection); this.container.selectedNode(collection);
this.container.onUpdateTabsButtons([]); this.container.onUpdateTabsButtons([]);
this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === collection.rid); this.container.tabsManager.refreshActiveTab(
tab => tab.collection?.id() === collection.id() && tab.collection.databaseId === collection.databaseId
);
}, },
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", undefined) isSelected: () => this.isDataNodeSelected(collection.databaseId, collection.id())
}; };
return { return {
@ -76,31 +82,33 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter {
}; };
} }
private isDataNodeSelected(rid: string, nodeKind: string, subnodeKind: ViewModels.CollectionTabKind): boolean { public isDataNodeSelected(
databaseId: string,
collectionId?: string,
subnodeKind?: ViewModels.CollectionTabKind
): boolean {
if (!this.container.selectedNode || !this.container.selectedNode()) { if (!this.container.selectedNode || !this.container.selectedNode()) {
return false; return false;
} }
const selectedNode = this.container.selectedNode(); const selectedNode = this.container.selectedNode();
const isNodeSelected = collectionId
? (selectedNode as ViewModels.Collection).databaseId === databaseId && selectedNode.id() === collectionId
: selectedNode.id() === databaseId;
if (subnodeKind) { if (!isNodeSelected) {
return selectedNode.rid === rid && selectedNode.nodeKind === nodeKind; return false;
} else {
const activeTab = this.container.tabsManager.activeTab();
let selectedSubnodeKind;
if (nodeKind === "Database" && (selectedNode as ViewModels.Database).selectedSubnodeKind) {
selectedSubnodeKind = (selectedNode as ViewModels.Database).selectedSubnodeKind();
} else if (nodeKind === "Collection" && (selectedNode as ViewModels.Collection).selectedSubnodeKind) {
selectedSubnodeKind = (selectedNode as ViewModels.Collection).selectedSubnodeKind();
}
return (
activeTab &&
activeTab.tabKind === subnodeKind &&
selectedNode.rid === rid &&
selectedSubnodeKind !== undefined &&
selectedSubnodeKind === subnodeKind
);
} }
if (!subnodeKind) {
return true;
}
const activeTab = this.container.tabsManager.activeTab();
const selectedSubnodeKind = collectionId
? (selectedNode as ViewModels.Collection).selectedSubnodeKind()
: (selectedNode as ViewModels.Database).selectedSubnodeKind();
return activeTab && activeTab.tabKind === subnodeKind && selectedSubnodeKind === subnodeKind;
} }
public triggerRender() { public triggerRender() {

View File

@ -74,7 +74,6 @@ export default class StoredProcedure {
collection: source, collection: source,
node: source, node: source,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/sproc`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/sproc`,
selfLink: "",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: source.container.onUpdateTabsButtons onUpdateTabsButtons: source.container.onUpdateTabsButtons
}); });
@ -123,7 +122,6 @@ export default class StoredProcedure {
this.collection.databaseId, this.collection.databaseId,
this.collection.id() this.collection.id()
)}/sprocs/${this.id()}`, )}/sprocs/${this.id()}`,
selfLink: this.self,
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
}); });

View File

@ -59,7 +59,6 @@ export default class Trigger {
collection: source, collection: source,
node: source, node: source,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/trigger`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/trigger`,
selfLink: "",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: source.container.onUpdateTabsButtons onUpdateTabsButtons: source.container.onUpdateTabsButtons
}); });
@ -100,7 +99,6 @@ export default class Trigger {
this.collection.databaseId, this.collection.databaseId,
this.collection.id() this.collection.id()
)}/triggers/${this.id()}`, )}/triggers/${this.id()}`,
selfLink: "",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
}); });

View File

@ -44,7 +44,6 @@ export default class UserDefinedFunction {
collection: source, collection: source,
node: source, node: source,
hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/udf`, hashLocation: `${Constants.HashRoutePrefixes.collectionsWithIds(source.databaseId, source.id())}/udf`,
selfLink: "",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: source.container.onUpdateTabsButtons onUpdateTabsButtons: source.container.onUpdateTabsButtons
}); });
@ -83,7 +82,6 @@ export default class UserDefinedFunction {
this.collection.databaseId, this.collection.databaseId,
this.collection.id() this.collection.id()
)}/udfs/${this.id()}`, )}/udfs/${this.id()}`,
selfLink: "",
isActive: ko.observable(false), isActive: ko.observable(false),
onUpdateTabsButtons: this.container.onUpdateTabsButtons onUpdateTabsButtons: this.container.onUpdateTabsButtons
}); });