Compare commits

...

3 Commits

Author SHA1 Message Date
asier-isayas
d35ae7e0f1 Add French, German, and Spanish to Full Text Search (Update container only) (#2228) (#2247)
* Add multiple languages for Full Text Search Policy

* fix tests

* show multiple languages for multi language support enabled accounts

* addressed comments

---------

Co-authored-by: Asier Isayas <aisayas@microsoft.com>
2025-11-05 09:13:08 -08:00
sunghyunkang1111
d0d615a85a Added infobox to advanced settings (#2231)
* Added infobox to advanced settings

* Update tooltip message and test snap
2025-10-21 13:49:52 -05:00
Dmitry Shilov
2996120235 fix: Clean file input after uploading files (#2189)
* fix: Clean file input after uploading files

- Enhance file upload component to trigger re-renders on state changes

* fix: Clean file input after uploading files

- Enhance file upload component to trigger re-renders on state changes
2025-10-20 21:49:41 +02:00
9 changed files with 112 additions and 36 deletions

View File

@@ -89,7 +89,7 @@ export class CapabilityNames {
public static readonly EnableMongo: string = "EnableMongo"; public static readonly EnableMongo: string = "EnableMongo";
public static readonly EnableServerless: string = "EnableServerless"; public static readonly EnableServerless: string = "EnableServerless";
public static readonly EnableNoSQLVectorSearch: string = "EnableNoSQLVectorSearch"; public static readonly EnableNoSQLVectorSearch: string = "EnableNoSQLVectorSearch";
public static readonly EnableNoSQLFullTextSearch: string = "EnableNoSQLFullTextSearch"; public static readonly EnableNoSQLFullTextSearchPreviewFeatures: string = "EnableNoSQLFullTextSearchPreviewFeatures";
} }
export enum CapacityMode { export enum CapacityMode {

View File

@@ -12,6 +12,7 @@ import {
import { FullTextIndex, FullTextPath, FullTextPolicy } from "Contracts/DataModels"; import { FullTextIndex, FullTextPath, FullTextPolicy } from "Contracts/DataModels";
import { CollapsibleSectionComponent } from "Explorer/Controls/CollapsiblePanel/CollapsibleSectionComponent"; import { CollapsibleSectionComponent } from "Explorer/Controls/CollapsiblePanel/CollapsibleSectionComponent";
import * as React from "react"; import * as React from "react";
import { isFullTextSearchPreviewFeaturesEnabled } from "Utils/CapabilityUtils";
export interface FullTextPoliciesComponentProps { export interface FullTextPoliciesComponentProps {
fullTextPolicy: FullTextPolicy; fullTextPolicy: FullTextPolicy;
@@ -22,6 +23,7 @@ export interface FullTextPoliciesComponentProps {
) => void; ) => void;
discardChanges?: boolean; discardChanges?: boolean;
onChangesDiscarded?: () => void; onChangesDiscarded?: () => void;
englishOnly?: boolean;
} }
export interface FullTextPolicyData { export interface FullTextPolicyData {
@@ -66,6 +68,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
onFullTextPathChange, onFullTextPathChange,
discardChanges, discardChanges,
onChangesDiscarded, onChangesDiscarded,
englishOnly,
}): JSX.Element => { }): JSX.Element => {
const getFullTextPathError = (path: string, index?: number): string => { const getFullTextPathError = (path: string, index?: number): string => {
let error = ""; let error = "";
@@ -87,6 +90,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
if (!fullTextPolicy) { if (!fullTextPolicy) {
fullTextPolicy = { defaultLanguage: getFullTextLanguageOptions()[0].key as never, fullTextPaths: [] }; fullTextPolicy = { defaultLanguage: getFullTextLanguageOptions()[0].key as never, fullTextPaths: [] };
} }
return fullTextPolicy.fullTextPaths.map((fullTextPath: FullTextPath) => ({ return fullTextPolicy.fullTextPaths.map((fullTextPath: FullTextPath) => ({
...fullTextPath, ...fullTextPath,
pathError: getFullTextPathError(fullTextPath.path), pathError: getFullTextPathError(fullTextPath.path),
@@ -166,7 +170,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
<Dropdown <Dropdown
required={true} required={true}
styles={dropdownStyles} styles={dropdownStyles}
options={getFullTextLanguageOptions()} options={getFullTextLanguageOptions(englishOnly)}
selectedKey={defaultLanguage} selectedKey={defaultLanguage}
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) => onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
setDefaultLanguage(option.key as never) setDefaultLanguage(option.key as never)
@@ -211,7 +215,7 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
<Dropdown <Dropdown
required={true} required={true}
styles={dropdownStyles} styles={dropdownStyles}
options={getFullTextLanguageOptions()} options={getFullTextLanguageOptions(englishOnly)}
selectedKey={fullTextPolicy.language} selectedKey={fullTextPolicy.language}
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) => onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
onFullTextPathPolicyChange(index, option) onFullTextPathPolicyChange(index, option)
@@ -229,11 +233,30 @@ export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPolicies
); );
}; };
export const getFullTextLanguageOptions = (): IDropdownOption[] => { export const getFullTextLanguageOptions = (englishOnly?: boolean): IDropdownOption[] => {
return [ const multiLanguageSupportEnabled: boolean = isFullTextSearchPreviewFeaturesEnabled() && !englishOnly;
const fullTextLanguageOptions: IDropdownOption[] = [
{ {
key: "en-US", key: "en-US",
text: "English (US)", text: "English (US)",
}, },
...(multiLanguageSupportEnabled
? [
{
key: "fr-FR",
text: "French",
},
{
key: "de-DE",
text: "German",
},
{
key: "es-ES",
text: "Spanish",
},
]
: []),
]; ];
return fullTextLanguageOptions;
}; };

View File

@@ -893,6 +893,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
) => { ) => {
this.setState({ fullTextPolicy, fullTextIndexes, fullTextPolicyValidated }); this.setState({ fullTextPolicy, fullTextIndexes, fullTextPolicyValidated });
}} }}
// Remove when multi language support on container create issue is fixed
englishOnly={true}
/> />
</Stack> </Stack>
</Stack> </Stack>

View File

@@ -516,6 +516,7 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
} }
> >
<FullTextPoliciesComponent <FullTextPoliciesComponent
englishOnly={true}
fullTextPolicy={ fullTextPolicy={
{ {
"defaultLanguage": "en-US", "defaultLanguage": "en-US",

View File

@@ -13,6 +13,7 @@ import {
IToggleStyles, IToggleStyles,
Position, Position,
SpinButton, SpinButton,
Stack,
Toggle, Toggle,
} from "@fluentui/react"; } from "@fluentui/react";
import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, makeStyles } from "@fluentui/react-components"; import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, makeStyles } from "@fluentui/react-components";
@@ -1163,14 +1164,20 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
</AccordionHeader> </AccordionHeader>
<AccordionPanel> <AccordionPanel>
<div className={styles.settingsSectionContainer}> <div className={styles.settingsSectionContainer}>
<Checkbox <Stack horizontal verticalAlign="center" tokens={{ childrenGap: 4 }}>
styles={{ label: { padding: 0 } }} <Checkbox
className="padding" styles={{ label: { padding: 0 } }}
ariaLabel="Ignore partition key on document update" className="padding"
checked={ignorePartitionKeyOnDocumentUpdate} ariaLabel="Ignore partition key on document update"
onChange={handleOnIgnorePartitionKeyOnDocumentUpdateChange} checked={ignorePartitionKeyOnDocumentUpdate}
label="Ignore partition key on document update" 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> </div>
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>

View File

@@ -589,20 +589,35 @@ exports[`Settings Pane should render Default properly 1`] = `
<div <div
className="___1dfa554_0000000 fo7qwa0" className="___1dfa554_0000000 fo7qwa0"
> >
<StyledCheckboxBase <Stack
ariaLabel="Ignore partition key on document update" horizontal={true}
checked={false} tokens={
className="padding"
label="Ignore partition key on document update"
onChange={[Function]}
styles={
{ {
"label": { "childrenGap": 4,
"padding": 0,
},
} }
} }
/> 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> </div>
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>
@@ -883,20 +898,35 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
<div <div
className="___1dfa554_0000000 fo7qwa0" className="___1dfa554_0000000 fo7qwa0"
> >
<StyledCheckboxBase <Stack
ariaLabel="Ignore partition key on document update" horizontal={true}
checked={false} tokens={
className="padding"
label="Ignore partition key on document update"
onChange={[Function]}
styles={
{ {
"label": { "childrenGap": 4,
"padding": 0,
},
} }
} }
/> 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> </div>
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>

View File

@@ -13,7 +13,7 @@ import {
import { Upload } from "Common/Upload/Upload"; import { Upload } from "Common/Upload/Upload";
import { UploadDetailsRecord } from "Contracts/ViewModels"; import { UploadDetailsRecord } from "Contracts/ViewModels";
import { logConsoleError } from "Utils/NotificationConsoleUtils"; 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 { getErrorMessage } from "../../Tables/Utilities";
import { useSelectedNode } from "../../useSelectedNode"; import { useSelectedNode } from "../../useSelectedNode";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
@@ -57,6 +57,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]); const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
const [formError, setFormError] = useState<string>(""); const [formError, setFormError] = useState<string>("");
const [isExecuting, setIsExecuting] = useState<boolean>(); const [isExecuting, setIsExecuting] = useState<boolean>();
const [reducer, setReducer] = useReducer((x) => x + 1, 1);
const onSubmit = () => { const onSubmit = () => {
setFormError(""); setFormError("");
@@ -75,6 +76,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
(uploadDetails) => { (uploadDetails) => {
setUploadFileData(uploadDetails.data); setUploadFileData(uploadDetails.data);
setFiles(undefined); setFiles(undefined);
setReducer(); // Trigger a re-render to update the UI with new upload details
// Emit the upload details to the parent component // Emit the upload details to the parent component
onUpload && onUpload(uploadDetails.data); onUpload && onUpload(uploadDetails.data);
}, },
@@ -95,6 +97,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
const props: RightPaneFormProps = { const props: RightPaneFormProps = {
formError, formError,
isExecuting: isExecuting, isExecuting: isExecuting,
isSubmitButtonDisabled: !files || files.length === 0,
submitButtonText: "Upload", submitButtonText: "Upload",
onSubmit, onSubmit,
}; };
@@ -192,6 +195,7 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpl
<RightPaneForm {...props}> <RightPaneForm {...props}>
<div className="paneMainContent"> <div className="paneMainContent">
<Upload <Upload
key={reducer} // Force re-render on state change
label="Select JSON Files" label="Select JSON Files"
onUpload={updateSelectedFiles} onUpload={updateSelectedFiles}
accept="application/json" accept="application/json"

View File

@@ -3,6 +3,7 @@
exports[`Upload Items Pane should render Default properly 1`] = ` exports[`Upload Items Pane should render Default properly 1`] = `
<RightPaneForm <RightPaneForm
formError="" formError=""
isSubmitButtonDisabled={true}
onSubmit={[Function]} onSubmit={[Function]}
submitButtonText="Upload" submitButtonText="Upload"
> >
@@ -11,6 +12,7 @@ exports[`Upload Items Pane should render Default properly 1`] = `
> >
<Upload <Upload
accept="application/json" accept="application/json"
key="1"
label="Select JSON Files" label="Select JSON Files"
multiple={true} multiple={true}
onUpload={[Function]} onUpload={[Function]}

View File

@@ -24,3 +24,10 @@ export const isVectorSearchEnabled = (): boolean => {
(isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLVectorSearch) || isFabricNative()) (isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLVectorSearch) || isFabricNative())
); );
}; };
export const isFullTextSearchPreviewFeaturesEnabled = (): boolean => {
return (
userContext.apiType === "SQL" &&
isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLFullTextSearchPreviewFeatures)
);
};