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(NET-1545): add tour to user management page #763

Merged
merged 2 commits into from
Sep 18, 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
5 changes: 3 additions & 2 deletions src/components/modals/add-user-modal/AddUserModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface AddUserModalProps {
addUserButtonRef?: Ref<HTMLDivElement>;
addUserNameInputRef?: Ref<HTMLDivElement>;
addUserPasswordInputRef?: Ref<HTMLDivElement>;
addUserSetAsAdminCheckboxRef?: Ref<HTMLDivElement>;
createUserModalPlatformAccessLevelRef?: Ref<HTMLDivElement>;
}

type CreateUserForm = User & {
Expand Down Expand Up @@ -62,6 +62,7 @@ export default function AddUserModal({
onCancel,
addUserNameInputRef,
addUserPasswordInputRef,
createUserModalPlatformAccessLevelRef,
}: AddUserModalProps) {
const [form] = Form.useForm<CreateUserForm>();
const [notify, notifyCtx] = notification.useNotification();
Expand Down Expand Up @@ -343,7 +344,7 @@ export default function AddUserModal({
<Divider />

<Row>
<Col xs={24}>
<Col xs={24} ref={createUserModalPlatformAccessLevelRef}>
<Skeleton active loading={isLoadingPlatformRoles} paragraph={false}>
<Form.Item
name="platform_role_id"
Expand Down
17 changes: 13 additions & 4 deletions src/components/modals/invite-user-modal/InviteUserModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
Tooltip,
Typography,
} from 'antd';
import { MouseEvent, useCallback, useEffect, useMemo, useState } from 'react';
import { MouseEvent, Ref, useCallback, useEffect, useMemo, useState } from 'react';
import '../CustomModal.scss';
import { extractErrorMsg } from '@/utils/ServiceUtils';
import { User, UserGroup, UserInvite, UserRole, UserRoleId } from '@/models/User';
Expand All @@ -35,6 +35,8 @@ interface InviteUserModalProps {
onInviteFinish: () => any;
onCancel?: (e: MouseEvent<HTMLButtonElement>) => void;
onClose?: () => void;
inviteUserModalPlatformAccessLevelRef: Ref<HTMLDivElement>;
inviteUserModalEmailAddressesInputRef: Ref<HTMLDivElement>;
}

interface UserInviteForm {
Expand Down Expand Up @@ -70,7 +72,14 @@ const groupsTabKey = 'groups';
const customRolesTabKey = 'custom-roles';
const defaultTabKey = groupsTabKey;

export default function InviteUserModal({ isOpen, onInviteFinish, onClose, onCancel }: InviteUserModalProps) {
export default function InviteUserModal({
isOpen,
onInviteFinish,
onClose,
onCancel,
inviteUserModalPlatformAccessLevelRef,
inviteUserModalEmailAddressesInputRef,
}: InviteUserModalProps) {
const [form] = Form.useForm<UserInviteForm>();
const [notify, notifyCtx] = notification.useNotification();
const { isServerEE } = useServerLicense();
Expand Down Expand Up @@ -372,7 +381,7 @@ export default function InviteUserModal({ isOpen, onInviteFinish, onClose, onCan
<>
<Form name="invite-user-form" form={form} layout="vertical">
<Row>
<Col xs={24}>
<Col xs={24} ref={inviteUserModalEmailAddressesInputRef}>
<Form.Item
label="Email address(es)"
name="user_emails"
Expand All @@ -388,7 +397,7 @@ export default function InviteUserModal({ isOpen, onInviteFinish, onClose, onCan
<Divider />

<Row>
<Col xs={24}>
<Col xs={24} ref={inviteUserModalPlatformAccessLevelRef}>
<Skeleton active loading={isLoadingPlatformRoles} paragraph={false}>
<Form.Item
name="platform_role_id"
Expand Down
9 changes: 9 additions & 0 deletions src/constants/LinkAndImageConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ const ROUTE_LOCAL_NETWORK_TRAFFIC_LINK = 'https://docs.netmaker.io/'; /// NEED T
const HOW_TO_ADD_USERS_TO_NETWORK = 'https://www.netmaker.io/resources/how-to-add-users-to-netmaker-saas';
const USER_MGMT_DOCS_URL = 'https://docs.netmaker.io/#';
const UI_DOCS_URL = 'https://docs.v2.netmaker.io/guide/references/user-interface';
const USER_MGMT_DOCS_NETWORK_ROLES_URL =
'https://docs.v2.netmaker.io/guide/netmaker-professional/users-in-netmaker-professional#network-roles';
const USER_MGMT_DOCS_USER_GROUPS_URL =
'https://docs.v2.netmaker.io/guide/netmaker-professional/users-in-netmaker-professional#user-groups';
const USER_MGMT_DOCS_INVITES_URL =
'https://docs.v2.netmaker.io/guide/netmaker-professional/users-in-netmaker-professional#adding-users__user-invite';

const EGRESS_IMG = '/egress.webp';
const RAG_IMG = '/rag.webp';
Expand All @@ -29,6 +35,9 @@ export const ExternalLinks = {
HOW_TO_ADD_USERS_TO_NETWORK,
USER_MGMT_DOCS_URL,
UI_DOCS_URL,
USER_MGMT_DOCS_NETWORK_ROLES_URL,
USER_MGMT_DOCS_USER_GROUPS_URL,
USER_MGMT_DOCS_INVITES_URL,
};

export const AppImages = {
Expand Down
74 changes: 66 additions & 8 deletions src/pages/users/CreateNetworkRolePage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useStore } from '@/store/store';
import { PlusOutlined } from '@ant-design/icons';
import { InfoCircleOutlined, PlusOutlined } from '@ant-design/icons';
import {
Button,
Card,
Expand All @@ -16,9 +16,11 @@ import {
Tabs,
TabsProps,
theme,
Tour,
TourProps,
Typography,
} from 'antd';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { PageProps } from '../../models/Page';
import './UsersPage.scss';
import { extractErrorMsg } from '@/utils/ServiceUtils';
Expand Down Expand Up @@ -77,6 +79,13 @@ export default function CreateNetworkRolePage(props: PageProps) {
const [isLoadingNetworks, setIsLoadingNetworks] = useState(true);
const [searchRag, setSearchRag] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [isTourOpen, setIsTourOpen] = useState(false);

const networkRoleName = useRef(null);
const networkName = useRef(null);
const networkAdminAccess = useRef(null);
const networkRolePermissions = useRef(null);
const createRoleButton = useRef(null);

const networkVal = Form.useWatch('network', metadataForm);

Expand Down Expand Up @@ -489,6 +498,39 @@ export default function CreateNetworkRolePage(props: PageProps) {
],
);

const createNetworkRoleTourSteps: TourProps['steps'] = [
{
title: 'Role Name',
description: 'Set network role name',
target: () => networkRoleName.current,
placement: 'bottom',
},
{
title: 'Network',
description: 'Select the network this role will apply to',
target: () => networkName.current,
placement: 'bottom',
},
{
title: 'Admin Access',
description: 'Assign admin access to the network',
target: () => networkAdminAccess.current,
placement: 'bottom',
},
{
title: 'Role Permissions',
description: 'Set role permissions for the network, turn on the permissions you want to grant',
target: () => networkRolePermissions.current,
placement: 'bottom',
},
{
title: 'Create Role',
description: 'Click here to create the network role',
target: () => createRoleButton.current,
placement: 'bottom',
},
];

useEffect(() => {
loadNetworks();
}, [isServerEE, loadNetworks]);
Expand All @@ -509,6 +551,16 @@ export default function CreateNetworkRolePage(props: PageProps) {
Create a Network Role
</Typography.Title>
</Col>
<Col xs={24} lg={12} style={{ textAlign: 'end' }}>
<Button
size="large"
onClick={() => {
setIsTourOpen(true);
}}
>
<InfoCircleOutlined /> Start Tour
</Button>
</Col>
</Row>
</Col>
</Row>
Expand All @@ -519,7 +571,7 @@ export default function CreateNetworkRolePage(props: PageProps) {
</Col>
<Form form={metadataForm} layout="vertical" style={{ width: '100%' }}>
<Row gutter={[24, 0]}>
<Col xs={24} md={12}>
<Col xs={24} md={12} ref={networkRoleName}>
<Form.Item
name="name"
label="Role Name"
Expand All @@ -529,7 +581,7 @@ export default function CreateNetworkRolePage(props: PageProps) {
<Input placeholder="Enter a name for this new role" style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col xs={24} md={12}>
<Col xs={24} md={12} ref={networkName}>
<Form.Item
name="network"
label="Specify the network this role will apply to"
Expand All @@ -542,7 +594,7 @@ export default function CreateNetworkRolePage(props: PageProps) {
/>
</Form.Item>
</Col>
<Col xs={24} md={12}>
<Col xs={24} md={12} ref={networkAdminAccess}>
<Form.Item
name="full_access"
label="Assign Admin Access To Network"
Expand All @@ -557,7 +609,7 @@ export default function CreateNetworkRolePage(props: PageProps) {
</Form>
</Row>

<Row className="tabbed-page-row-padding" style={{ paddingBottom: '5rem' }}>
<Row className="tabbed-page-row-padding" style={{ paddingBottom: '5rem' }} ref={networkRolePermissions}>
<Col xs={24}>
<Typography.Title level={4}>Role Permissions</Typography.Title>
</Col>
Expand All @@ -583,14 +635,20 @@ export default function CreateNetworkRolePage(props: PageProps) {
}}
>
<Col xs={24} style={{ textAlign: 'end' }}>
<Button type="primary" size="large" loading={isSubmitting} onClick={createNetworkRole}>
<Button
type="primary"
size="large"
loading={isSubmitting}
onClick={createNetworkRole}
ref={createRoleButton}
>
<PlusOutlined /> Create Role
</Button>
</Col>
</Row>
</Skeleton>

{/* misc */}
<Tour steps={createNetworkRoleTourSteps} open={isTourOpen} onClose={() => setIsTourOpen(false)} />
{notifyCtx}
</Layout.Content>
);
Expand Down
Loading
Loading