Merge branch 'release' into feat/reactive-actions-run-behaviour

This commit is contained in:
“sneha122” 2025-05-07 13:08:54 +01:00
commit 2e29675876
20 changed files with 132 additions and 33 deletions

View File

@ -413,7 +413,7 @@ export class LightModeTheme implements ColorModeTheme {
}
if (!this.seedIsVeryLight) {
color.oklch.l = 0.97;
color.oklch.l = 0.975;
}
if (this.seedChroma > 0.002) {
@ -785,7 +785,7 @@ export class LightModeTheme implements ColorModeTheme {
private get fgNeutralSubtle() {
const color = this.fgNeutral.clone();
color.oklch.l += 0.12;
color.oklch.l += 0.1;
return color;
}
@ -1063,7 +1063,7 @@ export class LightModeTheme implements ColorModeTheme {
// Slightly subtler version of neutral border, used in outlined buttons
const color = this.bdNeutral.clone();
color.oklch.l += 0.47;
color.oklch.l += 0.35;
return color;
}

View File

@ -358,7 +358,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.03 170)",
).getColors();
expect(bgNeutralSubtle).toEqual("rgb(95.592% 96.251% 95.981%)");
expect(bgNeutralSubtle).toEqual("rgb(96.247% 96.906% 96.636%)");
});
it("should return correct color when seedChroma > 0.01", () => {
@ -366,7 +366,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.1 170)",
).getColors();
expect(bgNeutralSubtle).toEqual("rgb(95.592% 96.251% 95.981%)");
expect(bgNeutralSubtle).toEqual("rgb(96.247% 96.906% 96.636%)");
});
it("should return correct color when chroma < 0.04", () => {
@ -374,7 +374,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.03 170)",
).getColors();
expect(bgNeutralSubtle).toEqual("rgb(95.592% 96.251% 95.981%)");
expect(bgNeutralSubtle).toEqual("rgb(96.247% 96.906% 96.636%)");
});
});
@ -384,7 +384,7 @@ describe("bgNeutralSubtleHover color", () => {
"oklch(0.92 0.1 170)",
).getColors();
expect(bgNeutralSubtleHover).toEqual("rgb(97.164% 97.825% 97.554%)");
expect(bgNeutralSubtleHover).toEqual("rgb(97.82% 98.482% 98.21%)");
});
});
@ -394,7 +394,7 @@ describe("bgNeutralSubtleActive color", () => {
"oklch(0.92 0.1 170)",
).getColors();
expect(bgNeutralSubtleActive).toEqual("rgb(94.286% 94.944% 94.674%)");
expect(bgNeutralSubtleActive).toEqual("rgb(94.939% 95.597% 95.327%)");
});
});
@ -692,7 +692,7 @@ describe("fgNeutralSubtle color", () => {
"oklch(0.45 0.03 60)",
).getColors();
expect(fgNeutralSubtle).toEqual("rgb(43.337% 43.337% 43.337%)");
expect(fgNeutralSubtle).toEqual("rgb(41.086% 41.086% 41.086%)");
});
});

View File

@ -0,0 +1,18 @@
import React from "react";
import BaseControl, {
type ControlProps,
} from "components/formControls/BaseControl";
import type { ControlType } from "constants/PropertyControlConstants";
interface AIChatIntegrationsControlProps extends ControlProps {}
class AIChatIntegrationsControl extends BaseControl<AIChatIntegrationsControlProps> {
getControlType(): ControlType {
return "AI_CHAT_INTEGRATIONS_FORM";
}
public render() {
return <div>AIChatIntegrationsControl</div>;
}
}
export default AIChatIntegrationsControl;

View File

@ -0,0 +1 @@
export { default } from "./AIChatIntegrationsControl";

View File

@ -1627,6 +1627,8 @@ export const PROPERTY_PANE_EMPTY_SEARCH_RESULT_MESSAGE =
"No properties found based on your search";
export const PROPERTY_SEARCH_INPUT_PLACEHOLDER =
"Search for controls, labels etc";
export const PROPERTY_PANE_TITLE_RENAME_DISABLED = () =>
"This widget cannot be renamed";
export const EXPLORER_BETA_ENTITY = () => "BETA";
export const BINDING_WIDGET_WALKTHROUGH_TITLE = () => "Widget properties";
export const BINDING_WIDGET_WALKTHROUGH_DESC = () =>

