fix: page list item icons aren't permission driven on first load (#18586)

* fix: page list ctas permission driven fix

* fix: page list and page context menu , datasource action pane create permission driven

* fix: check manage permission on page aswell for cloning

* fix: duplicate & fork app permission driven

* fix: onclick triggers on disabled icons
This commit is contained in:
Sangeeth Sivan 2022-12-02 02:56:21 +05:30 committed by GitHub
parent 058500704e
commit 3e8414b4e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 25 deletions

View File

@ -310,6 +310,7 @@ type ApplicationCardProps = {
update?: (id: string, data: UpdateApplicationPayload) => void; update?: (id: string, data: UpdateApplicationPayload) => void;
enableImportExport?: boolean; enableImportExport?: boolean;
isMobile?: boolean; isMobile?: boolean;
hasCreateNewApplicationPermission?: boolean;
}; };
const EditButton = styled(Button)` const EditButton = styled(Button)`
@ -469,7 +470,11 @@ export function ApplicationCard(props: ApplicationCardProps) {
cypressSelector: "t--share", cypressSelector: "t--share",
}); });
} }
if (props.duplicate && hasEditPermission) { if (
props.duplicate &&
props.hasCreateNewApplicationPermission &&
hasEditPermission
) {
moreActionItems.push({ moreActionItems.push({
onSelect: duplicateApp, onSelect: duplicateApp,
text: "Duplicate", text: "Duplicate",
@ -516,6 +521,7 @@ export function ApplicationCard(props: ApplicationCardProps) {
const hasDeletePermission = hasDeleteApplicationPermission( const hasDeletePermission = hasDeleteApplicationPermission(
props.application?.userPermissions, props.application?.userPermissions,
); );
const updateColor = (color: string) => { const updateColor = (color: string) => {
setSelectedColor(color); setSelectedColor(color);
props.update && props.update &&

View File

@ -922,6 +922,9 @@ function ApplicationsSection(props: any) {
delete={deleteApplication} delete={deleteApplication}
duplicate={duplicateApplicationDispatch} duplicate={duplicateApplicationDispatch}
enableImportExport={enableImportExport} enableImportExport={enableImportExport}
hasCreateNewApplicationPermission={
hasCreateNewApplicationPermission
}
isMobile={isMobile} isMobile={isMobile}
key={application.id} key={application.id}
update={updateApplicationDispatch} update={updateApplicationDispatch}

View File

@ -25,10 +25,13 @@ import {
createMessage, createMessage,
} from "@appsmith/constants/messages"; } from "@appsmith/constants/messages";
import { import {
hasCreatePagePermission,
hasDeletePagePermission, hasDeletePagePermission,
hasManagePagePermission, hasManagePagePermission,
} from "@appsmith/utils/permissionHelpers"; } from "@appsmith/utils/permissionHelpers";
import { getPageById } from "selectors/editorSelectors"; import { getPageById } from "selectors/editorSelectors";
import { getCurrentApplication } from "selectors/applicationSelectors";
import { AppState } from "@appsmith/reducers";
const CustomLabel = styled.div` const CustomLabel = styled.div`
display: flex; display: flex;
@ -101,6 +104,12 @@ export function PageContextMenu(props: {
const pagePermissions = const pagePermissions =
useSelector(getPageById(props.pageId))?.userPermissions || []; useSelector(getPageById(props.pageId))?.userPermissions || [];
const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
);
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canManagePages = hasManagePagePermission(pagePermissions); const canManagePages = hasManagePagePermission(pagePermissions);
const canDeletePages = hasDeletePagePermission(pagePermissions); const canDeletePages = hasDeletePagePermission(pagePermissions);
@ -111,11 +120,12 @@ export function PageContextMenu(props: {
onSelect: editPageName, onSelect: editPageName,
label: createMessage(CONTEXT_EDIT_NAME), label: createMessage(CONTEXT_EDIT_NAME),
}, },
canManagePages && { canCreatePages &&
value: "clone", canManagePages && {
onSelect: clonePage, value: "clone",
label: createMessage(CONTEXT_CLONE), onSelect: clonePage,
}, label: createMessage(CONTEXT_CLONE),
},
canManagePages && { canManagePages && {
value: "visibility", value: "visibility",
onSelect: setHiddenField, onSelect: setHiddenField,

View File

@ -10,7 +10,6 @@ import {
getCurrentApplication, getCurrentApplication,
getCurrentApplicationId, getCurrentApplicationId,
getCurrentPageId, getCurrentPageId,
getPagePermissions,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import Entity, { EntityClassNames } from "../Entity"; import Entity, { EntityClassNames } from "../Entity";
import history from "utils/history"; import history from "utils/history";
@ -192,18 +191,16 @@ function Pages() {
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
); );
const pagePermissions = useSelector(getPagePermissions);
const canCreatePages = hasCreatePagePermission(userAppPermissions); const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canManagePages = hasManagePagePermission(pagePermissions);
const pageElements = useMemo( const pageElements = useMemo(
() => () =>
pages.map((page) => { pages.map((page) => {
const icon = page.isDefault ? defaultPageIcon : pageIcon; const icon = page.isDefault ? defaultPageIcon : pageIcon;
const rightIcon = !!page.isHidden ? hiddenPageIcon : null; const rightIcon = !!page.isHidden ? hiddenPageIcon : null;
const isCurrentPage = currentPageId === page.pageId; const isCurrentPage = currentPageId === page.pageId;
const pagePermissions = page.userPermissions;
const canManagePages = hasManagePagePermission(pagePermissions);
const contextMenu = ( const contextMenu = (
<PageContextMenu <PageContextMenu
applicationId={applicationId as string} applicationId={applicationId as string}
@ -247,7 +244,6 @@ function Pages() {
action={onPageListSelection} action={onPageListSelection}
addButtonHelptext={createMessage(ADD_PAGE_TOOLTIP)} addButtonHelptext={createMessage(ADD_PAGE_TOOLTIP)}
alwaysShowRightIcon alwaysShowRightIcon
canEditEntityName={canManagePages}
className="group pages" className="group pages"
collapseRef={pageResizeRef} collapseRef={pageResizeRef}
customAddButton={ customAddButton={

View File

@ -14,17 +14,20 @@ import EditName from "./EditName";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { import {
getCurrentApplication,
getCurrentApplicationId, getCurrentApplicationId,
getPagePermissions, getPageById,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { Colors } from "constants/Colors"; import { Colors } from "constants/Colors";
import { TooltipComponent } from "design-system"; import { TooltipComponent } from "design-system";
import { createMessage, SETTINGS_TOOLTIP } from "@appsmith/constants/messages"; import { createMessage, SETTINGS_TOOLTIP } from "@appsmith/constants/messages";
import { TOOLTIP_HOVER_ON_DELAY } from "constants/AppConstants"; import { TOOLTIP_HOVER_ON_DELAY } from "constants/AppConstants";
import { import {
hasCreatePagePermission,
hasDeletePagePermission, hasDeletePagePermission,
hasManagePagePermission, hasManagePagePermission,
} from "@appsmith/utils/permissionHelpers"; } from "@appsmith/utils/permissionHelpers";
import { AppState } from "@appsmith/reducers";
// render over popover portals // render over popover portals
const Container = styled.div` const Container = styled.div`
@ -141,15 +144,24 @@ function ContextMenu(props: Props) {
* opens the context menu on interaction ( on click ) * opens the context menu on interaction ( on click )
*/ */
const handleInteraction = useCallback((isOpen) => { const handleInteraction = useCallback((isOpen) => {
setIsOpen(isOpen); (canManagePages || canDeletePages) && setIsOpen(isOpen);
}, []); }, []);
const pagePermissions = useSelector(getPagePermissions); const pagePermissions =
useSelector(getPageById(page.pageId))?.userPermissions || [];
const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
);
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canManagePages = hasManagePagePermission(pagePermissions); const canManagePages = hasManagePagePermission(pagePermissions);
const canDeletePages = hasDeletePagePermission(pagePermissions); const canDeletePages = hasDeletePagePermission(pagePermissions);
const canClonePages = canCreatePages && canManagePages;
return ( return (
<Popover2 <Popover2
content={ content={
@ -164,9 +176,9 @@ function ContextMenu(props: Props) {
<Action> <Action>
<CopyIcon <CopyIcon
color={Colors.GREY_9} color={Colors.GREY_9}
disabled={!canManagePages} disabled={!canClonePages}
height={16} height={16}
onClick={!canManagePages ? noop : () => onCopy(page.pageId)} onClick={!canClonePages ? noop : () => onCopy(page.pageId)}
width={16} width={16}
/> />
</Action> </Action>
@ -239,6 +251,7 @@ function ContextMenu(props: Props) {
<Action className={isOpen ? "active" : ""} type="button"> <Action className={isOpen ? "active" : ""} type="button">
<SettingsIcon <SettingsIcon
color={Colors.GREY_9} color={Colors.GREY_9}
disabled={!canManagePages && !canDeletePages}
height={16} height={16}
onClick={noop} onClick={noop}
width={16} width={16}

View File

@ -31,16 +31,18 @@ import { TOOLTIP_HOVER_ON_DELAY } from "constants/AppConstants";
import { import {
getCurrentApplicationId, getCurrentApplicationId,
getPagePermissions, getPageById,
selectApplicationVersion, selectApplicationVersion,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { ApplicationVersion } from "actions/applicationActions"; import { ApplicationVersion } from "actions/applicationActions";
import { AppState } from "@appsmith/reducers"; import { AppState } from "@appsmith/reducers";
import { import {
hasCreatePagePermission,
hasDeletePagePermission, hasDeletePagePermission,
hasManagePagePermission, hasManagePagePermission,
} from "@appsmith/utils/permissionHelpers"; } from "@appsmith/utils/permissionHelpers";
import { noop } from "utils/AppsmithUtils"; import { noop } from "utils/AppsmithUtils";
import { getCurrentApplication } from "selectors/applicationSelectors";
export const Container = styled.div` export const Container = styled.div`
display: flex; display: flex;
@ -152,12 +154,21 @@ function PageListItem(props: PageListItemProps) {
return dispatch(updatePage(item.pageId, item.pageName, !item.isHidden)); return dispatch(updatePage(item.pageId, item.pageName, !item.isHidden));
}, [dispatch, item]); }, [dispatch, item]);
const pagePermissions = useSelector(getPagePermissions); const pagePermissions =
useSelector(getPageById(item.pageId))?.userPermissions || [];
const userAppPermissions = useSelector(
(state: AppState) => getCurrentApplication(state)?.userPermissions ?? [],
);
const canCreatePages = hasCreatePagePermission(userAppPermissions);
const canManagePages = hasManagePagePermission(pagePermissions); const canManagePages = hasManagePagePermission(pagePermissions);
const canDeletePages = hasDeletePagePermission(pagePermissions); const canDeletePages = hasDeletePagePermission(pagePermissions);
const canClonePages = canCreatePages && canManagePages;
return ( return (
<Container> <Container>
<ListItem> <ListItem>
@ -212,9 +223,9 @@ function PageListItem(props: PageListItemProps) {
<Action type="button"> <Action type="button">
<CopyIcon <CopyIcon
color={Colors.GREY_9} color={Colors.GREY_9}
disabled={!canManagePages} disabled={!canClonePages}
height={16} height={16}
onClick={!canManagePages ? noop : clonePageCallback} onClick={!canClonePages ? noop : clonePageCallback}
width={16} width={16}
/> />
</Action> </Action>

View File

@ -109,6 +109,7 @@ import {
import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen"; import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen";
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig"; import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
import { import {
hasCreateDatasourcePermission,
hasDeleteActionPermission, hasDeleteActionPermission,
hasExecuteActionPermission, hasExecuteActionPermission,
hasManageActionPermission, hasManageActionPermission,
@ -125,6 +126,7 @@ import {
setQueryPaneResponseSelectedTab, setQueryPaneResponseSelectedTab,
} from "actions/queryPaneActions"; } from "actions/queryPaneActions";
import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants"; import { ActionExecutionResizerHeight } from "pages/Editor/APIEditor/constants";
import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors";
const QueryFormContainer = styled.form` const QueryFormContainer = styled.form`
flex: 1; flex: 1;
@ -522,6 +524,14 @@ export function EditorJSONtoForm(props: Props) {
currentActionConfig?.userPermissions, currentActionConfig?.userPermissions,
); );
const userWorkspacePermissions = useSelector(
(state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [],
);
const canCreateDatasource = hasCreateDatasourcePermission(
userWorkspacePermissions,
);
// Query is executed even once during the session, show the response data. // Query is executed even once during the session, show the response data.
if (executedQueryData) { if (executedQueryData) {
if (!executedQueryData.isExecutionSuccess) { if (!executedQueryData.isExecutionSuccess) {
@ -555,10 +565,12 @@ export function EditorJSONtoForm(props: Props) {
return ( return (
<> <>
<components.MenuList {...props}>{props.children}</components.MenuList> <components.MenuList {...props}>{props.children}</components.MenuList>
<CreateDatasource onClick={() => onCreateDatasourceClick()}> {canCreateDatasource ? (
<Icon className="createIcon" icon="plus" iconSize={11} /> <CreateDatasource onClick={() => onCreateDatasourceClick()}>
{createMessage(CREATE_NEW_DATASOURCE)} <Icon className="createIcon" icon="plus" iconSize={11} />
</CreateDatasource> {createMessage(CREATE_NEW_DATASOURCE)}
</CreateDatasource>
) : null}
</> </>
); );
} }