Added design fix phase 2

This commit is contained in:
kriks7iitk 2024-06-28 13:49:03 +05:30
parent b3f1f1c857
commit 9c57ccda8a
10 changed files with 189 additions and 58 deletions

View file

@ -52,7 +52,7 @@ function AddResourcePermissionsMenu({ openAddPermissionModal, resourcesOptions,
openAddPermissionModal();
}}
>
App
Add apps
</ButtonSolid>
</div>
);

View file

@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useState } from 'react';
import GroupChipTD from '@/ManageGroupPermissionsV2/ResourceChip';
import '../ManageGroupPermissionsV2/groupPermissions.theme.scss';
import SolidIcon from '@/_ui/Icon/SolidIcons';
@ -10,8 +10,7 @@ function AppResourcePermissions({
currentGroupPermission,
openEditPermissionModal,
}) {
console.log('Logging permissions');
console.log(permissions);
const [onHover, setHover] = useState(false);
const isRoleGroup = currentGroupPermission.name == 'admin';
const disableEditUpdate = currentGroupPermission.name == 'end-user';
const appsPermissions = permissions.appsGroupPermissions;
@ -21,7 +20,18 @@ function AppResourcePermissions({
if (apps.length == 0 || permissions.isAll) apps = ['All apps'];
return (
<div className="manage-resource-permission">
<div
className="manage-resource-permission"
onMouseOver={() => {
setHover(true);
}}
onMouseOut={() => {
setHover(false);
}}
onClick={() => {
!isRoleGroup && openEditPermissionModal(permissions);
}}
>
<div className="resource-name">
<SolidIcon name="app" width="20px" className="resource-icon" />
<div className="resource-text">{permissions.name}</div>
@ -36,6 +46,7 @@ function AppResourcePermissions({
updateOnlyGranularPermissions(permissions, {
canEdit: !appsPermissions.canEdit,
canView: appsPermissions.canEdit,
...(!appsPermissions.canEdit && { hideFromDashboard: false }),
});
}}
checked={appsPermissions.canEdit}
@ -77,7 +88,7 @@ function AppResourcePermissions({
});
}}
checked={appsPermissions.hideFromDashboard}
disabled={isRoleGroup}
disabled={isRoleGroup || !appsPermissions.canView}
data-cy="app-delete-checkbox"
/>
<span className="form-check-label" data-cy="app-delete-label">
@ -91,15 +102,17 @@ function AppResourcePermissions({
<GroupChipTD groups={apps} />
</div>
<div className="edit-icon-container">
<ButtonSolid
leftIcon="editrectangle"
className="edit-permission-custom"
iconWidth="14"
onClick={() => {
openEditPermissionModal(permissions);
}}
disabled={isRoleGroup}
/>
{onHover && (
<ButtonSolid
leftIcon="editrectangle"
className="edit-permission-custom"
iconWidth="14"
onClick={() => {
openEditPermissionModal(permissions);
}}
disabled={isRoleGroup}
/>
)}
</div>
</div>
);

View file

@ -13,6 +13,8 @@ import '../ManageGroupPermissionsV2/groupPermissions.theme.scss';
import ChangeRoleModal from '@/ManageGroupPermissionResourcesV2/ChangeRoleModal';
import AppResourcePermissions from '@/ManageGranularAccess/AppResourcePermission';
import AddResourcePermissionsMenu from '@/ManageGranularAccess/AddResourcePermissionsMenu';
import { ConfirmDialog } from '@/_components';
import { ToolTip } from '@/_components/ToolTip';
class ManageGranularAccessComponent extends React.Component {
constructor(props) {
@ -46,6 +48,8 @@ class ManageGranularAccessComponent extends React.Component {
updateParam: {},
updatingPermission: {},
updateType: '',
deleteConfirmationModal: false,
deletingPermissions: false,
};
}
@ -92,6 +96,9 @@ class ManageGranularAccessComponent extends React.Component {
deleteGranularPermissions = () => {
const { currentEditingPermissions } = this.state;
this.setState({
deleteGranularPermissions: true,
});
groupPermissionV2Service
.deleteGranularPermission(currentEditingPermissions.id)
.then(() => {
@ -101,6 +108,12 @@ class ManageGranularAccessComponent extends React.Component {
})
.catch((err) => {
toast.error(err.error);
})
.finally(() => {
this.setState({
deleteConfirmationModal: false,
deleteGranularPermissions: false,
});
});
};
@ -128,13 +141,16 @@ class ManageGranularAccessComponent extends React.Component {
})
.catch(({ error }) => {
this.closeAddPermissionModal();
this.props.updateParentState({
showEditRoleErrorModal: true,
errorTitle: error?.title ? error?.title : 'Cannot remove last admin',
errorMessage: error.error,
errorIconName: 'usergear',
errorListItems: error.data,
});
if (error?.error) {
this.props.updateParentState({
showEditRoleErrorModal: true,
errorTitle: error?.title ? error?.title : 'Cannot add granular permissions',
errorMessage: error.error,
errorIconName: 'usergear',
errorListItems: error.data,
});
}
toast.error(error);
});
// .then(())
};
@ -237,8 +253,6 @@ class ManageGranularAccessComponent extends React.Component {
allowRoleChange,
};
console.log(body);
groupPermissionV2Service
.updateGranularPermission(currentEditingPermissions.id, body)
.then(() => {
@ -360,11 +374,14 @@ class ManageGranularAccessComponent extends React.Component {
updateParam,
updatingPermission,
updateType,
deleteConfirmationModal,
deletingPermissions,
} = this.state;
const resourcesOptions = ['Apps'];
const currentGroupPermission = this.props?.groupPermission;
const isRoleGroup = currentGroupPermission.name == 'admin';
const defaultGroup = currentGroupPermission.type === 'default';
const showPermissionInfo = currentGroupPermission.name == 'admin' || currentGroupPermission.name == 'end-user';
const disableEditUpdate = currentGroupPermission.name == 'end-user';
const addPermissionTooltipMessage = !newPermissionName
@ -374,6 +391,16 @@ class ManageGranularAccessComponent extends React.Component {
: '';
return (
<div className="row granular-access-container justify-content-center">
<ConfirmDialog
show={deleteConfirmationModal}
message={'This permissions will be permanently deleted. Do you want to continue?'}
confirmButtonLoading={deletingPermissions}
onConfirm={() => this.deleteGranularPermissions()}
onCancel={() => {
this.setState({ deleteConfirmationModal: false, deletingPermissions: false });
}}
darkMode={this.props.darkMode}
/>
<ChangeRoleModal
showAutoRoleChangeModal={showAutoRoleChangeModal}
autoRoleChangeModalList={autoRoleChangeModalList}
@ -414,7 +441,12 @@ class ManageGranularAccessComponent extends React.Component {
iconWidth="15px"
className="icon-class"
variant="tertiary"
onClick={this.deleteGranularPermissions}
onClick={() => {
this.setState({
deleteConfirmationModal: true,
showAddPermissionModal: false,
});
}}
/>
</div>
)}
@ -464,7 +496,8 @@ class ManageGranularAccessComponent extends React.Component {
initialPermissionState: {
...prevState.initialPermissionState,
canEdit: !prevState.initialPermissionState.canEdit,
...(!prevState.initialPermissionState.canEdit && { canView: false }),
canView: prevState.initialPermissionState.canEdit,
...(prevState.initialPermissionState.canEdit && { hideFromDashboard: false }),
},
}));
}}
@ -488,7 +521,8 @@ class ManageGranularAccessComponent extends React.Component {
initialPermissionState: {
...prevState.initialPermissionState,
canView: !prevState.initialPermissionState.canView,
...(!prevState.initialPermissionState.canView && { canEdit: false }),
canEdit: prevState.initialPermissionState.canView,
...(prevState.initialPermissionState.canEdit && { hideFromDashboard: false }),
},
}));
}}
@ -502,6 +536,7 @@ class ManageGranularAccessComponent extends React.Component {
<input
className="form-check-input"
type="checkbox"
disabled={!initialPermissionState.canView}
checked={initialPermissionState.hideFromDashboard}
onClick={() => {
this.setState((prevState) => ({
@ -617,8 +652,8 @@ class ManageGranularAccessComponent extends React.Component {
updateOnlyGranularPermissions={this.updateOnlyGranularPermissions}
permissions={permissions}
currentGroupPermission={currentGroupPermission}
key={index}
openEditPermissionModal={this.openEditPermissionModal}
key={index}
/>
))}
</>

View file

@ -67,6 +67,9 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.groupPermissionId && this.props.groupPermissionId !== prevProps.groupPermissionId) {
this.fetchGroupAndResources(this.props.groupPermissionId);
this.setState({
showUserSearchBox: false,
});
}
}
@ -363,6 +366,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
updateParam: {},
isLoadingGroup: false,
isLoadingUsers: false,
isAddingUsers: false,
});
};
@ -518,7 +522,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
isLoading={isLoadingGroup || isLoadingUsers}
/>
<div className="org-users-page animation-fade">
{isLoadingGroup ? (
{isLoadingGroup || isLoadingUsers ? (
<Loader />
) : (
<div>
@ -527,7 +531,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
className="font-weight-500 tj-text-md"
// data-cy={`${this.props.selectedGroup.toLowerCase().replace(/\s+/g, '-')}-title`}
>
{this.props.selectedGroup}
{`${this.props.selectedGroup} (${usersInGroup.length})`}
</p>
{groupPermission.type === 'default' && (
<ToolTip message={'Every user must be part of one default group'}>
@ -557,7 +561,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
<nav className="nav nav-tabs groups-sub-header-wrap">
<a
onClick={() => this.setState({ currentTab: 'users' })}
onClick={() => this.setState({ currentTab: 'users', showUserSearchBox: false })}
className={cx('nav-item nav-link', { active: currentTab === 'users' })}
data-cy="users-link"
>
@ -572,7 +576,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
</a>
<a
onClick={() => this.setState({ currentTab: 'permissions' })}
onClick={() => this.setState({ currentTab: 'permissions', showUserSearchBox: false })}
className={cx('nav-item nav-link', { active: currentTab === 'permissions' })}
data-cy="permissions-link"
>
@ -589,7 +593,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
)}
</a>
<a
onClick={() => this.setState({ currentTab: 'granularAccess' })}
onClick={() => this.setState({ currentTab: 'granularAccess', showUserSearchBox: false })}
className={cx('nav-item nav-link', { active: currentTab === 'granularAccess' })}
data-cy="granular-access-link"
>

View file

@ -277,7 +277,11 @@ class ManageGroupPermissionsComponent extends React.Component {
this.fetchGroups('new');
})
.catch(({ error }) => {
toast.error(error);
toast.error(error, {
style: {
maxWidth: '500px !important',
},
});
this.setState({
creatingGroup: false,
showNewGroupForm: true,

View file

@ -178,15 +178,14 @@
.modal-body {
border: none;
padding: 12px 12px;
margin-left: 15px;
margin-bottom: 10px;
padding: 12px 12px 22px 27px;
.item-list {
display: flex;
gap: 5px;
flex-direction: column;
max-height: 100px; /* Set a fixed height or max-height */
overflow-y: auto; /* Enable vertical scrolling */
overflow-y: scroll; /* Enable vertical scrolling */
}
}
}
@ -312,6 +311,70 @@
max-width: unset !important;
}
}
.role-name-cell {
transition: 0.3s all;
border-radius: 6px;
width: 120px !important;
position: relative !important;
overflow: visible !important;
.groups-name-container {
display: flex;
column-gap: 8px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 185px;
}
.group-chip {
padding: 2px 8px;
margin: 0;
border-radius: 6px;
background-color: var(--slate3);
// color: var(--slate11);
min-height: 24px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 95px;
}
.all-groups-list {
position: absolute;
width: 100%;
top: 41px;
display: flex;
flex-direction: column;
background: var(--slate1);
align-items: flex-start;
border-radius: 6px;
border: 1px solid var(--slate1);
box-shadow: 0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08);
padding: 9px 10px;
gap: 10px;
cursor: default;
max-height: 240px;
overflow: auto;
left: 0px;
z-index: 1;
}
}
.role-name-cell[data-active="true"] {
display: flex;
background: var(--gray5) !important;
justify-content: center;
.groups-name-container {
padding-left: 6px;
justify-content: center;
}
.group-chip {
max-width: unset !important;
}
}
.edit-icon-container{
@ -337,6 +400,8 @@
}
.manage-resource-permission{
transition: background-color 0.3s ease;
border-bottom: 1px solid var(--slate5);
display: flex;
align-items:baseline;
@ -349,7 +414,7 @@
.resource-name {
display: flex;
flex-direction: column !important;
flex-direction: row !important;
gap: 10px;
@ -361,7 +426,10 @@
}
}
}
&:hover {
background-color: var(--slate3);
}
}
@ -376,4 +444,4 @@
.custom-input-error:focus {
border-color: red !important; /* Change border color when input is focused */
}
}

