diff --git a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageHandlerMenu.jsx b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageHandlerMenu.jsx index ec84149418..23976b5b45 100644 --- a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageHandlerMenu.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageHandlerMenu.jsx @@ -2,6 +2,7 @@ import React from 'react'; import { Overlay, Popover } from 'react-bootstrap'; import { Button } from '@/_ui/LeftSidebar'; import useStore from '@/AppBuilder/_stores/store'; +import { shallow } from 'zustand/shallow'; export const PageHandlerMenu = ({ darkMode }) => { const setShowEditingPopover = useStore((state) => state.setShowEditingPopover); @@ -21,6 +22,8 @@ export const PageHandlerMenu = ({ darkMode }) => { const clonePage = useStore((state) => state.clonePage); const markAsHomePage = useStore((state) => state.markAsHomePage); const togglePagePermissionModal = useStore((state) => state.togglePagePermissionModal); + const featureAccess = useStore((state) => state?.license?.featureAccess, shallow); + const licenseValid = !featureAccess?.licenseStatus?.isExpired && featureAccess?.licenseStatus?.isLicenseValid; // const popoverTargetRef = null; // console.log( @@ -166,16 +169,18 @@ export const PageHandlerMenu = ({ darkMode }) => { }} disabled={isHomePage} /> - { - togglePagePermissionModal(true); - }} - /> + {licenseValid && ( + { + togglePagePermissionModal(true); + }} + /> + )} { >
- + {isLicensed ? : <>} diff --git a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageMenuItem.jsx b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageMenuItem.jsx index 7968184633..0f3b5d21a7 100644 --- a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageMenuItem.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PageMenuItem.jsx @@ -31,6 +31,7 @@ export const PageMenuItem = withRouter( const featureAccess = useStore((state) => state?.license?.featureAccess, shallow); const licenseValid = !featureAccess?.licenseStatus?.isExpired && featureAccess?.licenseStatus?.isLicenseValid; const showEditingPopover = useStore((state) => state.showEditingPopover); + const restricted = page?.permissions && page?.permissions?.length > 0; const { definition: { styles, properties }, } = useStore((state) => state.pageSettings); @@ -199,7 +200,7 @@ export const PageMenuItem = withRouter(
- {licenseValid && page?.restricted && } + {licenseValid && restricted && }
{!shouldFreeze && ( diff --git a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PagePermission.jsx b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PagePermission.jsx index 095c33fd18..645bdcdc49 100644 --- a/frontend/src/AppBuilder/LeftSidebar/PageMenu/PagePermission.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/PageMenu/PagePermission.jsx @@ -26,6 +26,7 @@ export default function PagePermission({ darkMode }) { const setSelectedUsers = useStore((state) => state.setSelectedUsers); const pagePermission = useStore((state) => state.pagePermission); const setPagePermission = useStore((state) => state.setPagePermission); + const updatePageWithPermissions = useStore((state) => state.updatePageWithPermissions); const [pagePermissionType, setPagePermissionType] = useState('all'); const [showUserGroupSelect, toggleUserGroupSelect] = useState(false); @@ -45,7 +46,7 @@ export default function PagePermission({ darkMode }) { toggleUserGroupSelect(true); data?.length && setSelectedUserGroups( - data[0]?.users?.map((user) => ({ + data[0]?.groups?.map((user) => ({ label: user?.permissionGroup?.name, value: user?.permissionGroup?.id, count: user?.permissionGroup?.count, @@ -141,6 +142,7 @@ export default function PagePermission({ darkMode }) { .createPagePermission(appId, editingPage?.id, body) .then((data) => { toast.success('Permission successfully created!'); + updatePageWithPermissions(editingPage?.id, data); }) .catch(() => { toast.error('Permission could not be created. Please try again!'); @@ -164,6 +166,7 @@ export default function PagePermission({ darkMode }) { .updatePagePermission(appId, editingPage?.id, body) .then((data) => { toast.success('Permission successfully updated!'); + updatePageWithPermissions(editingPage?.id, data); }) .catch(() => { toast.error('Permission could not be updated. Please try again!'); @@ -180,6 +183,7 @@ export default function PagePermission({ darkMode }) { .deletePagePermission(appId, pageToDelete) .then((data) => { toast.success('Permission successfully deleted!'); + updatePageWithPermissions(pageToDelete, []); }) .catch(() => { toast.error('Permission could not be deleted. Please try again!'); diff --git a/frontend/src/AppBuilder/LeftSidebar/PageMenu/style.scss b/frontend/src/AppBuilder/LeftSidebar/PageMenu/style.scss index b3799e09ce..c4e4f97d33 100644 --- a/frontend/src/AppBuilder/LeftSidebar/PageMenu/style.scss +++ b/frontend/src/AppBuilder/LeftSidebar/PageMenu/style.scss @@ -305,6 +305,10 @@ } } + .react-select__menu-list { + overflow-y: unset !important; + } + .user-select-option { display: flex; align-items: center; diff --git a/frontend/src/AppBuilder/Viewer/PageGroup.jsx b/frontend/src/AppBuilder/Viewer/PageGroup.jsx index 120b5dfc68..0311115b09 100644 --- a/frontend/src/AppBuilder/Viewer/PageGroup.jsx +++ b/frontend/src/AppBuilder/Viewer/PageGroup.jsx @@ -15,7 +15,7 @@ const RenderPage = ({ page, currentPageId, switchPageWrapper, labelStyle, comput console.log({ isHomePage }); const iconName = isHomePage && !page.icon ? 'IconHome2' : page.icon; const IconElement = Icons?.[iconName] ?? Icons?.['IconFileDescription']; - return page.hidden || page.disabled ? null : ( + return (page.hidden || page.disabled) && page?.restricted ? null : ( switchPageWrapper(page?.id)} @@ -150,10 +150,15 @@ export const RenderPageAndPageGroup = ({ pages, labelStyle, computeStyles, darkM
{/* page.id)}> */} {filteredPages.map((page, index) => { - if (page.isPageGroup && page.children.length === 0 && labelStyle?.label?.hidden) { + if ( + page.isPageGroup && + page.children.length === 0 && + labelStyle?.label?.hidden && + !page.children.some((child) => child?.restricted === true) + ) { return null; } - if (page.children && page.isPageGroup) { + if (page.children && page.isPageGroup && !page.children.some((child) => child?.restricted === true)) { // if we are only displaying icons, we don't display the groups instead display separator to separate a page groups const renderSeparatorTop = index !== 0 && labelStyle?.label?.hidden; const renderSeparatorBottom = !filteredPages[index + 1]?.isPageGroup && labelStyle?.label?.hidden; @@ -193,7 +198,7 @@ export const RenderPageAndPageGroup = ({ pages, labelStyle, computeStyles, darkM )} ); - } else { + } else if (!page.isPageGroup) { return ( {}) => + (updatePaths, afterUpdateFn = () => {}, enableSave = true) => (pageId, values) => { return (set, get) => { set((state) => { @@ -57,7 +57,7 @@ const createPageUpdateCommand = const { app, currentVersionId } = get(); const diff = _.zipObject(updatePaths, values); - savePageChanges(app.appId, currentVersionId, pageId, diff); + if (enableSave) savePageChanges(app.appId, currentVersionId, pageId, diff); }; }; @@ -82,6 +82,8 @@ export const createPageMenuSlice = (set, get) => { state.editingPage = null; }); + const updatePageWithPermissions = createPageUpdateCommand(['permissions'], (state) => {}, false); + return { editingPage: null, showEditingPopover: false, @@ -194,6 +196,7 @@ export const createPageMenuSlice = (set, get) => { updatePageHandle(pageId, [value])(set, get); }, updatePageGroupName: (pageId, value) => updatePageGroupName(pageId, [value])(set, get), + updatePageWithPermissions: (pageId, value) => updatePageWithPermissions(pageId, [value])(set, get), // unsure about this one clonePage: async (pageId) => { const { diff --git a/server/ee b/server/ee index 7d46f023ce..78c6a52262 160000 --- a/server/ee +++ b/server/ee @@ -1 +1 @@ -Subproject commit 7d46f023cea42533c4a8ff387dcc1149553c4671 +Subproject commit 78c6a52262ba2df4a0771ae778178d2d74bb7517 diff --git a/server/src/modules/versions/services/create.service.ts b/server/src/modules/versions/services/create.service.ts index 12a24ac7c6..94b7f9783c 100644 --- a/server/src/modules/versions/services/create.service.ts +++ b/server/src/modules/versions/services/create.service.ts @@ -6,7 +6,7 @@ import { DataSource } from '@entities/data_source.entity'; import { DataSourceOptions } from '@entities/data_source_options.entity'; import { EventHandler, Target } from '@entities/event_handler.entity'; import { dbTransactionWrap } from '@helpers/database.helper'; -import { EntityManager } from 'typeorm'; +import { EntityManager, In } from 'typeorm'; import { Credential } from 'src/entities/credential.entity'; import * as uuid from 'uuid'; import { Page } from '@entities/page.entity'; @@ -22,6 +22,8 @@ import { DataSourcesRepository } from '@modules/data-sources/repository'; import { DataQueryRepository } from '@modules/data-queries/repository'; import { AppEnvironmentUtilService } from '@modules/app-environments/util.service'; import { IVersionsCreateService } from '../interfaces/services/ICreateService'; +import { PagePermission } from '@entities/page_permissions.entity'; +import { PageUser } from '@entities/page_users.entity'; @Injectable() export class VersionsCreateService implements IVersionsCreateService { @@ -401,6 +403,44 @@ export class VersionsCreateService implements IVersionsCreateService { homePageId = savedPage.id; } + const oldPermissions = await manager.find(PagePermission, { + where: { pageId: page.id }, + }); + + const newPermissions = oldPermissions.map((permission) => { + return manager.create(PagePermission, { + ...permission, + id: undefined, + pageId: oldPageToNewPageMapping[permission.pageId], + }); + }); + + await manager.save(PagePermission, newPermissions); + + const permissionIdMap = new Map(); + oldPermissions.forEach((oldPerm, index) => { + const newPerm = newPermissions[index]; + permissionIdMap.set(oldPerm.id, newPerm.id); + }); + + const oldPermissionIds = oldPermissions.map((p) => p.id); + + const oldPageUsers = await manager.find(PageUser, { + where: { + pagePermissionsId: In(oldPermissionIds), + }, + }); + + const newPageUsers = oldPageUsers.map((pu) => + manager.create(PageUser, { + ...pu, + id: undefined, + pagePermissionsId: permissionIdMap.get(pu.pagePermissionsId), + }) + ); + + await manager.save(PageUser, newPageUsers); + const pageEvents = allEvents.filter((event) => event.sourceId === page.id); pageEvents.forEach(async (event, index) => {