diff --git a/src/components/Modal/Modal/types.ts b/src/components/Modal/Modal/types.ts
index afd720c..e679e69 100644
--- a/src/components/Modal/Modal/types.ts
+++ b/src/components/Modal/Modal/types.ts
@@ -8,4 +8,5 @@ export type ModalProps = {
useCancelButton?: boolean;
isLoading?: boolean;
leftActions?: React.ReactNode;
+ saveButtonDisabled?: boolean;
};
diff --git a/src/components/Modal/StepsModal/StepsModal.tsx b/src/components/Modal/StepsModal/StepsModal.tsx
new file mode 100644
index 0000000..7e2135b
--- /dev/null
+++ b/src/components/Modal/StepsModal/StepsModal.tsx
@@ -0,0 +1,143 @@
+import React, { Fragment, useRef } from 'react';
+import { Dialog, Transition } from '@headlessui/react';
+import { XIcon } from '@heroicons/react/solid';
+import { StepsModalProps } from './types';
+
+export const StepsModal: React.FC
= ({
+ open,
+ onClose,
+ onSave,
+ onNext,
+ onPrevious,
+ children,
+ title = '',
+ useCancelButton = false,
+ isLoading = false,
+ leftActions = <>>,
+ showSaveButton = false,
+ showPreviousButton = false,
+ saveButtonDisabled = false,
+}) => {
+ const cancelButtonRef = useRef(null);
+ const saveButtonRef = useRef(null);
+ const nextButtonRef = useRef(null);
+ const previousButtonRef = useRef(null);
+
+ return (
+
+
+
+ );
+};
diff --git a/src/components/Modal/StepsModal/index.ts b/src/components/Modal/StepsModal/index.ts
new file mode 100644
index 0000000..7c9bae5
--- /dev/null
+++ b/src/components/Modal/StepsModal/index.ts
@@ -0,0 +1 @@
+export { StepsModal } from './StepsModal';
diff --git a/src/components/Modal/StepsModal/types.ts b/src/components/Modal/StepsModal/types.ts
new file mode 100644
index 0000000..f0b5bbd
--- /dev/null
+++ b/src/components/Modal/StepsModal/types.ts
@@ -0,0 +1,16 @@
+import React from 'react';
+
+export type StepsModalProps = {
+ open: boolean;
+ onClose: () => void;
+ onNext: () => void;
+ onPrevious: () => void;
+ title?: string;
+ onSave?: () => void;
+ useCancelButton?: boolean;
+ isLoading?: boolean;
+ leftActions?: React.ReactNode;
+ showSaveButton?: boolean;
+ showPreviousButton?: boolean;
+ saveButtonDisabled?: boolean;
+};
diff --git a/src/components/Modal/index.ts b/src/components/Modal/index.ts
index 4ef3e38..e5800df 100644
--- a/src/components/Modal/index.ts
+++ b/src/components/Modal/index.ts
@@ -1,2 +1,3 @@
export { ConfirmationModal } from './ConfirmationModal';
export { Modal } from './Modal';
+export { StepsModal } from './StepsModal';
diff --git a/src/components/ProgressSteps/ProgressSteps.tsx b/src/components/ProgressSteps/ProgressSteps.tsx
new file mode 100644
index 0000000..2a24d67
--- /dev/null
+++ b/src/components/ProgressSteps/ProgressSteps.tsx
@@ -0,0 +1,107 @@
+import _ from 'lodash';
+import React from 'react';
+import { ProgressStepsProps, ProgressStepStatus } from './types';
+
+export const ProgressSteps: React.FC = ({ steps, onNext, onPrevious, onStepClick, children }) => {
+ const handleNext = () => {
+ if (onNext) {
+ onNext();
+ }
+ };
+ const handlePrevious = () => {
+ if (onPrevious) {
+ onPrevious();
+ }
+ };
+
+ const showNextPage = () => {
+ if (onNext) {
+ return _.some(steps, { status: ProgressStepStatus.Upcoming });
+ }
+ return false;
+ };
+
+ const showPreviousPage = () => {
+ if (onPrevious) {
+ return _.some(steps, { status: ProgressStepStatus.Complete });
+ }
+ return false;
+ };
+
+ const handleStepClick = (stepId: string) => {
+ if (onStepClick) {
+ onStepClick(stepId);
+ }
+ };
+
+ return (
+ <>
+
+
+ {children}
+
+ {(showNextPage() || showPreviousPage()) && (
+
+
+ {showNextPage() && (
+
+ )}
+ {showPreviousPage() && (
+
+ )}
+
+
+ )}
+ >
+ );
+};
diff --git a/src/components/ProgressSteps/index.ts b/src/components/ProgressSteps/index.ts
new file mode 100644
index 0000000..2bc8859
--- /dev/null
+++ b/src/components/ProgressSteps/index.ts
@@ -0,0 +1 @@
+export { ProgressSteps } from './ProgressSteps';
diff --git a/src/components/ProgressSteps/types.ts b/src/components/ProgressSteps/types.ts
new file mode 100644
index 0000000..3eed8b3
--- /dev/null
+++ b/src/components/ProgressSteps/types.ts
@@ -0,0 +1,20 @@
+export type ProgressStepsProps = {
+ steps: ProgressStepInfo[];
+ onNext?: () => void;
+ onPrevious?: () => void;
+ onStepClick?: (stepId: string) => void;
+};
+
+export interface ProgressStepInfo {
+ id: string;
+ name: string;
+ status: ProgressStepStatus;
+ component?: React.ReactNode;
+ href?: string;
+}
+
+export enum ProgressStepStatus {
+ Complete = 0,
+ Current = 1,
+ Upcoming = 2,
+}
diff --git a/src/components/UserModal/UserModal.tsx b/src/components/UserModal/UserModal.tsx
index 0993b94..404db4b 100644
--- a/src/components/UserModal/UserModal.tsx
+++ b/src/components/UserModal/UserModal.tsx
@@ -68,6 +68,8 @@ export const UserModal = ({ open, onClose, userId, setUserId }: UserModalProps)
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]);
diff --git a/src/components/UserModal/consts.ts b/src/components/UserModal/consts.ts
index 7304a41..f156652 100644
--- a/src/components/UserModal/consts.ts
+++ b/src/components/UserModal/consts.ts
@@ -23,26 +23,35 @@ export const appAccessList = [
},
];
-const initialAppRoles = [
+export const allAppAccessList = [
+ {
+ name: 'dashboard',
+ image: '/assets/logo-small.svg',
+ label: 'Dashboard',
+ },
+ ...appAccessList,
+];
+
+export const initialAppRoles = [
{
name: 'dashboard',
role: UserRole.User,
},
{
name: 'wekan',
- role: UserRole.NoAccess,
+ role: UserRole.User,
},
{
name: 'wordpress',
- role: UserRole.NoAccess,
+ role: UserRole.User,
},
{
name: 'nextcloud',
- role: UserRole.NoAccess,
+ role: UserRole.User,
},
{
name: 'zulip',
- role: UserRole.NoAccess,
+ role: UserRole.User,
},
];
diff --git a/src/components/index.ts b/src/components/index.ts
index 565e17d..9a2f607 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -3,5 +3,6 @@ export { Header } from './Header';
export { Table } from './Table';
export { Banner } from './Banner';
export { Tabs } from './Tabs';
-export { Modal, ConfirmationModal } from './Modal';
+export { Modal, ConfirmationModal, StepsModal } from './Modal';
export { UserModal } from './UserModal';
+export { ProgressSteps } from './ProgressSteps';
diff --git a/src/modules/users/Users.tsx b/src/modules/users/Users.tsx
index c40cc79..41cfafb 100644
--- a/src/modules/users/Users.tsx
+++ b/src/modules/users/Users.tsx
@@ -1,6 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useState, useCallback, useEffect, useMemo } from 'react';
-import { SearchIcon, PlusIcon } from '@heroicons/react/solid';
+import { SearchIcon, PlusIcon, ViewGridAddIcon } from '@heroicons/react/solid';
import { CogIcon, TrashIcon } from '@heroicons/react/outline';
import { useUsers } from 'src/services/users';
import { Table } from 'src/components';
@@ -8,10 +8,12 @@ import { debounce } from 'lodash';
import { useAuth } from 'src/services/auth';
import { UserModal } from '../../components/UserModal';
+import { MultipleUsersModal } from './components';
export const Users: React.FC = () => {
const [selectedRowsIds, setSelectedRowsIds] = useState({});
const [configureModal, setConfigureModal] = useState(false);
+ const [multipleUsersModal, setMultipleUsersModal] = useState(false);
const [userId, setUserId] = useState(null);
const [search, setSearch] = useState('');
const { users, loadUsers, userTableLoading } = useUsers();
@@ -39,8 +41,11 @@ export const Users: React.FC = () => {
setUserId(id);
setConfigureModal(true);
};
+
const configureModalClose = () => setConfigureModal(false);
+ const multipleUsersModalClose = () => setMultipleUsersModal(false);
+
const columns: any = React.useMemo(
() => [
{
@@ -101,11 +106,19 @@ export const Users: React.FC = () => {
+
)}
@@ -166,6 +179,7 @@ export const Users: React.FC = () => {
{configureModal && (