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

View File

@ -358,7 +358,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.03 170)", "oklch(0.92 0.03 170)",
).getColors(); ).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", () => { it("should return correct color when seedChroma > 0.01", () => {
@ -366,7 +366,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.1 170)", "oklch(0.92 0.1 170)",
).getColors(); ).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", () => { it("should return correct color when chroma < 0.04", () => {
@ -374,7 +374,7 @@ describe("bgNeutralSubtle color", () => {
"oklch(0.92 0.03 170)", "oklch(0.92 0.03 170)",
).getColors(); ).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)", "oklch(0.92 0.1 170)",
).getColors(); ).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)", "oklch(0.92 0.1 170)",
).getColors(); ).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)", "oklch(0.45 0.03 60)",
).getColors(); ).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"; "No properties found based on your search";
export const PROPERTY_SEARCH_INPUT_PLACEHOLDER = export const PROPERTY_SEARCH_INPUT_PLACEHOLDER =
"Search for controls, labels etc"; "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 EXPLORER_BETA_ENTITY = () => "BETA";
export const BINDING_WIDGET_WALKTHROUGH_TITLE = () => "Widget properties"; export const BINDING_WIDGET_WALKTHROUGH_TITLE = () => "Widget properties";
export const BINDING_WIDGET_WALKTHROUGH_DESC = () => export const BINDING_WIDGET_WALKTHROUGH_DESC = () =>

View File

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

View File

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

View File

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

View File

@ -56,6 +56,7 @@ import {
AiChatSystemInstructionsControl, AiChatSystemInstructionsControl,
type AiChatSystemInstructionsControlProps, type AiChatSystemInstructionsControlProps,
} from "components/formControls/AIChatSystemInstructionsControl"; } from "components/formControls/AIChatSystemInstructionsControl";
import AIChatIntegrationsControl from "ee/components/formControls/AIChatIntegrationsControl";
/** /**
* NOTE: If you are adding a component that uses FormControl * 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( FormControlFactory.registerControlBuilder(
formControlTypes.DATASOURCE_LINK, formControlTypes.DATASOURCE_LINK,
{ {

View File

@ -27,4 +27,5 @@ export default {
DATASOURCE_LINK: "DATASOURCE_LINK", DATASOURCE_LINK: "DATASOURCE_LINK",
CUSTOM_ACTIONS_CONFIG_FORM: "CUSTOM_ACTIONS_CONFIG_FORM", CUSTOM_ACTIONS_CONFIG_FORM: "CUSTOM_ACTIONS_CONFIG_FORM",
AI_CHAT_SYSTEM_INSTRUCTIONS: "AI_CHAT_SYSTEM_INSTRUCTIONS", 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_anvil_enabled",
"release_layout_conversion_enabled", "release_layout_conversion_enabled",
"license_ai_agent_enabled", "license_ai_agent_enabled",
"release_ai_chat_integrations_enabled",
]; ];
export type OverriddenFeatureFlags = Partial<Record<FeatureFlag, boolean>>; export type OverriddenFeatureFlags = Partial<Record<FeatureFlag, boolean>>;

View File

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

View File

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

View File

@ -1268,7 +1268,12 @@ public class FileUtilsCEImpl implements FileInterface {
@Override @Override
public Mono<Object> reconstructPageFromGitRepo( 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; Mono<Object> pageObjectMono;
try { try {
Mono<Boolean> resetToLastCommit = Mono.just(Boolean.TRUE); Mono<Boolean> resetToLastCommit = Mono.just(Boolean.TRUE);
@ -1276,7 +1281,12 @@ public class FileUtilsCEImpl implements FileInterface {
if (Boolean.TRUE.equals(resetToLastCommitRequired)) { if (Boolean.TRUE.equals(resetToLastCommitRequired)) {
// instead of checking out to last branch we are first cleaning the git repo, // instead of checking out to last branch we are first cleaning the git repo,
// then checking out to the desired branch // 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 -> { pageObjectMono = resetToLastCommit.map(isSwitched -> {

View File

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

View File

@ -80,7 +80,12 @@ public interface FileInterface {
Mono<Object> reconstructPackageJsonFromGitRepository(Path repoSuffix); Mono<Object> reconstructPackageJsonFromGitRepository(Path repoSuffix);
Mono<Object> reconstructPageFromGitRepo( 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 - * 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> <dependency>
<groupId>net.snowflake</groupId> <groupId>net.snowflake</groupId>
<artifactId>snowflake-jdbc</artifactId> <artifactId>snowflake-jdbc</artifactId>
<version>3.22.0</version> <version>3.23.1</version>
</dependency> </dependency>
<dependency> <dependency>

View File

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