chore: Added context switching for pages pane (#29100)

This commit is contained in:
albinAppsmith 2023-11-28 18:16:43 +05:30 committed by GitHub
parent 2fa9f5fb70
commit 228548629b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 618 additions and 156 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -2274,6 +2274,10 @@ export const PAGES_PANE_TEXTS = {
queries_tab: () => "Queries",
js_tab: () => "JS",
ui_tab: () => "UI",
query_blank_state: () => "Write your first query or API to access data",
js_blank_state: () => "Use JS to transform your data or write business logic",
query_blank_button: () => "New Query/API",
js_blank_button: () => "New JS Object",
};
export const PARTIAL_IMPORT_EXPORT = {

View File

@ -15,6 +15,7 @@ import {
JS_COLLECTION_EDITOR_PATH,
JS_COLLECTION_ID_PATH,
PROVIDER_TEMPLATE_PATH,
QUERIES_EDITOR_BASE_PATH,
QUERIES_EDITOR_ID_PATH,
WIDGETS_EDITOR_BASE_PATH,
WIDGETS_EDITOR_ID_PATH,
@ -39,6 +40,8 @@ import ProviderTemplates from "pages/Editor/APIEditor/ProviderTemplates";
import GeneratePage from "pages/Editor/GeneratePage";
import type { RouteProps } from "react-router";
import { useIsAppSidebarEnabled } from "navigation/featureFlagHooks";
import { JSBlankState } from "../../../../../pages/Editor/JSEditor/JSBlankState";
import { QueriesBlankState } from "../../../../../pages/Editor/QueryEditor/QueriesBlankState";
export interface RouteReturnType extends RouteProps {
key: string;
@ -87,6 +90,12 @@ function useRoutes(path: string): RouteReturnType[] {
exact: true,
path: `${path}${API_EDITOR_ID_PATH}`,
},
{
key: "QueryEditorList",
component: QueriesBlankState,
exact: true,
path: `${path}${QUERIES_EDITOR_BASE_PATH}`,
},
{
key: "QueryEditor",
component: QueryEditor,
@ -94,8 +103,8 @@ function useRoutes(path: string): RouteReturnType[] {
path: `${path}${QUERIES_EDITOR_ID_PATH}`,
},
{
key: "JSEditor Collection",
component: JSEditor,
key: "JSEditorList",
component: JSBlankState,
exact: true,
path: `${path}${JS_COLLECTION_EDITOR_PATH}`,
},

View File

@ -13,7 +13,6 @@ import {
CURL_IMPORT_PAGE_PATH,
GENERATE_TEMPLATE_FORM_PATH,
INTEGRATION_EDITOR_PATH,
JS_COLLECTION_EDITOR_PATH,
JS_COLLECTION_ID_PATH,
PROVIDER_TEMPLATE_PATH,
QUERIES_EDITOR_ID_PATH,
@ -69,11 +68,6 @@ function EditorRoutes() {
exact
path={`${path}${QUERIES_EDITOR_ID_PATH}`}
/>
<SentryRoute
component={JSEditor}
exact
path={`${path}${JS_COLLECTION_EDITOR_PATH}`}
/>
<SentryRoute
component={JSEditor}
exact

View File

@ -55,13 +55,19 @@ import { PluginPackageName } from "entities/Action";
import { FocusEntity } from "navigation/FocusEntity";
import { SelectionRequestType } from "sagas/WidgetSelectUtils";
import { getExplorerWidth } from "selectors/explorerSelector";
import { getJSPaneConfigSelectedTab } from "selectors/jsPaneSelectors";
import {
getFirstJSObjectId,
getJSPaneConfigSelectedTab,
} from "selectors/jsPaneSelectors";
import {
getFocusablePropertyPaneField,
getPropertyPaneWidth,
getSelectedPropertyPanel,
} from "selectors/propertyPaneSelectors";
import { getQueryPaneConfigSelectedTabIndex } from "selectors/queryPaneSelectors";
import {
getFirstQueryId,
getQueryPaneConfigSelectedTabIndex,
} from "selectors/queryPaneSelectors";
import { getDebuggerContext } from "selectors/debuggerSelectors";
import { setDebuggerContext } from "actions/debuggerActions";
import { DefaultDebuggerContext } from "reducers/uiReducers/debuggerReducer";
@ -71,8 +77,16 @@ import {
getCurrentAppUrl,
getCurrentPageUrl,
getSelectedDatasourceId,
getSelectedJSObjectId,
getSelectedQueryId,
} from "./FocusSelectors";
import { setSelectedDatasource, setPageUrl, setAppUrl } from "./FocusSetters";
import {
setSelectedDatasource,
setSelectedJSObject,
setPageUrl,
setAppUrl,
setSelectedQuery,
} from "./FocusSetters";
import { getFirstDatasourceId } from "../selectors/datasourceSelectors";
export enum FocusElement {
@ -99,6 +113,8 @@ export enum FocusElement {
InputField = "InputField",
PageUrl = "PageUrl",
AppUrl = "AppUrl",
SelectedQuery = "SelectedQuery",
SelectedJSObject = "SelectedJSObject",
}
export enum ConfigType {
@ -276,24 +292,6 @@ export const FocusElementsConfig: Record<FocusEntity, Config[]> = {
setter: setQueryPaneConfigSelectedTabIndex,
defaultValue: 0,
},
],
[FocusEntity.PROPERTY_PANE]: [
{
type: ConfigType.Redux,
name: FocusElement.PropertyTabs,
selector: getWidgetSelectedPropertyTabIndex,
setter: setWidgetSelectedPropertyTabIndex,
defaultValue: 0,
},
{
type: ConfigType.Redux,
name: FocusElement.PropertyField,
selector: getFocusablePropertyPaneField,
setter: setFocusablePropertyPaneField,
defaultValue: "",
},
],
[FocusEntity.API]: [
{
type: ConfigType.Redux,
name: FocusElement.ApiPaneConfigTabs,
@ -319,6 +317,23 @@ export const FocusElementsConfig: Record<FocusEntity, Config[]> = {
setter: setApiRightPaneSelectedTab,
},
],
[FocusEntity.PROPERTY_PANE]: [
{
type: ConfigType.Redux,
name: FocusElement.PropertyTabs,
selector: getWidgetSelectedPropertyTabIndex,
setter: setWidgetSelectedPropertyTabIndex,
defaultValue: 0,
},
{
type: ConfigType.Redux,
name: FocusElement.PropertyField,
selector: getFocusablePropertyPaneField,
setter: setFocusablePropertyPaneField,
defaultValue: "",
},
],
[FocusEntity.API]: [],
[FocusEntity.DEBUGGER]: [
{
type: ConfigType.Redux,
@ -330,4 +345,22 @@ export const FocusElementsConfig: Record<FocusEntity, Config[]> = {
],
[FocusEntity.LIBRARY]: [],
[FocusEntity.SETTINGS]: [],
[FocusEntity.QUERY_LIST]: [
{
type: ConfigType.URL,
name: FocusElement.SelectedQuery,
selector: getSelectedQueryId,
setter: setSelectedQuery,
defaultValue: getFirstQueryId,
},
],
[FocusEntity.JS_OBJECT_LIST]: [
{
type: ConfigType.URL,
name: FocusElement.SelectedJSObject,
selector: getSelectedJSObjectId,
setter: setSelectedJSObject,
defaultValue: getFirstJSObjectId,
},
],
};

View File

@ -21,10 +21,19 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/queries",
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/api/myApiId",
expected: {
entity: FocusEntity.API,
entity: FocusEntity.QUERY,
id: "myApiId",
pageId: "myPageId",
appState: AppState.PAGES,
@ -39,6 +48,42 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/jsObjects",
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/jsObjects/myJSId",
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/datasource",
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
pageId: "myPageId",
appState: AppState.DATA,
},
},
{
path: "/applications/myAppId/pages/myPageId/edit/datasources/myDatasourceId",
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
pageId: "myPageId",
appState: AppState.DATA,
},
},
];
const pageSlugCases = [
{
@ -59,10 +104,19 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/app/eval/page1-myPageId/edit/queries",
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/eval/page1-myPageId/edit/api/myApiId",
expected: {
entity: FocusEntity.API,
entity: FocusEntity.QUERY,
id: "myApiId",
pageId: "myPageId",
appState: AppState.PAGES,
@ -77,6 +131,42 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/app/eval/page1-myPageId/edit/jsObjects",
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/eval/page1-myPageId/edit/jsObjects/myJSId",
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/eval/page1-myPageId/edit/datasource",
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
pageId: "myPageId",
appState: AppState.DATA,
},
},
{
path: "/app/eval/page1-myPageId/edit/datasources/myDatasourceId",
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
pageId: "myPageId",
appState: AppState.DATA,
},
},
];
const customSlugCases = [
{
@ -97,10 +187,19 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/queries",
expected: {
entity: FocusEntity.QUERY_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/api/myApiId",
expected: {
entity: FocusEntity.API,
entity: FocusEntity.QUERY,
id: "myApiId",
pageId: "myPageId",
appState: AppState.PAGES,
@ -115,6 +214,42 @@ describe("identifyEntityFromPath", () => {
appState: AppState.PAGES,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/jsObjects",
expected: {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/jsObjects/myJSId",
expected: {
entity: FocusEntity.JS_OBJECT,
id: "myJSId",
pageId: "myPageId",
appState: AppState.PAGES,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/datasource",
expected: {
entity: FocusEntity.DATASOURCE_LIST,
id: "",
pageId: "myPageId",
appState: AppState.DATA,
},
},
{
path: "/app/myCustomSlug-myPageId/edit/datasources/myDatasourceId",
expected: {
entity: FocusEntity.DATASOURCE,
id: "myDatasourceId",
pageId: "myPageId",
appState: AppState.DATA,
},
},
];
const cases = oldUrlCases.concat(pageSlugCases.concat(customSlugCases));

View File

@ -25,7 +25,9 @@ export enum FocusEntity {
DATASOURCE = "DATASOURCE",
DEBUGGER = "DEBUGGER",
QUERY = "QUERY",
QUERY_LIST = "QUERY_LIST",
JS_OBJECT = "JS_OBJECT",
JS_OBJECT_LIST = "JS_OBJECT_LIST",
PROPERTY_PANE = "PROPERTY_PANE",
NONE = "NONE",
APP_STATE = "APP_STATE",
@ -36,6 +38,8 @@ export enum FocusEntity {
export const FocusStoreHierarchy: Partial<Record<FocusEntity, FocusEntity>> = {
[FocusEntity.PROPERTY_PANE]: FocusEntity.CANVAS,
[FocusEntity.DATASOURCE]: FocusEntity.DATASOURCE_LIST,
[FocusEntity.JS_OBJECT]: FocusEntity.JS_OBJECT_LIST,
[FocusEntity.QUERY]: FocusEntity.QUERY_LIST,
};
export interface FocusEntityInfo {
@ -109,7 +113,7 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
};
}
return {
entity: FocusEntity.API,
entity: FocusEntity.QUERY,
id: match.params.apiId,
pageId: match.params.pageId,
appState: AppState.PAGES,
@ -172,6 +176,22 @@ export function identifyEntityFromPath(path: string): FocusEntityInfo {
appState: AppState.PAGES,
};
}
if (match.params.entity === "queries") {
return {
entity: FocusEntity.QUERY_LIST,
id: "",
pageId: match.params.pageId,
appState: AppState.PAGES,
};
}
if (match.params.entity === "jsObjects") {
return {
entity: FocusEntity.JS_OBJECT_LIST,
id: "",
pageId: match.params.pageId,
appState: AppState.PAGES,
};
}
if (match.params.entity) {
if (match.params.entity === "libraries") {
return {

View File

@ -1,13 +1,18 @@
import { matchPath } from "react-router";
import {
API_EDITOR_ID_PATH,
BUILDER_CUSTOM_PATH,
BUILDER_PATH,
BUILDER_PATH_DEPRECATED,
DATA_SOURCES_EDITOR_ID_PATH,
JS_COLLECTION_ID_PATH,
QUERIES_EDITOR_ID_PATH,
SAAS_GSHEET_EDITOR_ID_PATH,
} from "../constants/routes";
import { shouldStorePageURLForFocus } from "./FocusUtils";
import { FocusEntity, identifyEntityFromPath } from "./FocusEntity";
import { SAAS_EDITOR_API_ID_PATH } from "../pages/Editor/SaaSEditor/constants";
import { PluginType } from "../entities/Action";
export const getSelectedDatasourceId = (path: string): string | undefined => {
const match = matchPath<{ datasourceId?: string }>(path, [
@ -34,3 +39,54 @@ export const getCurrentAppUrl = (path: string): string | undefined => {
return path;
}
};
export type QueryListState =
| { id: string; type: PluginType; pluginPackageName?: string }
| undefined;
export const getSelectedQueryId = (path: string): QueryListState => {
const match = matchPath<{
queryId?: string;
apiId?: string;
pluginPackageName?: string;
}>(path, [
// Queries
BUILDER_PATH_DEPRECATED + QUERIES_EDITOR_ID_PATH,
BUILDER_PATH + QUERIES_EDITOR_ID_PATH,
BUILDER_CUSTOM_PATH + QUERIES_EDITOR_ID_PATH,
// SASS
BUILDER_PATH_DEPRECATED + SAAS_EDITOR_API_ID_PATH,
BUILDER_PATH + SAAS_EDITOR_API_ID_PATH,
BUILDER_CUSTOM_PATH + SAAS_EDITOR_API_ID_PATH,
// API
BUILDER_PATH_DEPRECATED + API_EDITOR_ID_PATH,
BUILDER_PATH + API_EDITOR_ID_PATH,
BUILDER_CUSTOM_PATH + API_EDITOR_ID_PATH,
]);
if (!match) return undefined;
const { apiId, pluginPackageName, queryId } = match.params;
if (!queryId || !apiId) {
return undefined;
}
let type: PluginType = PluginType.API;
if (pluginPackageName) {
type = PluginType.SAAS;
} else if (queryId) {
type = PluginType.DB;
}
return {
type,
id: apiId || queryId,
pluginPackageName,
};
};
export const getSelectedJSObjectId = (path: string): string | undefined => {
const match = matchPath<{ collectionId?: string }>(path, [
BUILDER_PATH_DEPRECATED + JS_COLLECTION_ID_PATH,
BUILDER_PATH + JS_COLLECTION_ID_PATH,
BUILDER_CUSTOM_PATH + JS_COLLECTION_ID_PATH,
]);
if (!match) return undefined;
return match.params.collectionId;
};

View File

@ -1,9 +1,17 @@
import history from "utils/history";
import { datasourcesEditorIdURL } from "@appsmith/RouteBuilder";
import {
apiEditorIdURL,
datasourcesEditorIdURL,
jsCollectionIdURL,
queryEditorIdURL,
saasEditorApiIdURL,
} from "@appsmith/RouteBuilder";
import { PluginType } from "../entities/Action";
import type { QueryListState } from "./FocusSelectors";
export function setSelectedDatasource(id: string | undefined) {
if (id) {
history.push(
history.replace(
datasourcesEditorIdURL({
datasourceId: id,
}),
@ -14,13 +22,56 @@ export function setSelectedDatasource(id: string | undefined) {
export function setPageUrl(path: string | undefined) {
if (path) {
const params = history.location.search;
history.push(`${path}${params}`);
history.replace(`${path}${params}`);
}
}
export function setAppUrl(path: string | undefined) {
if (path) {
const params = history.location.search;
history.push(`${path}${params}`);
history.replace(`${path}${params}`);
}
}
export function setSelectedQuery(state: QueryListState) {
if (state) {
switch (state.type) {
case PluginType.SAAS:
if (state.pluginPackageName) {
history.replace(
saasEditorApiIdURL({
apiId: state.id,
pluginPackageName: state.pluginPackageName,
}),
);
}
break;
case PluginType.DB:
history.replace(
queryEditorIdURL({
queryId: state.id,
}),
);
break;
case PluginType.API:
history.replace(
apiEditorIdURL({
apiId: state.id,
}),
);
break;
default:
break;
}
}
}
export function setSelectedJSObject(id: string | undefined) {
if (id) {
history.replace(
jsCollectionIdURL({
collectionId: id,
}),
);
}
}

View File

@ -1,6 +1,11 @@
import type { FocusEntityInfo } from "./FocusEntity";
import { FocusEntity, identifyEntityFromPath } from "./FocusEntity";
import { builderURL, datasourcesEditorURL } from "@appsmith/RouteBuilder";
import {
builderURL,
datasourcesEditorURL,
jsCollectionListURL,
queryListURL,
} from "@appsmith/RouteBuilder";
export const getEntityParentUrl = (
entityInfo: FocusEntityInfo,
@ -13,6 +18,12 @@ export const getEntityParentUrl = (
if (parentEntity === FocusEntity.DATASOURCE_LIST) {
return datasourcesEditorURL({ pageId: entityInfo.pageId });
}
if (parentEntity === FocusEntity.JS_OBJECT_LIST) {
return jsCollectionListURL({ pageId: entityInfo.pageId });
}
if (parentEntity === FocusEntity.QUERY_LIST) {
return queryListURL({ pageId: entityInfo.pageId });
}
return "";
};
export const isPageChange = (prevPath: string, currentPath: string) => {

View File

@ -0,0 +1,48 @@
import React from "react";
import { useSelector } from "react-redux";
import { Flex } from "design-system";
import styled from "styled-components";
import { selectFilesForExplorer } from "@appsmith/selectors/entitiesSelector";
import { useActiveAction } from "@appsmith/pages/Editor/Explorer/hooks";
import ExplorerJSCollectionEntity from "pages/Editor/Explorer/JSActions/JSActionEntity";
const JSContainer = styled(Flex)`
& .t--entity-item {
grid-template-columns: 4px auto 1fr auto auto auto auto auto;
& .t--entity-name {
padding-left: var(--ads-v2-spaces-3);
}
}
`;
const JSSection = () => {
const files = useSelector(selectFilesForExplorer);
const activeActionId = useActiveAction();
return (
<JSContainer
className="ide-pages-pane__content-queries"
flexDirection="column"
paddingTop="spaces-3"
>
{files.map(({ entity, type }: any) => {
if (type === "JS" && entity.id) {
return (
<ExplorerJSCollectionEntity
id={entity.id}
isActive={entity.id === activeActionId}
key={entity.id}
searchKeyword={""}
step={2}
type={type}
/>
);
}
})}
</JSContainer>
);
};
export { JSSection };

View File

@ -1,108 +0,0 @@
import React, { useMemo } from "react";
import { useSelector } from "react-redux";
import { Flex, Text } from "design-system";
import styled from "styled-components";
import { getPagePermissions } from "selectors/editorSelectors";
import { selectFilesForExplorer } from "@appsmith/selectors/entitiesSelector";
import { useActiveAction } from "@appsmith/pages/Editor/Explorer/hooks";
import ExplorerActionEntity from "pages/Editor/Explorer/Actions/ActionEntity";
import { EmptyComponent } from "pages/Editor/Explorer/common";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import {
createMessage,
EMPTY_QUERY_JS_BUTTON_TEXT,
EMPTY_QUERY_JS_MAIN_TEXT,
} from "@appsmith/constants/messages";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import ExplorerJSCollectionEntity from "pages/Editor/Explorer/JSActions/JSActionEntity";
const QueriesContainer = styled(Flex)`
& .t--entity-item {
grid-template-columns: 4px auto 1fr auto auto auto auto auto;
& .t--entity-name {
padding-left: var(--ads-v2-spaces-3);
}
}
`;
const QueriesJS = ({ paneType }: { paneType: "queries" | "js" }) => {
const files = useSelector(selectFilesForExplorer);
const activeActionId = useActiveAction();
const pagePermissions = useSelector(getPagePermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const fileEntities = useMemo(
() =>
files.map(({ entity, type }: any) => {
if (
paneType !== "js" &&
type === "group" &&
entity.name === "JS Objects"
) {
return (
<Flex key={entity.name || "Queries"} px="spaces-3">
<Text
className="overflow-hidden overflow-ellipsis whitespace-nowrap"
kind="heading-xs"
>
{entity.name}
</Text>
</Flex>
);
} else if (type !== "JS" && paneType === "queries") {
return (
<ExplorerActionEntity
id={entity.id}
isActive={entity.id === activeActionId}
key={entity.id}
searchKeyword={""}
step={2}
type={type}
/>
);
} else if (type === "JS" && paneType === "js") {
return (
<ExplorerJSCollectionEntity
id={entity.id}
isActive={entity.id === activeActionId}
key={entity.id}
searchKeyword={""}
step={2}
type={type}
/>
);
}
}),
[files, activeActionId],
);
return (
<QueriesContainer
className="ide-pages-pane__content-queries"
flexDirection="column"
paddingTop="spaces-3"
>
{fileEntities.length ? (
fileEntities
) : (
<EmptyComponent
mainText={createMessage(EMPTY_QUERY_JS_MAIN_TEXT)}
{...(canCreateActions && {
addBtnText: createMessage(EMPTY_QUERY_JS_BUTTON_TEXT),
// addFunction: onCreate,
})}
/>
)}
</QueriesContainer>
);
};
export { QueriesJS };

View File

@ -0,0 +1,70 @@
import React from "react";
import { useSelector } from "react-redux";
import { Flex, Text } from "design-system";
import styled from "styled-components";
import { selectFilesForExplorer } from "@appsmith/selectors/entitiesSelector";
import { useActiveAction } from "@appsmith/pages/Editor/Explorer/hooks";
import ExplorerActionEntity from "pages/Editor/Explorer/Actions/ActionEntity";
const QueriesContainer = styled(Flex)`
& .t--entity-item {
grid-template-columns: 4px auto 1fr auto auto auto auto auto;
& .t--entity-name {
padding-left: var(--ads-v2-spaces-3);
}
}
`;
const QueriesSection = () => {
const files = useSelector(selectFilesForExplorer);
const activeActionId = useActiveAction();
return (
<QueriesContainer
className="ide-pages-pane__content-queries"
flexDirection="column"
paddingTop="spaces-3"
>
{files.map(({ entity, type }: any) => {
if (type === "group" && entity.name !== "JS Objects") {
return (
<Flex key={entity.name || "Queries"} px="spaces-3">
<Text
className="overflow-hidden overflow-ellipsis whitespace-nowrap"
kind="heading-xs"
>
{entity.name}
</Text>
</Flex>
);
} else if (type !== "JS" && entity.id) {
return (
<ExplorerActionEntity
id={entity.id}
isActive={entity.id === activeActionId}
key={entity.id}
searchKeyword={""}
step={2}
type={type}
/>
);
}
})}
{files.length === 0 && (
<Flex px="spaces-3">
<Text
className="overflow-hidden overflow-ellipsis whitespace-nowrap"
kind="heading-xs"
>
No Queries/APIs found
</Text>
</Flex>
)}
</QueriesContainer>
);
};
export { QueriesSection };

View File

@ -1,13 +1,11 @@
import React, { useCallback, useEffect, useState } from "react";
import { withProfiler } from "@sentry/react";
import { Divider, Flex, SegmentedControl } from "design-system";
import { Flex, SegmentedControl } from "design-system";
import { useLocation } from "react-router";
import { useDispatch, useSelector } from "react-redux";
import { FocusEntity } from "navigation/FocusEntity";
import { identifyEntityFromPath } from "navigation/FocusEntity";
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
import { createMessage, PAGES_PANE_TEXTS } from "@appsmith/constants/messages";
import { QueriesJS } from "./Queries_JS";
import ExplorerWidgetGroup from "pages/Editor/Explorer/Widgets/WidgetGroup";
import { getCurrentPageId } from "@appsmith/selectors/entitiesSelector";
import AnalyticsUtil from "utils/AnalyticsUtil";
@ -21,6 +19,8 @@ import { forceOpenWidgetPanel } from "actions/widgetSidebarActions";
import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors";
import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions";
import Pages from "pages/Editor/Explorer/Pages";
import { JSSection } from "./JS_Section";
import { QueriesSection } from "./Queries_Section";
enum TabsType {
QUERIES = "queries",
@ -47,10 +47,12 @@ const _pagesPane = () => {
).entity;
switch (entity) {
case FocusEntity.QUERY:
case FocusEntity.QUERY_LIST:
case FocusEntity.API:
setSelected(TabsType.QUERIES);
break;
case FocusEntity.JS_OBJECT:
case FocusEntity.JS_OBJECT_LIST:
setSelected(TabsType.JS);
break;
case FocusEntity.CANVAS:
@ -92,7 +94,6 @@ const _pagesPane = () => {
};
return (
<Flex
border="1px solid var(--ads-v2-color-border)"
className="ide-pages-pane"
flexDirection="column"
gap="spacing-2"
@ -130,7 +131,6 @@ const _pagesPane = () => {
value={selected}
/>
</Flex>
<Divider />
<Flex
className="ide-pages-pane__content"
flexDirection="column"
@ -138,9 +138,9 @@ const _pagesPane = () => {
overflow="hidden"
width="100%"
>
{(selected === TabsType.QUERIES || selected === TabsType.JS) && (
<QueriesJS paneType={selected} />
)}
{selected === TabsType.QUERIES && <QueriesSection />}
{selected === TabsType.JS && <JSSection />}
{selected === TabsType.UI && (
<ExplorerWidgetGroup

View File

@ -88,7 +88,7 @@ function Sidebar() {
}
return (
<Container className="t--sidebar">
<Container className="t--sidebar" id="t--app-sidebar">
{isAppSidebarAnnouncementEnabled &&
!isAppSidebarAnnouncementDismissed && (
<AnnouncementPopover open={isPopoverOpen}>

View File

@ -0,0 +1,63 @@
import React from "react";
import { Flex, Text, Button } from "design-system";
import { importSvg } from "design-system-old";
import { createMessage, PAGES_PANE_TEXTS } from "@appsmith/constants/messages";
import {
getCurrentPageId,
getPagePermissions,
} from "selectors/editorSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useDispatch, useSelector } from "react-redux";
import { createNewJSCollection } from "../../../actions/jsPaneActions";
const JSBlankState = () => {
const pagePermissions = useSelector(getPagePermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const BlankStateIllustration = importSvg(
async () => import("assets/images/no-js-min.svg"),
);
const dispatch = useDispatch();
const pageId = useSelector(getCurrentPageId);
return (
<Flex
alignItems={"center"}
flexDirection={"column"}
gap={"spaces-7"}
height={"100%"}
justifyContent={"center"}
width={"100%"}
>
<BlankStateIllustration />
<Text color={"var(--ads-v2-color-fg)"} kind={"heading-xs"}>
{createMessage(PAGES_PANE_TEXTS.js_blank_state)}
</Text>
{canCreateActions && (
<Button
onClick={() =>
dispatch(
createNewJSCollection(pageId, "JS_OBJECT_GUTTER_RUN_BUTTON"),
)
}
size={"md"}
startIcon={"add-line"}
>
{createMessage(PAGES_PANE_TEXTS.js_blank_button)}
</Button>
)}
</Flex>
);
};
export { JSBlankState };

View File

@ -0,0 +1,48 @@
import React from "react";
import { Flex, Text, Button } from "design-system";
import { importSvg } from "design-system-old";
import { useSelector } from "react-redux";
import { createMessage, PAGES_PANE_TEXTS } from "@appsmith/constants/messages";
import { getPagePermissions } from "selectors/editorSelectors";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
const QueriesBlankState = () => {
const pagePermissions = useSelector(getPagePermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
pagePermissions,
);
const BlankStateIllustration = importSvg(
async () => import("assets/images/no-query-min.svg"),
);
return (
<Flex
alignItems={"center"}
flexDirection={"column"}
gap={"spaces-7"}
height={"100%"}
justifyContent={"center"}
width={"100%"}
>
<BlankStateIllustration />
<Text color={"var(--ads-v2-color-fg)"} kind={"heading-xs"}>
{createMessage(PAGES_PANE_TEXTS.query_blank_state)}
</Text>
{canCreateActions && (
<Button size={"md"} startIcon={"add-line"}>
{createMessage(PAGES_PANE_TEXTS.query_blank_button)}
</Button>
)}
</Flex>
);
};
export { QueriesBlankState };

View File

@ -1,4 +1,12 @@
import type { AppState } from "@appsmith/reducers";
import { getCurrentJSCollections } from "@appsmith/selectors/entitiesSelector";
export const getJSPaneConfigSelectedTab = (state: AppState) =>
state.ui.jsPane.selectedConfigTab;
export const getFirstJSObjectId = (state: AppState) => {
const currentJSActions = getCurrentJSCollections(state);
if (currentJSActions.length) {
return currentJSActions[0].config.id;
}
};

View File

@ -1,4 +1,22 @@
import type { AppState } from "@appsmith/reducers";
import type { QueryListState } from "../navigation/FocusSelectors";
import { getPageActions } from "@appsmith/selectors/entitiesSelector";
import { getCurrentPageId } from "./editorSelectors";
export const getQueryPaneConfigSelectedTabIndex = (state: AppState) =>
state.ui.queryPane.selectedConfigTabIndex;
export const getFirstQueryId = (state: AppState): QueryListState => {
const { plugins } = state.entities;
const pageId = getCurrentPageId(state);
const currentPageActions = getPageActions(pageId)(state);
if (currentPageActions.length) {
const first = currentPageActions[0].config;
const plugin = plugins.list.find((p) => p.id === first.pluginId);
return {
id: first.id,
type: first.pluginType,
pluginPackageName: plugin?.packageName,
};
}
};