add-frames #1

Merged
philipp merged 22 commits from add-frames into fork 2022-11-02 10:25:45 +01:00
7 changed files with 267 additions and 1 deletions
Showing only changes of commit 9627874dae - Show all commits

View file

@ -0,0 +1,2 @@
export { Apps } from './Apps';
export { AppSingle } from './AppSingle';

View file

@ -1 +1,4 @@
export { Login } from './login';
export { Dashboard } from './dashboard';
export { Apps, AppSingle } from './apps';
export { Users } from './users';

View file

@ -13,7 +13,7 @@ import { debounce } from 'lodash';
import { useAuth } from 'src/services/auth';
import { UserModal } from '../../components/UserModal';
// import { MultipleUsersModal } from '../components/multipleUsersModal';
import { MultipleUsersModal } from './components/MultipleUsersModal';
export const Users: React.FC = () => {
const [selectedRowsIds, setSelectedRowsIds] = useState({});
@ -184,6 +184,7 @@ export const Users: React.FC = () => {
{configureModal && (
<UserModal open={configureModal} onClose={configureModalClose} userId={userId} setUserId={setUserId} />
)}
{multipleUsersModal && <MultipleUsersModal open={multipleUsersModal} onClose={multipleUsersModalClose} />}
</div>
</div>
);

View file

@ -0,0 +1,248 @@
import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import { useFieldArray, useForm, useWatch } from 'react-hook-form';
import { Banner, StepsModal, ProgressSteps } from 'src/components';
import { Select, TextArea } from 'src/components/Form';
import { MultipleUsersData, UserRole, useUsers } from 'src/services/users';
import { allAppAccessList } from 'src/components/UserModal/consts';
import { ProgressStepInfo, ProgressStepStatus } from 'src/components/ProgressSteps/types';
import { initialMultipleUsersForm, MultipleUsersModalProps } from './types';
export const MultipleUsersModal = ({ open, onClose }: MultipleUsersModalProps) => {
const [steps, setSteps] = useState<ProgressStepInfo[]>([]);
const [isAdminRoleSelected, setAdminRoleSelected] = useState(false);
const { createUsers, userModalLoading } = useUsers();
const { control, handleSubmit } = useForm<MultipleUsersData>({
defaultValues: initialMultipleUsersForm,
});
const { fields, update } = useFieldArray({
control,
name: 'appRoles',
});
const dashboardRole = useWatch({
control,
name: 'appRoles.0.role',
});
const csvDataWatch = useWatch({
control,
name: 'csvUserData',
});
useEffect(() => {
const isAdminDashboardRoleSelected = dashboardRole === UserRole.Admin;
setAdminRoleSelected(isAdminDashboardRoleSelected);
if (isAdminDashboardRoleSelected) {
fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.Admin }));
} else {
fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.User }));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dashboardRole]);
const renderUsersCsvDataInput = () => {
return (
<div>
<div className="mt-8">
<h3 className="text-lg leading-6 font-medium text-gray-900">CSV data</h3>
</div>
<div className="mt-6">
<TextArea
control={control}
name="csvUserData"
placeholder={`Please paste users in CSV format: email, name\nuser1@example.com,User One\nuser2@example.com,User Two`}
rows={15}
required
/>
</div>
</div>
);
};
const renderAppAccess = () => {
return (
<div>
<div className="mt-8">
<h3 className="text-lg leading-6 font-medium text-gray-900">App Access</h3>
</div>
{isAdminRoleSelected && (
<div className="sm:col-span-6">
<Banner title="Admin users automatically have admin-level access to all apps." titleSm="Admin user" />
</div>
)}
<div>
<div className="flow-root mt-6">
<ul className="-my-5 divide-y divide-gray-200">
{fields
.filter((field) => field.name === 'dashboard')
.map((item, index) => (
<li className="py-4" key={item.name}>
<div className="flex items-center space-x-4">
<div className="flex-shrink-0 flex-1 flex items-center">
<img
className="h-10 w-10 rounded-md overflow-hidden"
src={_.find(allAppAccessList, ['name', item.name!])?.image}
alt={item.name ?? 'Image'}
/>
<h3 className="ml-4 text-md leading-6 font-medium text-gray-900">
{_.find(allAppAccessList, ['name', item.name!])?.label}
</h3>
</div>
<div className="sm:col-span-2">
<Select
key={item.id}
control={control}
name={`appRoles.${index}.role`}
options={[
{ value: UserRole.User, name: 'User' },
{ value: UserRole.Admin, name: 'Admin' },
]}
/>
</div>
</div>
</li>
))}
{!isAdminRoleSelected &&
fields.map((item, index) => {
if (item.name === 'dashboard') {
return null;
}
return (
<li className="py-4" key={item.name}>
<div className="flex items-center space-x-4">
<div className="flex-shrink-0 flex-1 flex items-center">
<img
className="h-10 w-10 rounded-md overflow-hidden"
src={_.find(allAppAccessList, ['name', item.name!])?.image}
alt={item.name ?? 'Image'}
/>
<h3 className="ml-4 text-md leading-6 font-medium text-gray-900">
{_.find(allAppAccessList, ['name', item.name!])?.label}
</h3>
</div>
<div className="sm:col-span-2">
<Select
key={item.id}
control={control}
name={`appRoles.${index}.role`}
disabled={isAdminRoleSelected}
options={[
{ value: UserRole.NoAccess, name: 'No Access' },
{ value: UserRole.User, name: 'User' },
{ value: UserRole.Admin, name: 'Admin' },
]}
/>
</div>
</div>
</li>
);
})}
</ul>
</div>
</div>
</div>
);
};
useEffect(() => {
setSteps([
{
id: 'Step 1',
name: 'Enter CSV user data',
status: ProgressStepStatus.Current,
},
{
id: 'Step 2',
name: 'Define app access roles',
status: ProgressStepStatus.Upcoming,
},
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open]);
const handleSave = async () => {
try {
await handleSubmit((data) => createUsers(data))();
} catch (e: any) {
// Continue
}
onClose();
};
const handleClose = () => {
onClose();
};
const getActiveStepIndex = () => _.findIndex(steps, { status: ProgressStepStatus.Current });
const updateStepsStatus = (nextIndex: number) => {
const updatedSteps = [...steps];
_.forEach(updatedSteps, (step, index) => {
if (index < nextIndex) {
step.status = ProgressStepStatus.Complete;
} else if (index === nextIndex) {
step.status = ProgressStepStatus.Current;
} else {
step.status = ProgressStepStatus.Upcoming;
}
});
setSteps(updatedSteps);
};
const handleStepClick = (stepId: string) => {
const activeStepIndex = _.findIndex(steps, { id: stepId });
updateStepsStatus(activeStepIndex);
};
const handleNext = () => {
const nextIndex = getActiveStepIndex() + 1;
updateStepsStatus(nextIndex);
};
const handlePrevious = () => {
const nextIndex = getActiveStepIndex() - 1;
updateStepsStatus(nextIndex);
};
const activeStepIndex = getActiveStepIndex();
const showSave = !_.some(steps, { status: ProgressStepStatus.Upcoming });
const showPrevious = _.some(steps, { status: ProgressStepStatus.Complete });
return (
<StepsModal
onClose={handleClose}
open={open}
onSave={handleSave}
onNext={handleNext}
onPrevious={handlePrevious}
showPreviousButton={showPrevious}
isLoading={userModalLoading}
useCancelButton
showSaveButton={showSave}
saveButtonDisabled={_.isEmpty(csvDataWatch)}
>
<div className="bg-white px-4">
<div className="space-y-10 divide-y divide-gray-200">
<div>
<div>
<h3 className="text-lg leading-6 font-medium text-gray-900">Add new users</h3>
</div>
<div className="sm:px-6 pt-6">
<ProgressSteps steps={steps} onStepClick={handleStepClick}>
{activeStepIndex === 0 ? renderUsersCsvDataInput() : renderAppAccess()}
</ProgressSteps>
</div>
</div>
</div>
</div>
</StepsModal>
);
};

View file

@ -0,0 +1 @@
export { MultipleUsersModal } from './MultipleUsersModal';

View file

@ -0,0 +1,10 @@
import { initialAppRoles } from 'src/components/UserModal/consts';
export type MultipleUsersModalProps = {
open: boolean;
onClose: () => void;
};
export const initialMultipleUsersForm = {
appRoles: initialAppRoles,
};

View file

@ -0,0 +1 @@
export { Users } from './Users';