mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-09 20:49:12 +00:00
Compare commits
4 Commits
users/nish
...
hotfix/nov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d35ae7e0f1 | ||
|
|
d0d615a85a | ||
|
|
2996120235 | ||
|
|
3cd6d5a65d |
@@ -89,7 +89,7 @@ export class CapabilityNames {
|
||||
public static readonly EnableMongo: string = "EnableMongo";
|
||||
public static readonly EnableServerless: string = "EnableServerless";
|
||||
public static readonly EnableNoSQLVectorSearch: string = "EnableNoSQLVectorSearch";
|
||||
public static readonly EnableNoSQLFullTextSearch: string = "EnableNoSQLFullTextSearch";
|
||||
public static readonly EnableNoSQLFullTextSearchPreviewFeatures: string = "EnableNoSQLFullTextSearchPreviewFeatures";
|
||||
}
|
||||
|
||||
export enum CapacityMode {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Item, RequestOptions } from "@azure/cosmos";
|
||||
import { HttpHeaders } from "Common/Constants";
|
||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||
import { CollectionBase } from "../../Contracts/ViewModels";
|
||||
import DocumentId from "../../Explorer/Tree/DocumentId";
|
||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
@@ -23,10 +24,17 @@ export const updateDocument = async (
|
||||
[HttpHeaders.partitionKey]: documentId.partitionKeyValue,
|
||||
}
|
||||
: {};
|
||||
|
||||
// If user has chosen to ignore partition key on update, pass null instead of actual partition key value
|
||||
const ignorePartitionKeyOnDocumentUpdateFlag = LocalStorageUtility.getEntryBoolean(
|
||||
StorageKey.IgnorePartitionKeyOnDocumentUpdate,
|
||||
);
|
||||
const partitionKey = ignorePartitionKeyOnDocumentUpdateFlag ? undefined : getPartitionKeyValue(documentId);
|
||||
|
||||
const response = await client()
|
||||
.database(collection.databaseId)
|
||||
.container(collection.id())
|
||||
.item(documentId.id(), getPartitionKeyValue(documentId))
|
||||
.item(documentId.id(), partitionKey)
|
||||
.replace(newDocument, options);
|
||||
|
||||
logConsoleInfo(`Successfully updated ${entityName} ${documentId.id()}`);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { FullTextIndex, FullTextPath, FullTextPolicy } from "Contracts/DataModels";
|
||||
import { CollapsibleSectionComponent } from "Explorer/Controls/CollapsiblePanel/CollapsibleSectionComponent";
|
||||
import * as React from "react";
|
||||
import { isFullTextSearchPreviewFeaturesEnabled } from "Utils/CapabilityUtils";
|
||||
|
||||
export interface FullTextPoliciesComponentProps {
|
||||
fullTextPolicy: FullTextPolicy;
|
||||
@@ -22,6 +23,7 @@ export interface FullTextPoliciesComponentProps {
|
||||
) => void;
|
||||
discardChanges?: boolean;
|
||||
onChangesDiscarded?: () => void;
|
||||
englishOnly?: boolean;
|
||||
}
|
||||
|
||||
export interface FullTextPolicyData {
|
||||
@@ -66,6 +68,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
|
||||
onFullTextPathChange,
|
||||
discardChanges,
|
||||
onChangesDiscarded,
|
||||
englishOnly,
|
||||
}): JSX.Element => {
|
||||
const getFullTextPathError = (path: string, index?: number): string => {
|
||||
let error = "";
|
||||
@@ -87,6 +90,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
|
||||
if (!fullTextPolicy) {
|
||||
fullTextPolicy = { defaultLanguage: getFullTextLanguageOptions()[0].key as never, fullTextPaths: [] };
|
||||
}
|
||||
|
||||
return fullTextPolicy.fullTextPaths.map((fullTextPath: FullTextPath) => ({
|
||||
...fullTextPath,
|
||||
pathError: getFullTextPathError(fullTextPath.path),
|
||||
@@ -166,7 +170,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
|
||||
<Dropdown
|
||||
required={true}
|
||||
styles={dropdownStyles}
|
||||
options={getFullTextLanguageOptions()}
|
||||
options={getFullTextLanguageOptions(englishOnly)}
|
||||
selectedKey={defaultLanguage}
|
||||
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
|
||||
setDefaultLanguage(option.key as never)
|
||||
@@ -211,7 +215,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
|
||||
<Dropdown
|
||||
required={true}
|
||||
styles={dropdownStyles}
|
||||
options={getFullTextLanguageOptions()}
|
||||
options={getFullTextLanguageOptions(englishOnly)}
|
||||
selectedKey={fullTextPolicy.language}
|
||||
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
|
||||
onFullTextPathPolicyChange(index, option)
|
||||
@@ -229,11 +233,30 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
|
||||
);
|
||||
};
|
||||
|
||||
export const getFullTextLanguageOptions = (): IDropdownOption[] => {
|
||||
return [
|
||||
export const getFullTextLanguageOptions = (englishOnly?: boolean): IDropdownOption[] => {
|
||||
const multiLanguageSupportEnabled: boolean = isFullTextSearchPreviewFeaturesEnabled() && !englishOnly;
|
||||
const fullTextLanguageOptions: IDropdownOption[] = [
|
||||
{
|
||||
key: "en-US",
|
||||
text: "English (US)",
|
||||
},
|
||||
...(multiLanguageSupportEnabled
|
||||
? [
|
||||
{
|
||||
key: "fr-FR",
|
||||
text: "French",
|
||||
},
|
||||
{
|
||||
key: "de-DE",
|
||||
text: "German",
|
||||
},
|
||||
{
|
||||
key: "es-ES",
|
||||
text: "Spanish",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return fullTextLanguageOptions;
|
||||
};
|
||||
|
||||
@@ -893,6 +893,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
) => {
|
||||
this.setState({ fullTextPolicy, fullTextIndexes, fullTextPolicyValidated });
|
||||
}}
|
||||
// Remove when multi language support on container create issue is fixed
|
||||
englishOnly={true}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -516,6 +516,7 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
||||
}
|
||||
>
|
||||
<FullTextPoliciesComponent
|
||||
englishOnly={true}
|
||||
fullTextPolicy={
|
||||
{
|
||||
"defaultLanguage": "en-US",
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
IToggleStyles,
|
||||
Position,
|
||||
SpinButton,
|
||||
Stack,
|
||||
Toggle,
|
||||
} from "@fluentui/react";
|
||||
import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, makeStyles } from "@fluentui/react-components";
|
||||
@@ -204,6 +205,9 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
? (LocalStorageUtility.getEntryString(StorageKey.MongoGuidRepresentation) as Constants.MongoGuidRepresentation)
|
||||
: Constants.MongoGuidRepresentation.CSharpLegacy,
|
||||
);
|
||||
const [ignorePartitionKeyOnDocumentUpdate, setIgnorePartitionKeyOnDocumentUpdate] = useState<boolean>(
|
||||
LocalStorageUtility.getEntryBoolean(StorageKey.IgnorePartitionKeyOnDocumentUpdate),
|
||||
);
|
||||
|
||||
const styles = useStyles();
|
||||
|
||||
@@ -424,6 +428,12 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
LocalStorageUtility.setEntryString(StorageKey.MongoGuidRepresentation, mongoGuidRepresentation);
|
||||
}
|
||||
|
||||
// Advanced settings
|
||||
LocalStorageUtility.setEntryBoolean(
|
||||
StorageKey.IgnorePartitionKeyOnDocumentUpdate,
|
||||
ignorePartitionKeyOnDocumentUpdate,
|
||||
);
|
||||
|
||||
setIsExecuting(false);
|
||||
logConsoleInfo(
|
||||
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`,
|
||||
@@ -453,6 +463,10 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
);
|
||||
}
|
||||
|
||||
logConsoleInfo(
|
||||
`${ignorePartitionKeyOnDocumentUpdate ? "Enabled" : "Disabled"} ignoring partition key on document update`,
|
||||
);
|
||||
|
||||
refreshExplorer && (await explorer.refreshExplorer());
|
||||
closeSidePanel();
|
||||
};
|
||||
@@ -593,6 +607,13 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
setMongoGuidRepresentation(option.key as Constants.MongoGuidRepresentation);
|
||||
};
|
||||
|
||||
const handleOnIgnorePartitionKeyOnDocumentUpdateChange = (
|
||||
ev: React.MouseEvent<HTMLElement>,
|
||||
checked?: boolean,
|
||||
): void => {
|
||||
setIgnorePartitionKeyOnDocumentUpdate(!!checked);
|
||||
};
|
||||
|
||||
const choiceButtonStyles = {
|
||||
root: {
|
||||
clear: "both",
|
||||
@@ -1137,6 +1158,29 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
)}
|
||||
<AccordionItem value="15">
|
||||
<AccordionHeader>
|
||||
<div className={styles.header}>Advanced Settings</div>
|
||||
</AccordionHeader>
|
||||
<AccordionPanel>
|
||||
<div className={styles.settingsSectionContainer}>
|
||||
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 4 }}>
|
||||
<Checkbox
|
||||
styles={{ label: { padding: 0 } }}
|
||||
className="padding"
|
||||
ariaLabel="Ignore partition key on document update"
|
||||
checked={ignorePartitionKeyOnDocumentUpdate}
|
||||
onChange={handleOnIgnorePartitionKeyOnDocumentUpdateChange}
|
||||
label="Ignore partition key on document update"
|
||||
/>
|
||||
<InfoTooltip className={styles.headerIcon}>
|
||||
If checked, the partition key value will not be used to locate the document during update
|
||||
operations. Only use this if document updates are failing due to an abnormal partition key.
|
||||
</InfoTooltip>
|
||||
</Stack>
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)}
|
||||
|
||||
|
||||
@@ -575,6 +575,52 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
<AccordionItem
|
||||
value="15"
|
||||
>
|
||||
<AccordionHeader>
|
||||
<div
|
||||
className="___15c001r_0000000 fq02s40"
|
||||
>
|
||||
Advanced Settings
|
||||
</div>
|
||||
</AccordionHeader>
|
||||
<AccordionPanel>
|
||||
<div
|
||||
className="___1dfa554_0000000 fo7qwa0"
|
||||
>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
tokens={
|
||||
{
|
||||
"childrenGap": 4,
|
||||
}
|
||||
}
|
||||
verticalAlign="center"
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
ariaLabel="Ignore partition key on document update"
|
||||
checked={false}
|
||||
className="padding"
|
||||
label="Ignore partition key on document update"
|
||||
onChange={[Function]}
|
||||
styles={
|
||||
{
|
||||
"label": {
|
||||
"padding": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<InfoTooltip
|
||||
className="___vtc5hy0_0000000 f10ra9hq f1k6fduh"
|
||||
>
|
||||
If checked, the partition key value will not be used to locate the document during update operations. Only use this if document updates are failing due to an abnormal partition key.
|
||||
</InfoTooltip>
|
||||
</Stack>
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
<div
|
||||
className="settingsSection"
|
||||
@@ -838,6 +884,52 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
<AccordionItem
|
||||
value="15"
|
||||
>
|
||||
<AccordionHeader>
|
||||
<div
|
||||
className="___15c001r_0000000 fq02s40"
|
||||
>
|
||||
Advanced Settings
|
||||
</div>
|
||||
</AccordionHeader>
|
||||
<AccordionPanel>
|
||||
<div
|
||||
className="___1dfa554_0000000 fo7qwa0"
|
||||
>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
tokens={
|
||||
{
|
||||
"childrenGap": 4,
|
||||
}
|
||||
}
|
||||
verticalAlign="center"
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
ariaLabel="Ignore partition key on document update"
|
||||
checked={false}
|
||||
className="padding"
|
||||
label="Ignore partition key on document update"
|
||||
onChange={[Function]}
|
||||
styles={
|
||||
{
|
||||
"label": {
|
||||
"padding": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<InfoTooltip
|
||||
className="___vtc5hy0_0000000 f10ra9hq f1k6fduh"
|
||||
>
|
||||
If checked, the partition key value will not be used to locate the document during update operations. Only use this if document updates are failing due to an abnormal partition key.
|
||||
</InfoTooltip>
|
||||
</Stack>
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
<div
|
||||
className="settingsSection"
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { Upload } from "Common/Upload/Upload";
|
||||
import { UploadDetailsRecord } from "Contracts/ViewModels";
|
||||
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
||||
import React, { ChangeEvent, FunctionComponent, useState } from "react";
|
||||
import React, { ChangeEvent, FunctionComponent, useReducer, useState } from "react";
|
||||
import { getErrorMessage } from "../../Tables/Utilities";
|
||||
import { useSelectedNode } from "../../useSelectedNode";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
@@ -57,6 +57,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
|
||||
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
|
||||
const [formError, setFormError] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>();
|
||||
const [reducer, setReducer] = useReducer((x) => x + 1, 1);
|
||||
|
||||
const onSubmit = () => {
|
||||
setFormError("");
|
||||
@@ -75,6 +76,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
|
||||
(uploadDetails) => {
|
||||
setUploadFileData(uploadDetails.data);
|
||||
setFiles(undefined);
|
||||
setReducer(); // Trigger a re-render to update the UI with new upload details
|
||||
// Emit the upload details to the parent component
|
||||
onUpload && onUpload(uploadDetails.data);
|
||||
},
|
||||
@@ -95,6 +97,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
|
||||
const props: RightPaneFormProps = {
|
||||
formError,
|
||||
isExecuting: isExecuting,
|
||||
isSubmitButtonDisabled: !files || files.length === 0,
|
||||
submitButtonText: "Upload",
|
||||
onSubmit,
|
||||
};
|
||||
@@ -192,6 +195,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
|
||||
<RightPaneForm {...props}>
|
||||
<div className="paneMainContent">
|
||||
<Upload
|
||||
key={reducer} // Force re-render on state change
|
||||
label="Select JSON Files"
|
||||
onUpload={updateSelectedFiles}
|
||||
accept="application/json"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
exports[`Upload Items Pane should render Default properly 1`] = `
|
||||
<RightPaneForm
|
||||
formError=""
|
||||
isSubmitButtonDisabled={true}
|
||||
onSubmit={[Function]}
|
||||
submitButtonText="Upload"
|
||||
>
|
||||
@@ -11,6 +12,7 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
||||
>
|
||||
<Upload
|
||||
accept="application/json"
|
||||
key="1"
|
||||
label="Select JSON Files"
|
||||
multiple={true}
|
||||
onUpload={[Function]}
|
||||
|
||||
@@ -35,6 +35,7 @@ export enum StorageKey {
|
||||
DefaultQueryResultsView,
|
||||
AppState,
|
||||
MongoGuidRepresentation,
|
||||
IgnorePartitionKeyOnDocumentUpdate,
|
||||
}
|
||||
|
||||
export const hasRUThresholdBeenConfigured = (): boolean => {
|
||||
|
||||
@@ -24,3 +24,10 @@ export const isVectorSearchEnabled = (): boolean => {
|
||||
(isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLVectorSearch) || isFabricNative())
|
||||
);
|
||||
};
|
||||
|
||||
export const isFullTextSearchPreviewFeaturesEnabled = (): boolean => {
|
||||
return (
|
||||
userContext.apiType === "SQL" &&
|
||||
isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLFullTextSearchPreviewFeatures)
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user