Merge branch 'master' into users/languye/improve-filter-view

This commit is contained in:
Laurent Nguyen
2024-04-15 16:42:48 +02:00
39 changed files with 389 additions and 629 deletions

View File

@@ -1,3 +1,5 @@
import { sendMessage } from "Common/MessageHandler";
import { MessageTypes } from "Contracts/MessageTypes";
import { CopilotProvider } from "Explorer/QueryCopilot/QueryCopilotContext";
import { userContext } from "UserContext";
import React from "react";
@@ -54,6 +56,11 @@ export class NewQueryTab extends TabsBase {
);
}
public onActivate(): void {
this.propagateTabInformation(MessageTypes.ActivateTab);
super.onActivate();
}
public onTabClick(): void {
useTabs.getState().activateTab(this);
this.iTabAccessor.onTabClickEvent();
@@ -61,6 +68,7 @@ export class NewQueryTab extends TabsBase {
public onCloseTabButtonClick(): void {
useTabs.getState().closeTab(this);
this.propagateTabInformation(MessageTypes.CloseTab);
if (this.iTabAccessor) {
this.iTabAccessor.onCloseClickEvent(true);
}
@@ -69,4 +77,15 @@ export class NewQueryTab extends TabsBase {
public getContainer(): Explorer {
return this.props.container;
}
private propagateTabInformation(type: MessageTypes): void {
sendMessage({
type,
data: {
kind: this.tabKind,
databaseId: this.collection?.databaseId,
collectionId: this.collection?.id?.(),
},
});
}
}

View File

@@ -134,7 +134,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
this.state = {
toggleState: ToggleState.Result,
sqlQueryEditorContent: props.queryText || "SELECT * FROM c",
sqlQueryEditorContent: props.isPreferredApiMongoDB ? "{}" : props.queryText || "SELECT * FROM c",
selectedContent: "",
queryResults: undefined,
error: "",
@@ -496,13 +496,16 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
};
public onChangeContent(newContent: string): void {
// The copilot store's active query takes precedence over the local state,
// and we can't update both states in a single operation.
// So, we update the copilot store's state first, then update the local state.
if (this.state.copilotActive) {
this.props.copilotStore?.setQuery(newContent);
}
this.setState({
sqlQueryEditorContent: newContent,
queryCopilotGeneratedQuery: "",
});
if (this.state.copilotActive) {
this.props.copilotStore?.setQuery(newContent);
}
if (this.isPreferredApiMongoDB) {
if (newContent.length > 0) {
this.executeQueryButton = {
@@ -544,7 +547,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
useCommandBar.getState().setContextButtons(this.getTabsButtons());
}
public setEditorContent(): string {
public getEditorContent(): string {
if (this.isCopilotTabActive && this.state.queryCopilotGeneratedQuery) {
return this.state.queryCopilotGeneratedQuery;
}
@@ -601,7 +604,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
<div className="queryEditor" style={{ height: "100%" }}>
<EditorReact
language={"sql"}
content={this.setEditorContent()}
content={this.getEditorContent()}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}

View File

@@ -324,13 +324,17 @@ const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): J
const showMongoAndCassandraProxiesNetworkSettingsWarning = (): boolean => {
const ipRules: IpRule[] = userContext.databaseAccount?.properties?.ipRules;
if ((userContext.apiType === "Mongo" || userContext.apiType === "Cassandra") && ipRules?.length) {
if (
((userContext.apiType === "Mongo" && configContext.MONGO_PROXY_ENDPOINT !== MongoProxyEndpoints.Development) ||
(userContext.apiType === "Cassandra" &&
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development)) &&
ipRules?.length
) {
const legacyPortalBackendIPs: string[] = PortalBackendIPs[configContext.BACKEND_ENDPOINT];
const ipAddressesFromIPRules: string[] = ipRules.map((ipRule) => ipRule.ipAddressOrRange);
const ipRulesIncludeLegacyPortalBackend: boolean =
ipAddressesFromIPRules.filter((ipAddressFromIPRule) => legacyPortalBackendIPs.includes(ipAddressFromIPRule))
?.length === legacyPortalBackendIPs.length;
const ipRulesIncludeLegacyPortalBackend: boolean = legacyPortalBackendIPs.every((legacyPortalBackendIP: string) =>
ipAddressesFromIPRules.includes(legacyPortalBackendIP),
);
if (!ipRulesIncludeLegacyPortalBackend) {
return false;
}
@@ -344,9 +348,9 @@ const showMongoAndCassandraProxiesNetworkSettingsWarning = (): boolean => {
? [...MongoProxyOutboundIPs[MongoProxyEndpoints.Mpac], ...MongoProxyOutboundIPs[MongoProxyEndpoints.Prod]]
: MongoProxyOutboundIPs[configContext.MONGO_PROXY_ENDPOINT];
const ipRulesIncludeMongoProxy: boolean =
ipAddressesFromIPRules.filter((ipAddressFromIPRule) => mongoProxyOutboundIPs.includes(ipAddressFromIPRule))
?.length === mongoProxyOutboundIPs.length;
const ipRulesIncludeMongoProxy: boolean = mongoProxyOutboundIPs.every((mongoProxyOutboundIP: string) =>
ipAddressesFromIPRules.includes(mongoProxyOutboundIP),
);
if (ipRulesIncludeMongoProxy) {
updateConfigContext({
@@ -368,9 +372,15 @@ const showMongoAndCassandraProxiesNetworkSettingsWarning = (): boolean => {
]
: CassandraProxyOutboundIPs[configContext.CASSANDRA_PROXY_ENDPOINT];
const ipRulesIncludeCassandraProxy: boolean =
ipAddressesFromIPRules.filter((ipAddressFromIPRule) => cassandraProxyOutboundIPs.includes(ipAddressFromIPRule))
?.length === cassandraProxyOutboundIPs.length;
const ipRulesIncludeCassandraProxy: boolean = cassandraProxyOutboundIPs.every(
(cassandraProxyOutboundIP: string) => ipAddressesFromIPRules.includes(cassandraProxyOutboundIP),
);
if (ipRulesIncludeCassandraProxy) {
updateConfigContext({
CASSANDRA_PROXY_OUTBOUND_IPS_ALLOWLISTED: true,
});
}
return !ipRulesIncludeCassandraProxy;
}

View File

@@ -40,11 +40,10 @@ export default class TabsBase extends WaitsForTemplateViewModel {
this.database = options.database;
this.rid = options.rid || (this.collection && this.collection.rid) || "";
this.tabKind = options.tabKind;
this.tabTitle = ko.observable<string>(options.title);
this.tabTitle = ko.observable<string>(this.getTitle(options));
this.tabPath =
ko.observable(options.tabPath ?? "") ||
(this.collection &&
ko.observable<string>(`${this.collection.databaseId}>${this.collection.id()}>${this.tabTitle()}`));
this.collection &&
ko.observable<string>(`${this.collection.databaseId}>${this.collection.id()}>${options.title}`);
this.pendingNotification = ko.observable<DataModels.Notification>(undefined);
this.onLoadStartKey = options.onLoadStartKey;
this.closeTabButton = {
@@ -143,6 +142,26 @@ export default class TabsBase extends WaitsForTemplateViewModel {
return (this.collection && this.collection.container) || (this.database && this.database.container);
}
public getTitle(options: ViewModels.TabOptions): string {
const coll = this.collection?.id();
const db = this.database?.id();
if (coll) {
if (coll.length > 8) {
return coll.slice(0, 5) + "…" + options.title;
} else {
return coll + "." + options.title;
}
} else if (db) {
if (db.length > 8) {
return db.slice(0, 5) + "…" + options.title;
} else {
return db + "." + options.title;
}
} else {
return options.title;
}
}
/** Renders a Javascript object to be displayed inside Monaco Editor */
public renderObjectForEditor(value: any, replacer: any, space: string | number): string {
return JSON.stringify(value, replacer, space);