mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-28 13:21:42 +00:00
* First dark theme commits for command bar * Updated theme on sidebar * Updated tabs, sidebar, splash screen * settings theme changes * Dark theme applied to Monaco editor * Dark theme to stored procedures * Fixed sidebar scroll * Updated scroll issue in sidebar * Command bar items fixed * Fixed lint errors * fixed lint errors * settings side panel fixed * Second last iteration for css * Fixed all the issues of css * Updated the theme icon for now on DE to change the theme from portal/DE itself * Formatting issue resolved * Remove CloudShellTerminalComponent changes - revert to master version * Fixed test issue * Fixed formatting issue * Fix tests: update snapshots and revert xterm imports for compatibility * Fix xterm imports in CloudShellTerminalComponent to use @xterm packages * Fix Cloud Shell component imports for compatibility * Update test snapshots * Fix xterm package consistency across all CloudShell components * Fix TypeScript compilation errors in CloudShell components and query Documents - Standardized xterm package imports across CloudShell components to use legacy 'xterm' package - Fixed Terminal type compatibility issues in CommonUtils.tsx - Added type casting for enableQueryControl property in queryDocuments.ts to handle Azure Cosmos SDK interface limitations - Applied code formatting to ensure consistency * Update failing snapshot tests - Updated TreeNodeComponent snapshot tests for loading states - Updated ThroughputInputAutoPilotV3Component snapshots for number formatting changes (10,00,000 -> 1,000,000) - All snapshot tests now pass * Fixed test issue * Fixed test issue * Updated the buttons for theme * Updated the Theme changes based on portal theme changes * Updated review comments * Updated the duplicate code and fixed the fabric react error * Few places styling added and resolving few comments * Fixed errors * Fixed comments * Fixed comments * Fixed comments * Fixed full text policy issue for mongoru accounts * Resolved comments for class Name and few others * Added css for homepage in ru accounts * Final commit with all the feedback issues resolved * Lint error resolved * Updated the review comments and few Ui issues * Resolved review comments and changed header bg and active state color * Moved svg code to different file and imported * css fixed for the hpome page boxed for ru account * Lint errors * Fixed boxes issue in ru accounts * Handled the initial theme from the portal * Updated snap * Update snapshots for TreeNodeComponent and CreateCopyJobScreensProvider tests * Fix duplicate DataExplorerRoot test id causing Playwright strict mode violation * Fix locale-dependent number formatting in ThroughputInputAutoPilotV3Component --------- Co-authored-by: Sakshi Gupta <sakshig+microsoft@microsoft.com> Co-authored-by: Sakshi Gupta <sakshig@microsoft.com>
425 lines
13 KiB
TypeScript
425 lines
13 KiB
TypeScript
import {
|
|
DefaultButton,
|
|
Dropdown,
|
|
IDropdownOption,
|
|
IDropdownStyles,
|
|
IStyleFunctionOrObject,
|
|
ITextFieldStyleProps,
|
|
ITextFieldStyles,
|
|
Label,
|
|
Stack,
|
|
TextField,
|
|
} from "@fluentui/react";
|
|
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;
|
|
onFullTextPathChange: (
|
|
fullTextPolicy: FullTextPolicy,
|
|
fullTextIndexes: FullTextIndex[],
|
|
validationPassed: boolean,
|
|
) => void;
|
|
discardChanges?: boolean;
|
|
onChangesDiscarded?: () => void;
|
|
englishOnly?: boolean;
|
|
}
|
|
|
|
export interface FullTextPolicyData {
|
|
path: string;
|
|
language: string;
|
|
pathError: string;
|
|
}
|
|
|
|
const labelStyles = {
|
|
root: {
|
|
fontSize: 12,
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
};
|
|
|
|
const textFieldStyles: IStyleFunctionOrObject<ITextFieldStyleProps, ITextFieldStyles> = {
|
|
fieldGroup: {
|
|
height: 27,
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
},
|
|
field: {
|
|
fontSize: 12,
|
|
padding: "0 8px",
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
},
|
|
root: {
|
|
selectors: {
|
|
input: {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"input:hover": {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
},
|
|
"input:focus": {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
borderColor: "var(--colorBrandBackground)",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
const dropdownStyles: Partial<IDropdownStyles> = {
|
|
root: {
|
|
width: "40%",
|
|
marginTop: "10px",
|
|
selectors: {
|
|
"&:hover .ms-Dropdown-title": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
},
|
|
"&:hover span.ms-Dropdown-title": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:focus .ms-Dropdown-title": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
},
|
|
"&:focus span.ms-Dropdown-title": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
},
|
|
},
|
|
label: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
dropdown: {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
title: {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
selectors: {
|
|
"&:hover": {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:focus": {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:hover .ms-Dropdown-titleText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:focus .ms-Dropdown-titleText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"& .ms-Dropdown-titleText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&.ms-Dropdown-title--hasPlaceholder": {
|
|
color: "var(--colorNeutralForeground2)",
|
|
},
|
|
},
|
|
},
|
|
errorMessage: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
caretDown: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
callout: {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
border: "1px solid var(--colorNeutralStroke1)",
|
|
},
|
|
dropdownItems: {
|
|
backgroundColor: "var(--colorNeutralBackground2)",
|
|
},
|
|
dropdownItem: {
|
|
backgroundColor: "transparent",
|
|
color: "var(--colorNeutralForeground1)",
|
|
minHeight: "36px",
|
|
lineHeight: "36px",
|
|
selectors: {
|
|
"&:hover": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:hover .ms-Dropdown-optionText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:focus": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:active": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"& .ms-Dropdown-optionText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
},
|
|
},
|
|
dropdownItemSelected: {
|
|
backgroundColor: "rgba(255, 255, 255, 0.08)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
minHeight: "36px",
|
|
lineHeight: "36px",
|
|
selectors: {
|
|
"&:hover": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:hover .ms-Dropdown-optionText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:focus": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"&:active": {
|
|
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
"& .ms-Dropdown-optionText": {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
},
|
|
},
|
|
dropdownOptionText: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
dropdownItemHeader: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
},
|
|
};
|
|
|
|
export const FullTextPoliciesComponent: React.FunctionComponent<FullTextPoliciesComponentProps> = ({
|
|
fullTextPolicy,
|
|
onFullTextPathChange,
|
|
discardChanges,
|
|
onChangesDiscarded,
|
|
englishOnly,
|
|
}): JSX.Element => {
|
|
const getFullTextPathError = (path: string, index?: number): string => {
|
|
let error = "";
|
|
if (!path) {
|
|
error = "Full text path should not be empty";
|
|
}
|
|
if (
|
|
index >= 0 &&
|
|
fullTextPathData?.find(
|
|
(fullTextPath: FullTextPolicyData, dataIndex: number) => dataIndex !== index && fullTextPath.path === path,
|
|
)
|
|
) {
|
|
error = "Full text path is already defined";
|
|
}
|
|
return error;
|
|
};
|
|
|
|
const initializeData = (fullTextPolicy: FullTextPolicy): FullTextPolicyData[] => {
|
|
if (!fullTextPolicy) {
|
|
fullTextPolicy = { defaultLanguage: getFullTextLanguageOptions()[0].key as never, fullTextPaths: [] };
|
|
}
|
|
|
|
return fullTextPolicy.fullTextPaths.map((fullTextPath: FullTextPath) => ({
|
|
...fullTextPath,
|
|
pathError: getFullTextPathError(fullTextPath.path),
|
|
}));
|
|
};
|
|
|
|
const [fullTextPathData, setFullTextPathData] = React.useState<FullTextPolicyData[]>(initializeData(fullTextPolicy));
|
|
const [defaultLanguage, setDefaultLanguage] = React.useState<string>(
|
|
fullTextPolicy ? fullTextPolicy.defaultLanguage : (getFullTextLanguageOptions()[0].key as never),
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
propagateData();
|
|
}, [fullTextPathData, defaultLanguage]);
|
|
|
|
React.useEffect(() => {
|
|
if (discardChanges) {
|
|
setFullTextPathData(initializeData(fullTextPolicy));
|
|
setDefaultLanguage(fullTextPolicy.defaultLanguage);
|
|
onChangesDiscarded();
|
|
}
|
|
}, [discardChanges]);
|
|
|
|
const propagateData = () => {
|
|
const newFullTextPolicy: FullTextPolicy = {
|
|
defaultLanguage: defaultLanguage,
|
|
fullTextPaths: fullTextPathData.map((policy: FullTextPolicyData) => ({
|
|
path: policy.path,
|
|
language: policy.language,
|
|
})),
|
|
};
|
|
const fullTextIndexes: FullTextIndex[] = fullTextPathData.map((policy) => ({
|
|
path: policy.path,
|
|
}));
|
|
const validationPassed = fullTextPathData.every((policy: FullTextPolicyData) => policy.pathError === "");
|
|
onFullTextPathChange(newFullTextPolicy, fullTextIndexes, validationPassed);
|
|
};
|
|
|
|
const onFullTextPathValueChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const value = event.target.value.trim();
|
|
const fullTextPaths = [...fullTextPathData];
|
|
if (!fullTextPaths[index]?.path && !value.startsWith("/")) {
|
|
fullTextPaths[index].path = "/" + value;
|
|
} else {
|
|
fullTextPaths[index].path = value;
|
|
}
|
|
fullTextPaths[index].pathError = getFullTextPathError(value, index);
|
|
setFullTextPathData(fullTextPaths);
|
|
};
|
|
|
|
const onFullTextPathPolicyChange = (index: number, option: IDropdownOption): void => {
|
|
const policies = [...fullTextPathData];
|
|
policies[index].language = option.key as never;
|
|
setFullTextPathData(policies);
|
|
};
|
|
|
|
const onAdd = () => {
|
|
setFullTextPathData([
|
|
...fullTextPathData,
|
|
{
|
|
path: "",
|
|
language: defaultLanguage,
|
|
pathError: getFullTextPathError(""),
|
|
},
|
|
]);
|
|
};
|
|
|
|
const onDelete = (index: number) => {
|
|
const policies = fullTextPathData.filter((_uniqueKey, j) => index !== j);
|
|
setFullTextPathData(policies);
|
|
};
|
|
|
|
return (
|
|
<Stack tokens={{ childrenGap: 4 }}>
|
|
<Stack style={{ marginBottom: 10 }}>
|
|
<Label styles={labelStyles}>Default language</Label>
|
|
<Dropdown
|
|
required={true}
|
|
styles={dropdownStyles}
|
|
options={getFullTextLanguageOptions(englishOnly)}
|
|
selectedKey={defaultLanguage}
|
|
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
|
|
setDefaultLanguage(option.key as never)
|
|
}
|
|
></Dropdown>
|
|
</Stack>
|
|
{fullTextPathData &&
|
|
fullTextPathData.length > 0 &&
|
|
fullTextPathData.map((fullTextPolicy: FullTextPolicyData, index: number) => (
|
|
<CollapsibleSectionComponent
|
|
key={index}
|
|
isExpandedByDefault={true}
|
|
title={`Full text path ${index + 1}`}
|
|
showDelete={true}
|
|
onDelete={() => onDelete(index)}
|
|
>
|
|
<Stack horizontal tokens={{ childrenGap: 4 }}>
|
|
<Stack
|
|
styles={{
|
|
root: {
|
|
margin: "0 0 6px 20px !important",
|
|
paddingLeft: 20,
|
|
width: "80%",
|
|
borderLeft: "1px solid",
|
|
},
|
|
}}
|
|
>
|
|
<Stack>
|
|
<Label styles={labelStyles}>Path</Label>
|
|
<TextField
|
|
id={`full-text-policy-path-${index + 1}`}
|
|
required={true}
|
|
placeholder="/fullTextPath1"
|
|
styles={textFieldStyles}
|
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onFullTextPathValueChange(index, event)}
|
|
value={fullTextPolicy.path || ""}
|
|
errorMessage={fullTextPolicy.pathError}
|
|
/>
|
|
</Stack>
|
|
<Stack>
|
|
<Label styles={labelStyles}>Language</Label>
|
|
<Dropdown
|
|
required={true}
|
|
styles={dropdownStyles}
|
|
options={getFullTextLanguageOptions(englishOnly)}
|
|
selectedKey={fullTextPolicy.language}
|
|
onChange={(_event: React.FormEvent<HTMLDivElement>, option: IDropdownOption) =>
|
|
onFullTextPathPolicyChange(index, option)
|
|
}
|
|
></Dropdown>
|
|
</Stack>
|
|
</Stack>
|
|
</Stack>
|
|
</CollapsibleSectionComponent>
|
|
))}
|
|
<DefaultButton
|
|
id={`add-vector-policy`}
|
|
styles={{
|
|
root: {
|
|
maxWidth: 170,
|
|
fontSize: 12,
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "transparent",
|
|
borderColor: "var(--colorNeutralStroke1)",
|
|
},
|
|
rootHovered: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "transparent",
|
|
borderColor: "var(--colorNeutralForeground1)",
|
|
},
|
|
rootPressed: {
|
|
color: "var(--colorNeutralForeground1)",
|
|
backgroundColor: "transparent",
|
|
borderColor: "var(--colorNeutralForeground1)",
|
|
},
|
|
rootDisabled: {
|
|
backgroundColor: "transparent",
|
|
},
|
|
}}
|
|
onClick={onAdd}
|
|
>
|
|
Add full text path
|
|
</DefaultButton>
|
|
</Stack>
|
|
);
|
|
};
|
|
|
|
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;
|
|
};
|