RolePermission kopyalama

This commit is contained in:
Sedat ÖZTÜRK 2026-03-30 13:53:50 +03:00
parent b0dd72ec57
commit 9fb838dcba
3 changed files with 108 additions and 9 deletions

View file

@ -1182,6 +1182,12 @@
"en": "Change permissions", "en": "Change permissions",
"tr": "İzinleri değiştir" "tr": "İzinleri değiştir"
}, },
{
"resourceName": "Platform",
"key": "AbpIdentity.Roles.CopyPermissions",
"en": "Copy permissions",
"tr": "İzinleri kopyala"
},
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "AbpIdentity.Users", "key": "AbpIdentity.Users",
@ -16782,7 +16788,7 @@
}, },
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "App.SqlQueryManager.SelectPlaceholder", "key": "App.Select",
"en": "— Select —", "en": "— Select —",
"tr": "— Seçiniz —" "tr": "— Seçiniz —"
}, },

View file

@ -10,7 +10,7 @@ import {
PermissionWithGroupName, PermissionWithGroupName,
PermissionWithStyle, PermissionWithStyle,
} from '@/proxy/admin/models' } from '@/proxy/admin/models'
import { getPermissions, updatePermissions } from '@/services/identity.service' import { getPermissions, getRoles, updatePermissions } from '@/services/identity.service'
import { useStoreActions, useStoreState } from '@/store' import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { ChangeEvent, useEffect, useMemo, useState } from 'react' import { ChangeEvent, useEffect, useMemo, useState } from 'react'
@ -311,6 +311,55 @@ function RolesPermission({
fetchDataPermissions() fetchDataPermissions()
}, [name]) }, [name])
// --- Copy Permissions State and Logic ---
const [roleList, setRoleList] = useState<string[]>([])
// --- Copy Permissions Dialog State ---
const [copyDialogOpen, setCopyDialogOpen] = useState(false)
const [copyDialogRole, setCopyDialogRole] = useState('')
// Fetch all roles for select (except current)
useEffect(() => {
async function fetchRoles() {
try {
const res = await getRoles()
setRoleList(res.data.items?.map((r: any) => r.name) || [])
} catch (e) {
setRoleList([])
}
}
fetchRoles()
}, [copyDialogOpen])
// Dialog üzerinden kopyalama işlemi
const handleCopyDialogConfirm = async () => {
if (!copyDialogRole || !permissionList) return
setIsLoading(true)
try {
const res = await getPermissions(providerName, copyDialogRole)
const sourcePerms = getPermissionsWithGroupName(res.data?.groups)
const grantedNames = new Set(sourcePerms.filter((p) => p.isGranted).map((p) => p.name))
permissionList.groups.forEach((group) => {
group.permissions.forEach((perm) => {
perm.isGranted = grantedNames.has(perm.name)
})
})
setPermissionList({ ...permissionList })
changeGroup(selectedGroup?.name)
toast.push(<Notification title={translate('::PermissionsCopied')} type="success" />, {
placement: 'top-end',
})
setCopyDialogOpen(false)
setCopyDialogRole('')
} catch (e) {
toast.push(<Notification title={translate('::CopyFailed')} type="danger" />, {
placement: 'top-end',
})
} finally {
setIsLoading(false)
}
}
return permissionList ? ( return permissionList ? (
<Container> <Container>
<Dialog <Dialog
@ -336,7 +385,6 @@ function RolesPermission({
{translate('AbpPermissionManagement::SelectAllInThisTab')} {translate('AbpPermissionManagement::SelectAllInThisTab')}
</Checkbox> </Checkbox>
<Button size="sm" variant="plain" onClick={handleExpandAll} icon={<FaChevronRight />}> <Button size="sm" variant="plain" onClick={handleExpandAll} icon={<FaChevronRight />}>
{translate('::ListForms.ListFormEdit.ExpandAll')} {translate('::ListForms.ListFormEdit.ExpandAll')}
</Button> </Button>
@ -422,7 +470,13 @@ function RolesPermission({
</div> </div>
</div> </div>
</div> </div>
<div className="text-right mt-6"> <div className="flex justify-between items-center mt-6">
<div className="flex items-center">
<Button variant="solid" color="sky-500" onClick={() => setCopyDialogOpen(true)}>
{translate('::AbpIdentity.Roles.CopyPermissions')}
</Button>
</div>
<div className="text-right">
<Button className="ltr:mr-2 rtl:ml-2" variant="plain" onClick={onDialogClose}> <Button className="ltr:mr-2 rtl:ml-2" variant="plain" onClick={onDialogClose}>
{translate('::Cancel')} {translate('::Cancel')}
</Button> </Button>
@ -430,6 +484,45 @@ function RolesPermission({
{isLoading ? translate('::SavingWithThreeDot') : translate('::Save')} {isLoading ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button> </Button>
</div> </div>
</div>
</Dialog>
{/* Copy Permissions Dialog */}
<Dialog
isOpen={copyDialogOpen}
width="min(400px, 95vw)"
onClose={() => setCopyDialogOpen(false)}
>
<h5 className="mb-2">{translate('::AbpIdentity.Roles.CopyPermissions')}</h5>
<div className="mb-4">
<select
className="border rounded px-2 py-1 w-full"
value={copyDialogRole}
onChange={(e) => setCopyDialogRole(e.target.value)}
>
<option value="">{translate('::App.Select')}</option>
{roleList
.filter((role) => role !== name)
.map((role) => (
<option key={role} value={role}>
{role}
</option>
))}
</select>
</div>
<div className="flex justify-end gap-2">
<Button variant="plain" onClick={() => setCopyDialogOpen(false)}>
{translate('::Cancel')}
</Button>
<Button
variant="solid"
onClick={handleCopyDialogConfirm}
disabled={!copyDialogRole || isLoading}
loading={isLoading}
>
{translate('::Copy')}
</Button>
</div>
</Dialog> </Dialog>
</Container> </Container>
) : ( ) : (

View file

@ -2057,7 +2057,7 @@ const SqlTableDesignerDialog = ({
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm dark:bg-gray-700 dark:text-white focus:ring-2 focus:ring-indigo-500" className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm dark:bg-gray-700 dark:text-white focus:ring-2 focus:ring-indigo-500"
> >
<option value=""> <option value="">
{translate('::App.SqlQueryManager.SelectPlaceholder')} {translate('::App.Select')}
</option> </option>
{columns {columns
.filter((c) => c.columnName.trim()) .filter((c) => c.columnName.trim())
@ -2082,7 +2082,7 @@ const SqlTableDesignerDialog = ({
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm dark:bg-gray-700 dark:text-white focus:ring-2 focus:ring-indigo-500" className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm dark:bg-gray-700 dark:text-white focus:ring-2 focus:ring-indigo-500"
> >
<option value=""> <option value="">
{translate('::App.SqlQueryManager.SelectPlaceholder')} {translate('::App.Select')}
</option> </option>
{dbTables.map((t) => ( {dbTables.map((t) => (
<option key={`${t.schemaName}.${t.tableName}`} value={t.tableName}> <option key={`${t.schemaName}.${t.tableName}`} value={t.tableName}>