Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(console): support org permission management on new org template page #5603

Merged
merged 4 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/console/src/consts/page-tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ export enum EnterpriseSsoDetailsTabs {
}

export enum OrganizationTemplateTabs {
OrgRoles = 'org-roles',
OrgPermissions = 'org-permissions',
OrganizationRoles = 'organization-roles',
OrganizationPermissions = 'organization-permissions',
}
15 changes: 9 additions & 6 deletions packages/console/src/containers/ConsoleContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ import Mfa from '@/pages/Mfa';
import NotFound from '@/pages/NotFound';
import OrganizationDetails from '@/pages/OrganizationDetails';
import OrganizationTemplate from '@/pages/OrganizationTemplate';
import OrgPermissions from '@/pages/OrganizationTemplate/OrgPermissions';
import OrgRoles from '@/pages/OrganizationTemplate/OrgRoles';
import OrganizationPermissions from '@/pages/OrganizationTemplate/OrganizationPermissions';
import OrganizationRoles from '@/pages/OrganizationTemplate/OrganizationRoles';
import Organizations from '@/pages/Organizations';
import OrganizationGuide from '@/pages/Organizations/Guide';
import Profile from '@/pages/Profile';
Expand Down Expand Up @@ -190,12 +190,15 @@ function ConsoleContent() {
<Route path="organization-template" element={<OrganizationTemplate />}>
<Route
index
element={<Navigate replace to={OrganizationTemplateTabs.OrgRoles} />}
element={<Navigate replace to={OrganizationTemplateTabs.OrganizationRoles} />}
/>
<Route path={OrganizationTemplateTabs.OrgRoles} element={<OrgRoles />} />
<Route
path={OrganizationTemplateTabs.OrgPermissions}
element={<OrgPermissions />}
path={OrganizationTemplateTabs.OrganizationRoles}
element={<OrganizationRoles />}
/>
<Route
path={OrganizationTemplateTabs.OrganizationPermissions}
element={<OrganizationPermissions />}
/>
</Route>
)}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { type OrganizationScope } from '@logto/schemas';
import { cond, type Nullable } from '@silverhand/essentials';
import { useForm } from 'react-hook-form';
import { toast } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
import ReactModal from 'react-modal';

import Button from '@/ds-components/Button';
import FormField from '@/ds-components/FormField';
import ModalLayout from '@/ds-components/ModalLayout';
import TextInput from '@/ds-components/TextInput';
import useApi from '@/hooks/use-api';
import * as modalStyles from '@/scss/modal.module.scss';
import { trySubmitSafe } from '@/utils/form';

type Props = {
/**
* The organization permission data to edit. If null, the modal will be in create mode.
*/
data: Nullable<OrganizationScope>;
onClose: () => void;
};

type FormData = Pick<OrganizationScope, 'name' | 'description'>;

const organizationScopesPath = 'api/organization-scopes';

/** A modal that allows users to create or edit an organization permission. */
function OrganizationPermissionModal({ data, onClose }: Props) {
const isCreateMode = data === null;

const { t } = useTranslation(undefined, {
keyPrefix: 'admin_console',
});

const api = useApi();

const {
register,
formState: { errors, isSubmitting },
handleSubmit,
} = useForm<FormData>(cond(data && { defaultValues: data }));

const submit = handleSubmit(
trySubmitSafe(async (json) => {
await (isCreateMode
? api.post(organizationScopesPath, {
json,
})
: api.patch(`${organizationScopesPath}/${data.id}`, {
json,
}));
toast.success(
t(isCreateMode ? 'organization_template.permissions.created' : 'general.saved', {
name: json.name,
})
);
onClose();
})
);

return (
<ReactModal
isOpen
className={modalStyles.content}
overlayClassName={modalStyles.overlay}
onRequestClose={onClose}
>
<ModalLayout
title={`organization_template.permissions.${isCreateMode ? 'create' : 'edit'}_title`}
footer={
<>
{!isCreateMode && (
<Button title="general.cancel" isLoading={isSubmitting} onClick={onClose} />
)}
<Button
type="primary"
title={
isCreateMode
? 'organization_template.permissions.create_permission'
: 'general.save'
}
isLoading={isSubmitting}
onClick={submit}
/>
</>
}
onClose={onClose}
>
<FormField isRequired title="organization_template.permissions.permission_field_name">
<TextInput
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={isCreateMode}
readOnly={!isCreateMode}
placeholder="read:appointment"
error={Boolean(errors.name)}
{...register('name', { required: true })}
/>
</FormField>
<FormField title="organization_template.permissions.description_field_name">
<TextInput
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={!isCreateMode}
placeholder={t('organization_template.permissions.description_field_placeholder')}
error={Boolean(errors.description)}
{...register('description')}
/>
</FormField>
</ModalLayout>
</ReactModal>
);
}

export default OrganizationPermissionModal;
Loading
Loading