chore: Added context switching for pages pane (#29100)
This commit is contained in:
parent
2fa9f5fb70
commit
228548629b
1
app/client/src/assets/images/no-js-min.svg
Normal file
1
app/client/src/assets/images/no-js-min.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 17 KiB |
1
app/client/src/assets/images/no-query-min.svg
Normal file
1
app/client/src/assets/images/no-query-min.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 42 KiB |
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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}`,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
48
app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx
Normal file
48
app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx
Normal 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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ function Sidebar() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Container className="t--sidebar">
|
||||
<Container className="t--sidebar" id="t--app-sidebar">
|
||||
{isAppSidebarAnnouncementEnabled &&
|
||||
!isAppSidebarAnnouncementDismissed && (
|
||||
<AnnouncementPopover open={isPopoverOpen}>
|
||||
|
|
|
|||
63
app/client/src/pages/Editor/JSEditor/JSBlankState.tsx
Normal file
63
app/client/src/pages/Editor/JSEditor/JSBlankState.tsx
Normal 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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user