Tab names can now be updated from the entity explorer (#2779)
This commit is contained in:
parent
344b7f73a6
commit
51696b7220
|
|
@ -14,6 +14,7 @@ import { removeSpecialChars } from "utils/helpers";
|
|||
import { AppState } from "reducers";
|
||||
import { Page, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { WidgetTypes } from "constants/WidgetConstants";
|
||||
|
||||
const searchHighlightSpanClassName = "token";
|
||||
const searchTokenizationDelimiter = "!!";
|
||||
|
|
@ -71,6 +72,24 @@ export interface EntityNameProps {
|
|||
export const EntityName = forwardRef(
|
||||
(props: EntityNameProps, ref: React.Ref<HTMLDivElement>) => {
|
||||
const { name, updateEntityName, searchKeyword } = props;
|
||||
const tabs:
|
||||
| Array<{ id: string; widgetId: string; label: string }>
|
||||
| undefined = useSelector((state: AppState) => {
|
||||
if (state.entities.canvasWidgets.hasOwnProperty(props.entityId)) {
|
||||
const widget = state.entities.canvasWidgets[props.entityId];
|
||||
if (
|
||||
widget.parentId &&
|
||||
state.entities.canvasWidgets.hasOwnProperty(widget.parentId)
|
||||
) {
|
||||
const parent = state.entities.canvasWidgets[widget.parentId];
|
||||
if (parent.type === WidgetTypes.TABS_WIDGET) {
|
||||
return parent.tabs;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
const nameUpdateError = useSelector((state: AppState) => {
|
||||
return state.ui.explorer.updateEntityError === props.entityId;
|
||||
});
|
||||
|
|
@ -99,12 +118,20 @@ export const EntityName = forwardRef(
|
|||
);
|
||||
|
||||
const hasNameConflict = useCallback(
|
||||
(newName: string) =>
|
||||
!(
|
||||
existingPageNames.indexOf(newName) === -1 &&
|
||||
existingActionNames.indexOf(newName) === -1 &&
|
||||
existingWidgetNames.indexOf(newName) === -1
|
||||
),
|
||||
(
|
||||
newName: string,
|
||||
tabs?: Array<{ id: string; widgetId: string; label: string }>,
|
||||
) => {
|
||||
if (tabs === undefined) {
|
||||
return !(
|
||||
existingPageNames.indexOf(newName) === -1 &&
|
||||
existingActionNames.indexOf(newName) === -1 &&
|
||||
existingWidgetNames.indexOf(newName) === -1
|
||||
);
|
||||
} else {
|
||||
return tabs.findIndex((tab) => tab.label === newName) > -1;
|
||||
}
|
||||
},
|
||||
[existingPageNames, existingActionNames, existingWidgetNames],
|
||||
);
|
||||
|
||||
|
|
@ -112,7 +139,7 @@ export const EntityName = forwardRef(
|
|||
(newName: string): string | boolean => {
|
||||
if (!newName || newName.trim().length === 0) {
|
||||
return "Please enter a name";
|
||||
} else if (newName !== name && hasNameConflict(newName)) {
|
||||
} else if (newName !== name && hasNameConflict(newName, tabs)) {
|
||||
return `${newName} is already being used.`;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
initCanvasLayout,
|
||||
updateCurrentPage,
|
||||
updateWidgetNameSuccess,
|
||||
updateAndSaveLayout,
|
||||
} from "actions/pageActions";
|
||||
import PageApi, {
|
||||
ClonePageRequest,
|
||||
|
|
@ -75,6 +76,7 @@ import { getQueryParams } from "utils/AppsmithUtils";
|
|||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
import { WidgetTypes } from "constants/WidgetConstants";
|
||||
|
||||
const getWidgetName = (state: AppState, widgetId: string) =>
|
||||
state.entities.canvasWidgets[widgetId];
|
||||
|
|
@ -544,47 +546,110 @@ export function* updateWidgetNameSaga(
|
|||
const pageId = yield select(getCurrentPageId);
|
||||
const existingPageNames = yield select(getExistingPageNames);
|
||||
|
||||
// check if name is not conflicting with any
|
||||
// existing entity/api/queries/reserved words
|
||||
if (
|
||||
isNameValid(action.payload.newName, {
|
||||
...evalTree,
|
||||
...existingPageNames,
|
||||
})
|
||||
) {
|
||||
const request: UpdateWidgetNameRequest = {
|
||||
newName: action.payload.newName,
|
||||
oldName: widgetName,
|
||||
pageId,
|
||||
layoutId,
|
||||
};
|
||||
const response: UpdateWidgetNameResponse = yield call(
|
||||
PageApi.updateWidgetName,
|
||||
request,
|
||||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield updateCanvasWithDSL(response.data, pageId, layoutId);
|
||||
// TODO(abhinav): Why do we need to jump through these hoops just to
|
||||
// change the tab name? Figure out a better design to make this moot.
|
||||
const tabs:
|
||||
| Array<{
|
||||
id: string;
|
||||
widgetId: string;
|
||||
label: string;
|
||||
}>
|
||||
| undefined = yield select((state: AppState) => {
|
||||
// Check if this widget exists in the canvas widgets
|
||||
if (state.entities.canvasWidgets.hasOwnProperty(action.payload.id)) {
|
||||
// If it does assign it to a variable
|
||||
const widget = state.entities.canvasWidgets[action.payload.id];
|
||||
// Check if this widget has a parent in the canvas widgets
|
||||
if (
|
||||
widget.parentId &&
|
||||
state.entities.canvasWidgets.hasOwnProperty(widget.parentId)
|
||||
) {
|
||||
// If the parent exists assign it to a variable
|
||||
const parent = state.entities.canvasWidgets[widget.parentId];
|
||||
// Check if this parent is a TABS_WIDGET
|
||||
if (parent.type === WidgetTypes.TABS_WIDGET) {
|
||||
// If it is return the tabs property
|
||||
return parent.tabs;
|
||||
}
|
||||
}
|
||||
}
|
||||
// This isn't a tab in a tabs widget so return undefined
|
||||
return;
|
||||
});
|
||||
|
||||
yield put(updateWidgetNameSuccess());
|
||||
// Add this to the page DSLs for entity explorer
|
||||
// If we're trying to update the name of a tab in the TABS_WIDGET
|
||||
if (tabs !== undefined) {
|
||||
// Get all canvas widgets
|
||||
const stateWidgets = yield select(getWidgets);
|
||||
// Shallow copy canvas widgets as they're immutable
|
||||
const widgets = { ...stateWidgets };
|
||||
// Get the parent Id of the tab (canvas widget) whose name we're updating
|
||||
const parentId = widgets[action.payload.id].parentId;
|
||||
// Update the tabName property of the tab (canvas widget)
|
||||
widgets[action.payload.id] = {
|
||||
...widgets[action.payload.id],
|
||||
tabName: action.payload.newName,
|
||||
};
|
||||
// Shallow copy the parent widget so that we can update the properties
|
||||
const parent = { ...widgets[parentId] };
|
||||
// Update the tabs property of the parent tabs widget
|
||||
parent.tabs = tabs.map(
|
||||
(tab: { widgetId: string; label: string; id: string }) => {
|
||||
if (tab.widgetId === action.payload.id) {
|
||||
return { ...tab, label: action.payload.newName };
|
||||
}
|
||||
return tab;
|
||||
},
|
||||
);
|
||||
// replace the parent widget in the canvas widgets
|
||||
widgets[parentId] = parent;
|
||||
// Update and save the new widgets
|
||||
yield put(updateAndSaveLayout(widgets));
|
||||
// Send a update saying that we've successfully updated the name
|
||||
yield put(updateWidgetNameSuccess());
|
||||
} else {
|
||||
// check if name is not conflicting with any
|
||||
// existing entity/api/queries/reserved words
|
||||
if (
|
||||
isNameValid(action.payload.newName, {
|
||||
...evalTree,
|
||||
...existingPageNames,
|
||||
})
|
||||
) {
|
||||
const request: UpdateWidgetNameRequest = {
|
||||
newName: action.payload.newName,
|
||||
oldName: widgetName,
|
||||
pageId,
|
||||
layoutId,
|
||||
};
|
||||
const response: UpdateWidgetNameResponse = yield call(
|
||||
PageApi.updateWidgetName,
|
||||
request,
|
||||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield updateCanvasWithDSL(response.data, pageId, layoutId);
|
||||
|
||||
yield put(updateWidgetNameSuccess());
|
||||
// Add this to the page DSLs for entity explorer
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSL_SUCCESS,
|
||||
payload: {
|
||||
pageId: pageId,
|
||||
dsl: response.data.dsl,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_PAGE_DSL_SUCCESS,
|
||||
type: ReduxActionErrorTypes.UPDATE_WIDGET_NAME_ERROR,
|
||||
payload: {
|
||||
pageId: pageId,
|
||||
dsl: response.data.dsl,
|
||||
error: {
|
||||
message: `Entity name: ${action.payload.newName} is already being used.`,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.UPDATE_WIDGET_NAME_ERROR,
|
||||
payload: {
|
||||
error: {
|
||||
message: `Entity name: ${action.payload.newName} is already being used.`,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user