View File

@ -58,6 +58,8 @@ export const FEATURE_FLAG = {
release_git_package_enabled: "release_git_package_enabled",
license_external_saas_plugins_enabled:
"license_external_saas_plugins_enabled",
release_computation_cache_enabled: "release_computation_cache_enabled",
release_ai_chat_integrations_enabled: "release_ai_chat_integrations_enabled",
} as const;
export type FeatureFlag = keyof typeof FEATURE_FLAG;
@ -106,6 +108,8 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_table_custom_sort_function_enabled: false,
release_git_package_enabled: false,
license_external_saas_plugins_enabled: false,
release_computation_cache_enabled: false,
release_ai_chat_integrations_enabled: false,
};
export const AB_TESTING_EVENT_KEYS = {

View File

@ -0,0 +1 @@
export { default } from "ce/components/formControls/AIChatIntegrationsControl";

View File

@ -23,6 +23,10 @@ import {
getIsCurrentWidgetRecentlyAdded,
getPropertyPaneWidth,
} from "selectors/propertyPaneSelectors";
import {
createMessage,
PROPERTY_PANE_TITLE_RENAME_DISABLED,
} from "ee/constants/messages";
interface PropertyPaneTitleProps {
title: string;
@ -31,6 +35,7 @@ interface PropertyPaneTitleProps {
updatePropertyTitle?: (title: string) => void;
onBackClick?: () => void;
isPanelTitle?: boolean;
isRenameDisabled?: boolean;
actions: Array<{
tooltipContent: string;
icon: ReactElement;
@ -186,22 +191,36 @@ const PropertyPaneTitle = memo(function PropertyPaneTitle(
className="flex-grow"
onKeyDown={handleTabKeyDown}
>
<EditableText
className="flex-grow text-lg font-semibold t--property-pane-title"
defaultValue={name}
editInteractionKind={EditInteractionKind.SINGLE}
fill
hideEditIcon
isEditingDefault={isEditingDefault}
onBlur={!props.isPanelTitle ? updateTitle : undefined}
onBlurEverytime={handleOnBlurEverytime}
onTextChanged={!props.isPanelTitle ? undefined : updateNewTitle}
placeholder={props.title}
savingState={updating ? SavingState.STARTED : SavingState.NOT_STARTED}
underline
valueTransform={!props.isPanelTitle ? removeSpecialChars : undefined}
wrapperRef={containerRef}
/>
{props.isRenameDisabled ? (
<div className="flex-grow text-lg font-semibold t--property-pane-title">
<Tooltip
content={createMessage(PROPERTY_PANE_TITLE_RENAME_DISABLED)}
>
<div>{name}</div>
</Tooltip>
</div>
) : (
<EditableText
className="flex-grow text-lg font-semibold t--property-pane-title"
defaultValue={name}
editInteractionKind={EditInteractionKind.SINGLE}
fill
hideEditIcon
isEditingDefault={isEditingDefault}
onBlur={!props.isPanelTitle ? updateTitle : undefined}
onBlurEverytime={handleOnBlurEverytime}
onTextChanged={!props.isPanelTitle ? undefined : updateNewTitle}
placeholder={props.title}
savingState={
updating ? SavingState.STARTED : SavingState.NOT_STARTED
}
underline
valueTransform={
!props.isPanelTitle ? removeSpecialChars : undefined
}
wrapperRef={containerRef}
/>
)}
</StyledEditableContainer>
{/* ACTIONS */}

View File

@ -287,6 +287,7 @@ function PropertyPaneView(
>
<PropertyPaneTitle
actions={actions}
isRenameDisabled={widgetProperties?.isRenameDisabled}
key={widgetProperties.widgetId}
title={widgetProperties.widgetName}
widgetId={widgetProperties.widgetId}

View File

@ -335,6 +335,10 @@ export const getCurrentPageName = createSelector(
?.pageName,
);
const isModuleWidget = (
config: ReturnType<typeof WidgetFactory.getConfigs>[string],
) => config.type.startsWith("MODULE_WIDGET_");
export const getWidgetCards = createSelector(
getIsAutoLayout,
getIsAnvilLayout,
@ -357,7 +361,7 @@ export const getWidgetCards = createSelector(
return config.widgetName !== "Map" && !config.hideCard;
}
return !config.hideCard;
return !config.hideCard && !isModuleWidget(config);
});
const _cards: WidgetCardProps[] = cards.map((config) => {

View File

@ -56,6 +56,7 @@ import {
AiChatSystemInstructionsControl,
type AiChatSystemInstructionsControlProps,
} from "components/formControls/AIChatSystemInstructionsControl";
import AIChatIntegrationsControl from "ee/components/formControls/AIChatIntegrationsControl";
/**
* NOTE: If you are adding a component that uses FormControl
@ -253,6 +254,14 @@ class FormControlRegistry {
},
},
);
FormControlFactory.registerControlBuilder(
formControlTypes.AI_CHAT_INTEGRATIONS_FORM,
{
buildPropertyControl(controlProps): JSX.Element {
return <AIChatIntegrationsControl {...controlProps} />;
},
},
);
FormControlFactory.registerControlBuilder(
formControlTypes.DATASOURCE_LINK,
{

View File

@ -27,4 +27,5 @@ export default {
DATASOURCE_LINK: "DATASOURCE_LINK",
CUSTOM_ACTIONS_CONFIG_FORM: "CUSTOM_ACTIONS_CONFIG_FORM",
AI_CHAT_SYSTEM_INSTRUCTIONS: "AI_CHAT_SYSTEM_INSTRUCTIONS",
AI_CHAT_INTEGRATIONS_FORM: "AI_CHAT_INTEGRATIONS_FORM",
};

View File

@ -16,6 +16,7 @@ export const AvailableFeaturesToOverride: FeatureFlag[] = [
"release_anvil_enabled",
"release_layout_conversion_enabled",
"license_ai_agent_enabled",
"release_ai_chat_integrations_enabled",
];
export type OverriddenFeatureFlags = Partial<Record<FeatureFlag, boolean>>;

View File

@ -7,6 +7,8 @@ import { APP_MODE } from "entities/App";
import localforage from "localforage";
import loglevel from "loglevel";
import { AppComputationCache } from "./index";
import { WorkerEnv } from "workers/Evaluation/handlers/workerEnv";
import type { FeatureFlags } from "ee/entities/FeatureFlag";
jest.useFakeTimers();
@ -68,6 +70,9 @@ describe("AppComputationCache", () => {
beforeEach(() => {
jest.clearAllMocks();
AppComputationCache.resetInstance();
WorkerEnv.setFeatureFlags({
release_computation_cache_enabled: true,
} as FeatureFlags);
// Now instantiate the singleton after mocks are set up
appComputationCache = AppComputationCache.getInstance();

View File

@ -9,6 +9,7 @@ import {
} from "./types";
import debounce from "lodash/debounce";
import { isFinite, isNumber, isString } from "lodash";
import { WorkerEnv } from "workers/Evaluation/handlers/workerEnv";
interface ICachedData<T> {
value: T;
@ -82,6 +83,12 @@ export class AppComputationCache {
5000,
);
isComputationCacheFeatureEnabled() {
const featureFlags = WorkerEnv.getFeatureFlags();
return featureFlags["release_computation_cache_enabled"] || false;
}
/**
* Check if the computation result should be cached based on the app mode configuration
* @returns - A boolean indicating whether the cache should be enabled for the given app mode
@ -95,7 +102,8 @@ export class AppComputationCache {
if (
!this.isAppModeValid(appMode) ||
!this.isTimestampValid(timestamp) ||
!this.isDSLVersionValid(dslVersion)
!this.isDSLVersionValid(dslVersion) ||
!this.isComputationCacheFeatureEnabled()
) {
return false;
}

View File

@ -1268,7 +1268,12 @@ public class FileUtilsCEImpl implements FileInterface {
@Override
public Mono<Object> reconstructPageFromGitRepo(
String pageName, String branchName, Path baseRepoSuffixPath, Boolean resetToLastCommitRequired) {
String pageName,
String branchName,
Path baseRepoSuffixPath,
Boolean resetToLastCommitRequired,
Boolean useFSGitHandler,
Boolean keepWorkingDirChanges) {
Mono<Object> pageObjectMono;
try {
Mono<Boolean> resetToLastCommit = Mono.just(Boolean.TRUE);
@ -1276,7 +1281,12 @@ public class FileUtilsCEImpl implements FileInterface {
if (Boolean.TRUE.equals(resetToLastCommitRequired)) {
// instead of checking out to last branch we are first cleaning the git repo,
// then checking out to the desired branch
resetToLastCommit = gitExecutor.resetToLastCommit(baseRepoSuffixPath, branchName, false);
if (Boolean.TRUE.equals(useFSGitHandler)) {
resetToLastCommit =
fsGitHandler.resetToLastCommit(baseRepoSuffixPath, branchName, keepWorkingDirChanges);
} else {
resetToLastCommit = gitExecutor.resetToLastCommit(baseRepoSuffixPath, branchName, true);
}
}
pageObjectMono = resetToLastCommit.map(isSwitched -> {

View File

@ -24,6 +24,7 @@ public enum FeatureFlagEnum {
* Feature flag to detect if the RTS git reset is enabled
*/
ab_rts_git_reset_enabled,
release_git_api_contracts_enabled,
// Deprecated CE flags over here
release_git_autocommit_feature_enabled,

View File

@ -80,7 +80,12 @@ public interface FileInterface {
Mono<Object> reconstructPackageJsonFromGitRepository(Path repoSuffix);
Mono<Object> reconstructPageFromGitRepo(
String pageName, String branchName, Path repoSuffixPath, Boolean checkoutRequired);
String pageName,
String branchName,
Path repoSuffixPath,
Boolean checkoutRequired,
Boolean useFSGitHandler,
Boolean keepWorkingDirChanges);
/**
* Once the user connects the existing application to a remote repo, we will initialize the repo with Readme.md -

View File

@ -18,7 +18,7 @@
<dependency>
<groupId>net.snowflake</groupId>
<artifactId>snowflake-jdbc</artifactId>
<version>3.22.0</version>
<version>3.23.1</version>
</dependency>
<dependency>

View File

@ -933,6 +933,9 @@ public class CommonGitFileUtilsCE {
String defaultArtifactId = gitArtifactMetadata.getDefaultArtifactId();
String refName = gitArtifactMetadata.getRefName();
String repoName = gitArtifactMetadata.getRepoName();
Mono<Boolean> useFSGitHandlerMono = featureFlagService.check(FeatureFlagEnum.release_git_api_contracts_enabled);
Mono<Boolean> keepWorkingDirChangesMono =
featureFlagService.check(FeatureFlagEnum.release_git_reset_optimization_enabled);
if (!hasText(workspaceId)) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.WORKSPACE_ID));
@ -957,8 +960,14 @@ public class CommonGitFileUtilsCE {
ArtifactGitFileUtils<?> artifactGitFileUtils = getArtifactBasedFileHelper(artifactType);
Path baseRepoSuffix = artifactGitFileUtils.getRepoSuffixPath(workspaceId, defaultArtifactId, repoName);
Mono<JSONObject> jsonObjectMono = fileUtils
.reconstructPageFromGitRepo(pageDTO.getName(), refName, baseRepoSuffix, isResetToLastCommitRequired)
Mono<JSONObject> jsonObjectMono = Mono.zip(useFSGitHandlerMono, keepWorkingDirChangesMono)
.flatMap(tuple -> fileUtils.reconstructPageFromGitRepo(
pageDTO.getName(),
refName,
baseRepoSuffix,
isResetToLastCommitRequired,
tuple.getT1(),
tuple.getT2()))
.onErrorResume(error -> Mono.error(
new AppsmithException(AppsmithError.GIT_ACTION_FAILED, RECONSTRUCT_PAGE, error.getMessage())))
.map(pageJson -> {