View file

@ -119,7 +119,6 @@ export function UserGroupsSelect(props) {
multiValue: (base) => ({
...base,
borderRadius: '6px',
height: '16px',
backgroundColor: 'var(--slate3)',
color: 'var(--slate11)',
'.selected-value': {
@ -136,12 +135,6 @@ export function UserGroupsSelect(props) {
paddingLeft: '0px',
...(state.data.isFixed && { display: 'none' }),
}),
valueContainer: (base) => ({
...base,
minHeight: '32px !important',
maxHeight: '32px !important',
padding: '0px 5px 0px 5px !important',
}),
input: (base) => ({
...base,
input: {
@ -151,8 +144,6 @@ export function UserGroupsSelect(props) {
}),
control: (base) => ({
...base,
height: '32px !important',
minHeight: '32px !important',
outline: 'none',
border: '1px solid var(--slate7)',
boxShadow: 'none',

View file

@ -77,8 +77,8 @@
border-bottom: 1px solid var(--slate5);
margin: 0; /* Ensure no margin */
padding: 0; /* Ensure no padding */
min-height: calc(100% - 48px - 16px - 55px - 50px);
max-height: calc(100% - 48px - 16px - 55px - 50px);
min-height: calc(100% - 48px - 16px - 55px - 70px);
max-height: calc(100% - 48px - 16px - 55px - 70px);
}
.permission-body-two {
@ -87,8 +87,8 @@
border-bottom: 1px solid var(--slate5);
margin: 0; /* Ensure no margin */
padding: 0; /* Ensure no padding */
min-height: calc(100% - 16px - 55px - 34px);
max-height: calc(100% - 16px - 55px - 34px);
min-height: calc(100% - 16px - 55px - 54px);
max-height: calc(100% - 16px - 55px - 54px);
}
.side-button-cont {
@ -99,6 +99,7 @@
flex-shrink: 0; /* Prevent shrinking */
margin: 0; /* Ensure no margin */
padding: 12px; /* Ensure no padding */
margin-bottom: 15px;
.add-icon {
width: 135px;

View file

@ -87,7 +87,8 @@ export function viewableAppsQueryUsingPermissions(
),
];
const viewableAppsQb = createQueryBuilder(AppBase, 'viewable_apps')
const viewableAppsQb = manager
.createQueryBuilder(AppBase, 'viewable_apps')
.innerJoin('viewable_apps.user', 'user')
.addSelect(['user.firstName', 'user.lastName'])
.where('viewable_apps.organization_id = :organizationId', { organizationId: user.organizationId });
@ -97,7 +98,7 @@ export function viewableAppsQueryUsingPermissions(
}
if (!userAppPermissions.hideAll && !(userAppPermissions.isAllEditable || userAppPermissions.isAllViewable)) {
viewableAppsQb.where('viewable_apps IN (:...viewableApps)', {
viewableAppsQb.where('viewable_apps.id IN (:...viewableApps)', {
viewableApps,
});
}

View file

@ -16,6 +16,7 @@ import {
import { GranularPermissions } from 'src/entities/granular_permissions.entity';
import { TOOLJET_RESOURCE } from 'src/constants/global.constant';
import { getUserPermissionsQuery } from '@module/permissions/utility/permission-ability.utility';
import { App } from 'src/entities/app.entity';
@Injectable()
export class AbilityService {
@ -50,12 +51,15 @@ export class AbilityService {
}, DEFAULT_USER_PERMISSIONS);
const { resources } = resourcePermissionsObject;
if (resources && resources.some((item) => item.resource === TOOLJET_RESOURCE.APP)) {
userPermissions[TOOLJET_RESOURCE.APP] = this.createUserAppsPermissions(appsGranularPermissions);
userPermissions[TOOLJET_RESOURCE.APP] = await this.createUserAppsPermissions(appsGranularPermissions, user);
}
return userPermissions;
}
private createUserAppsPermissions(appsGranularPermissions: GranularPermissions[]): UserAppsPermissions {
private async createUserAppsPermissions(
appsGranularPermissions: GranularPermissions[],
user: User
): Promise<UserAppsPermissions> {
const userAppsPermissions: UserAppsPermissions = appsGranularPermissions.reduce((acc, permission) => {
const appsPermission = permission?.appsGroupPermissions;
const groupApps = appsPermission?.groupApps ? appsPermission.groupApps.map((item) => item.appId) : [];
@ -70,6 +74,16 @@ export class AbilityService {
hideAll: acc.hideAll || (appsPermission.hideFromDashboard && permission.isAll),
};
}, DEFAULT_USER_APPS_PERMISSIONS);
await dbTransactionWrap(async (manager: EntityManager) => {
const appsOwnedByUser = await manager.find(App, {
where: { userId: user.id, organizationId: user.organizationId },
});
const appsIdOwnedByUser = appsOwnedByUser.map((app) => app.id);
userAppsPermissions.editableAppsId = Array.from(
new Set([...userAppsPermissions.editableAppsId, ...appsIdOwnedByUser])
);
});
return userAppsPermissions;
}
}