@campxdev/react-blueprint 1.6.4 → 1.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.tsx +1 -2
- package/package.json +1 -1
- package/src/App.tsx +71 -46
- package/src/components/Assets/Icons/IconComponents/PrinterIcon.tsx +42 -0
- package/src/components/Assets/Icons/Icons.tsx +2 -0
- package/src/components/DataDisplay/ActivityLogView/ActivityLogView.tsx +228 -0
- package/src/components/DataDisplay/ActivityLogView/Icons.tsx +65 -0
- package/src/components/DataDisplay/ActivityLogView/service.tsx +101 -0
- package/src/components/DataDisplay/ActivityLogView/styles.tsx +52 -0
- package/src/components/DataDisplay/Card/Card.tsx +1 -1
- package/src/components/DataDisplay/DataTable/TablePagination.tsx +4 -0
- package/src/components/DataDisplay/EditableDataTable/EditableDataTable.tsx +32 -21
- package/src/components/DataDisplay/export.ts +1 -0
- package/src/components/Feedback/Tooltip/ToolTipContent.tsx +15 -0
- package/src/components/Feedback/Tooltip/Tooltip.tsx +3 -17
- package/src/components/Feedback/export.ts +1 -0
- package/src/components/Input/SingleSelect/SingleSelect.tsx +22 -5
- package/src/components/Layout/PageHeader/PageHeader.tsx +52 -42
- package/src/components/Layout/PageHeader/components/DensitySelector/DensitySelector.tsx +2 -2
- package/src/components/Layout/PageHeader/components/SearchBar.tsx +66 -0
- package/src/components/Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector.tsx +14 -4
- package/src/components/Navigation/ConfirmDialog/ConfirmDialog.tsx +2 -2
- package/src/hooks/usePageHeader.ts +51 -12
- package/src/redux/slices/pageHeaderSlice.ts +71 -9
- package/src/stories/DataDisplay/ActivityLogView.stories.tsx +96 -0
- package/src/stories/Feedback/Tooltip.stories.tsx +2 -6
- package/src/stories/Input/TextField.stories.tsx +2 -2
package/.storybook/preview.tsx
CHANGED
|
@@ -4,9 +4,8 @@ import React from 'react';
|
|
|
4
4
|
import { Provider } from 'react-redux';
|
|
5
5
|
import { BrowserRouter } from 'react-router-dom';
|
|
6
6
|
import { useDarkMode } from 'storybook-dark-mode';
|
|
7
|
-
import { store } from '../src/redux/
|
|
7
|
+
import { store } from '../src/redux/store';
|
|
8
8
|
import { MuiThemeProvider } from '../src/themes/MuiThemeProvider';
|
|
9
|
-
|
|
10
9
|
import { DarkColorTokens } from '../src/themes/colorTokens/darkColorTokens';
|
|
11
10
|
import { LightColorTokens } from '../src/themes/colorTokens/lightColorTokens';
|
|
12
11
|
import { darkTheme } from '../src/themes/darkTheme';
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LocalizationProvider } from '@mui/x-date-pickers';
|
|
2
|
+
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
|
|
2
3
|
import './App.css';
|
|
3
|
-
import {
|
|
4
|
+
import { ActivityLogView } from './components/export';
|
|
4
5
|
|
|
5
6
|
interface RowType {
|
|
6
7
|
lastName: string;
|
|
@@ -17,50 +18,74 @@ function App() {
|
|
|
17
18
|
paddingLeft: '16px',
|
|
18
19
|
}}
|
|
19
20
|
>
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
21
|
+
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
22
|
+
<ActivityLogView
|
|
23
|
+
activitiesData={[
|
|
24
|
+
{
|
|
25
|
+
userName: 'ss',
|
|
26
|
+
action: 'create',
|
|
27
|
+
message: 's',
|
|
28
|
+
timestamp: new Date().toISOString(),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
userName: 'ss',
|
|
32
|
+
action: 'update',
|
|
33
|
+
message: 's',
|
|
34
|
+
timestamp: new Date().toISOString(),
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
userName: 'ss',
|
|
38
|
+
action: 'update',
|
|
39
|
+
message: 's',
|
|
40
|
+
timestamp: new Date().toISOString(),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
userName: 'ss',
|
|
44
|
+
action: 'update',
|
|
45
|
+
message: 's',
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
userName: 'ss',
|
|
50
|
+
action: 'update',
|
|
51
|
+
message: 's',
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
userName: 'ss',
|
|
56
|
+
action: 'delete',
|
|
57
|
+
message: 's',
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
userName: 'ss',
|
|
62
|
+
action: 'update',
|
|
63
|
+
message: 's',
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
userName: 'ss',
|
|
68
|
+
action: 'update',
|
|
69
|
+
message: 's',
|
|
70
|
+
timestamp: new Date().toISOString(),
|
|
71
|
+
},
|
|
72
|
+
]}
|
|
73
|
+
isFetchingNextPage={false}
|
|
74
|
+
fetchNextPage={function (): void {
|
|
75
|
+
// throw new Error('Function not implemented.');
|
|
76
|
+
}}
|
|
77
|
+
hasNextPage={undefined}
|
|
78
|
+
fromDate={null}
|
|
79
|
+
toDate={null}
|
|
80
|
+
setFromDate={function (date: Date | null): void {
|
|
81
|
+
// throw new Error('Function not implemented.');
|
|
82
|
+
}}
|
|
83
|
+
setToDate={function (date: Date | null): void {
|
|
84
|
+
// throw new Error('Function not implemented.');
|
|
85
|
+
}}
|
|
86
|
+
isLoading={false}
|
|
87
|
+
/>
|
|
88
|
+
</LocalizationProvider>
|
|
64
89
|
</div>
|
|
65
90
|
);
|
|
66
91
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const PrinterIcon = ({ size = 16 }) => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
width={size}
|
|
5
|
+
height={size}
|
|
6
|
+
viewBox="0 0 16 17"
|
|
7
|
+
fill="none"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
>
|
|
10
|
+
<path
|
|
11
|
+
d="M11.169 5.66634H4.8362C4.70378 5.6655 4.57703 5.61253 4.48339 5.51889C4.38975 5.42525 4.33678 5.29849 4.33594 5.16607V3.83274C4.33594 2.12607 5.129 1.33301 6.8362 1.33301H9.169C10.8757 1.33301 11.6687 2.12607 11.6687 3.83327V5.16661C11.6678 5.29884 11.6148 5.42539 11.5213 5.51889C11.4278 5.6124 11.3012 5.66536 11.169 5.66634ZM5.33594 4.66634H10.6693V3.83327C10.6693 2.69994 10.3029 2.33354 9.16954 2.33354H6.8362C5.70287 2.33354 5.33647 2.69994 5.33647 3.83381L5.33594 4.66634Z"
|
|
12
|
+
fill="#121212"
|
|
13
|
+
stroke="#121212"
|
|
14
|
+
strokeWidth="0.4"
|
|
15
|
+
/>
|
|
16
|
+
<path
|
|
17
|
+
d="M8.669 15.6672H7.33567C5.72234 15.6672 4.83594 14.7808 4.83594 13.1669V10.5002C4.83692 10.3679 4.88995 10.2413 4.98358 10.1478C5.0772 10.0542 5.20388 10.0013 5.3362 10.0005H10.6695C10.802 10.0013 10.9287 10.0543 11.0224 10.1479C11.116 10.2416 11.169 10.3683 11.1698 10.5008V13.1674C11.1693 14.7808 10.2823 15.6672 8.669 15.6672ZM5.83594 11.0005V13.1669C5.83594 14.2202 6.28287 14.6666 7.3362 14.6666H8.66954C9.72234 14.6672 10.1693 14.2202 10.1693 13.1669V11.0005H5.83594Z"
|
|
18
|
+
fill="#121212"
|
|
19
|
+
stroke="#121212"
|
|
20
|
+
strokeWidth="0.4"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
d="M12.0003 12.9998H10.6669C10.5347 12.9989 10.4082 12.9459 10.3146 12.8524C10.2211 12.7589 10.1682 12.6323 10.1672 12.5001V10.9998H5.83333V12.4996C5.8325 12.6319 5.77959 12.7586 5.68607 12.8522C5.59255 12.9458 5.46593 12.9989 5.3336 12.9998H4.00027C2.3864 12.9998 1.5 12.1129 1.5 10.4996V7.16677C1.5 5.5529 2.3864 4.6665 4.00027 4.6665H12.0003C13.6136 4.6665 14.5005 5.5529 14.5005 7.16677V10.5001C14.5 12.1129 13.6131 12.9998 12.0003 12.9998ZM11.1667 11.9998H12.0003C13.0536 11.9998 13.5005 11.5529 13.5005 10.5001V7.16677C13.5005 6.11344 13.0536 5.66704 12.0008 5.66704H4.0008C2.94747 5.66704 2.50107 6.11397 2.50107 7.1673V10.5006C2.50107 11.554 2.948 12.0009 4.00133 12.0009H4.83333V10.4996C4.83431 10.3673 4.88727 10.2408 4.98078 10.1473C5.07429 10.0538 5.20083 10.0008 5.33307 9.99984H10.6664C10.7987 10.0007 10.9254 10.0536 11.019 10.1471C11.1127 10.2406 11.1657 10.3672 11.1667 10.4996V11.9998Z"
|
|
24
|
+
fill="#121212"
|
|
25
|
+
stroke="#121212"
|
|
26
|
+
strokeWidth="0.4"
|
|
27
|
+
/>
|
|
28
|
+
<path
|
|
29
|
+
d="M11.3305 11.0005H4.66433C4.532 10.9997 4.40532 10.9467 4.3117 10.8532C4.21808 10.7597 4.16504 10.6331 4.16406 10.5008C4.1649 10.3683 4.21788 10.2416 4.31151 10.1479C4.40515 10.0543 4.53191 10.0013 4.66433 10.0005H11.331C11.4634 10.0013 11.5902 10.0543 11.6838 10.1479C11.7774 10.2416 11.8304 10.3683 11.8313 10.5008C11.8303 10.6332 11.7772 10.7599 11.6834 10.8534C11.5897 10.9469 11.4629 10.9998 11.3305 11.0005Z"
|
|
30
|
+
fill="#121212"
|
|
31
|
+
stroke="#121212"
|
|
32
|
+
strokeWidth="0.4"
|
|
33
|
+
/>
|
|
34
|
+
<path
|
|
35
|
+
d="M6.66433 8.3335H4.66433C4.532 8.33266 4.40532 8.27976 4.3117 8.18623C4.21808 8.09271 4.16504 7.96609 4.16406 7.83376C4.1649 7.70134 4.21788 7.57458 4.31151 7.48095C4.40515 7.38731 4.53191 7.33434 4.66433 7.3335H6.66433C6.79675 7.33434 6.92351 7.38731 7.01714 7.48095C7.11078 7.57458 7.16376 7.70134 7.1646 7.83376C7.16362 7.96609 7.11058 8.09271 7.01696 8.18623C6.92334 8.27976 6.79666 8.33266 6.66433 8.3335Z"
|
|
36
|
+
fill="#121212"
|
|
37
|
+
stroke="#121212"
|
|
38
|
+
strokeWidth="0.4"
|
|
39
|
+
/>
|
|
40
|
+
</svg>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -78,6 +78,7 @@ import { OpenPaymentsIcon } from './IconComponents/OpenPaymentsIcon';
|
|
|
78
78
|
import { PayxIcon } from './IconComponents/PayxIcon';
|
|
79
79
|
import { PdfIcon } from './IconComponents/PdfIcon';
|
|
80
80
|
import { PeoplexIcon } from './IconComponents/PeoplexIcon';
|
|
81
|
+
import { PrinterIcon } from './IconComponents/PrinterIcon';
|
|
81
82
|
import { ProductFeaturesIcon } from './IconComponents/ProductFeaturesIcon';
|
|
82
83
|
import { ProfileIcon } from './IconComponents/ProfileIcon';
|
|
83
84
|
import QuizIcon from './IconComponents/QuizIcon';
|
|
@@ -116,6 +117,7 @@ import { WhatsappIcon } from './IconComponents/WhatsappIcon';
|
|
|
116
117
|
|
|
117
118
|
export const Icons = {
|
|
118
119
|
NoteIcon,
|
|
120
|
+
PrinterIcon,
|
|
119
121
|
RedoIcon,
|
|
120
122
|
WhatsappIcon,
|
|
121
123
|
SmsIcon,
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { TimelineContent, TimelineItem, TimelineSeparator } from '@mui/lab';
|
|
2
|
+
import { Box, Stack, Typography, useTheme } from '@mui/material';
|
|
3
|
+
import { format, isToday } from 'date-fns';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { Button, DatePicker, Spinner } from '../../export';
|
|
7
|
+
import {
|
|
8
|
+
ActivityIcon,
|
|
9
|
+
convertUTCtoIST,
|
|
10
|
+
NoDataFound,
|
|
11
|
+
ScrollToTopButton,
|
|
12
|
+
useIntersectionObserver,
|
|
13
|
+
} from './service';
|
|
14
|
+
import {
|
|
15
|
+
StyledActivityLogViewBox,
|
|
16
|
+
StyledIconBox,
|
|
17
|
+
StyledSectionTitle,
|
|
18
|
+
StyledSpinnerBox,
|
|
19
|
+
StyledTimeline,
|
|
20
|
+
StyledTimelineConnector,
|
|
21
|
+
StyledTimelineDot,
|
|
22
|
+
} from './styles';
|
|
23
|
+
|
|
24
|
+
export type ActivityAction = 'create' | 'update' | 'delete';
|
|
25
|
+
|
|
26
|
+
export interface Activity {
|
|
27
|
+
userName: string;
|
|
28
|
+
action: ActivityAction;
|
|
29
|
+
message: string;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface ActivityLogProps {
|
|
34
|
+
activitiesData: Activity[];
|
|
35
|
+
isFetchingNextPage: boolean;
|
|
36
|
+
fetchNextPage: () => void;
|
|
37
|
+
hasNextPage: boolean | undefined;
|
|
38
|
+
fromDate: Date | null;
|
|
39
|
+
toDate: Date | null;
|
|
40
|
+
setFromDate: (date: Date | null) => void;
|
|
41
|
+
setToDate: (date: Date | null) => void;
|
|
42
|
+
isLoading: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ActivityLogFilter = ({
|
|
46
|
+
fromDate,
|
|
47
|
+
toDate,
|
|
48
|
+
setFromDate,
|
|
49
|
+
setToDate,
|
|
50
|
+
fetchNextPage,
|
|
51
|
+
isLoading,
|
|
52
|
+
}: {
|
|
53
|
+
fromDate: Date | null;
|
|
54
|
+
toDate: Date | null;
|
|
55
|
+
setFromDate: (date: Date | null) => void;
|
|
56
|
+
setToDate: (date: Date | null) => void;
|
|
57
|
+
fetchNextPage: () => void;
|
|
58
|
+
isLoading: boolean;
|
|
59
|
+
}) => {
|
|
60
|
+
const [localFromDate, setLocalFromDate] = useState(fromDate);
|
|
61
|
+
const [localToDate, setLocalToDate] = useState(toDate);
|
|
62
|
+
|
|
63
|
+
const handleFilterSubmit = () => {
|
|
64
|
+
setFromDate(localFromDate);
|
|
65
|
+
setToDate(localToDate);
|
|
66
|
+
fetchNextPage();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const clearFilters = () => {
|
|
70
|
+
setLocalFromDate(null);
|
|
71
|
+
setLocalToDate(null);
|
|
72
|
+
setFromDate(null);
|
|
73
|
+
setToDate(null);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 3 }}>
|
|
78
|
+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
79
|
+
<DatePicker
|
|
80
|
+
key={`from-date-${localFromDate}`}
|
|
81
|
+
label="From Date"
|
|
82
|
+
value={localFromDate}
|
|
83
|
+
onChange={setLocalFromDate}
|
|
84
|
+
disabled={isLoading}
|
|
85
|
+
/>
|
|
86
|
+
<DatePicker
|
|
87
|
+
key={`to-date-${localToDate}`}
|
|
88
|
+
label="To Date"
|
|
89
|
+
value={localToDate}
|
|
90
|
+
onChange={setLocalToDate}
|
|
91
|
+
disabled={isLoading}
|
|
92
|
+
/>
|
|
93
|
+
<Stack spacing={1} direction="row" ml={1} mt={2}>
|
|
94
|
+
<Button onClick={handleFilterSubmit} variant="contained">
|
|
95
|
+
Submit
|
|
96
|
+
</Button>
|
|
97
|
+
</Stack>
|
|
98
|
+
</Box>
|
|
99
|
+
<Box sx={{ display: 'flex', mt: 3.5 }}>
|
|
100
|
+
<Button onClick={clearFilters} disabled={isLoading}>
|
|
101
|
+
Clear
|
|
102
|
+
</Button>
|
|
103
|
+
</Box>
|
|
104
|
+
</Box>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const ActivityLogView = ({
|
|
109
|
+
activitiesData,
|
|
110
|
+
isFetchingNextPage,
|
|
111
|
+
fetchNextPage,
|
|
112
|
+
hasNextPage,
|
|
113
|
+
fromDate,
|
|
114
|
+
toDate,
|
|
115
|
+
setFromDate,
|
|
116
|
+
setToDate,
|
|
117
|
+
isLoading,
|
|
118
|
+
}: ActivityLogProps) => {
|
|
119
|
+
const theme = useTheme();
|
|
120
|
+
const lastItemRef = useIntersectionObserver(() => {
|
|
121
|
+
if (!isFetchingNextPage && hasNextPage) fetchNextPage();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const loading = isLoading && activitiesData.length === 0;
|
|
125
|
+
|
|
126
|
+
// Group activities by Today and Past Week and Older
|
|
127
|
+
const groupedActivities = _.groupBy(activitiesData, (activity) => {
|
|
128
|
+
const activityDate = convertUTCtoIST(activity.timestamp);
|
|
129
|
+
return isToday(activityDate)
|
|
130
|
+
? 'Today'
|
|
131
|
+
: activityDate > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
|
|
132
|
+
? 'Past Week'
|
|
133
|
+
: 'Older';
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const renderMessage = (activity: Activity) =>
|
|
137
|
+
activity.message.split('\n').map((part, index) => (
|
|
138
|
+
<Typography key={index} component="div">
|
|
139
|
+
{index === 0 && (
|
|
140
|
+
<span style={{ color: theme.palette.text.primary }}>
|
|
141
|
+
{activity.userName}
|
|
142
|
+
</span>
|
|
143
|
+
)}{' '}
|
|
144
|
+
{part.split(/('[^']*')/g).map((text, idx) => {
|
|
145
|
+
const isQuotedText = text.startsWith("'") && text.endsWith("'");
|
|
146
|
+
return (
|
|
147
|
+
<span
|
|
148
|
+
key={idx}
|
|
149
|
+
style={{
|
|
150
|
+
color: isQuotedText
|
|
151
|
+
? theme.palette.text.primary
|
|
152
|
+
: theme.palette.text.secondary,
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
{isQuotedText ? text.slice(1, -1) : text}
|
|
156
|
+
</span>
|
|
157
|
+
);
|
|
158
|
+
})}
|
|
159
|
+
</Typography>
|
|
160
|
+
));
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<StyledActivityLogViewBox className="scrollable-activity-log">
|
|
164
|
+
<ActivityLogFilter
|
|
165
|
+
fromDate={fromDate}
|
|
166
|
+
toDate={toDate}
|
|
167
|
+
setFromDate={setFromDate}
|
|
168
|
+
setToDate={setToDate}
|
|
169
|
+
fetchNextPage={fetchNextPage}
|
|
170
|
+
isLoading={isLoading}
|
|
171
|
+
/>
|
|
172
|
+
|
|
173
|
+
{loading ? (
|
|
174
|
+
<StyledSpinnerBox>
|
|
175
|
+
<Spinner />
|
|
176
|
+
</StyledSpinnerBox>
|
|
177
|
+
) : activitiesData.length === 0 ? (
|
|
178
|
+
<NoDataFound message={'No data found'} />
|
|
179
|
+
) : (
|
|
180
|
+
Object.entries(groupedActivities).map(([section, activities]) => (
|
|
181
|
+
<Box key={section}>
|
|
182
|
+
<StyledSectionTitle>{section}</StyledSectionTitle>
|
|
183
|
+
<StyledTimeline>
|
|
184
|
+
{activities.map((activity, index) => (
|
|
185
|
+
<TimelineItem
|
|
186
|
+
key={index}
|
|
187
|
+
ref={index === activities.length - 1 ? lastItemRef : null}
|
|
188
|
+
>
|
|
189
|
+
<TimelineSeparator>
|
|
190
|
+
<StyledTimelineDot>
|
|
191
|
+
<StyledIconBox>
|
|
192
|
+
<ActivityIcon type={activity.action} />
|
|
193
|
+
</StyledIconBox>
|
|
194
|
+
</StyledTimelineDot>
|
|
195
|
+
{index < activities.length - 1 && (
|
|
196
|
+
<StyledTimelineConnector />
|
|
197
|
+
)}
|
|
198
|
+
</TimelineSeparator>
|
|
199
|
+
<TimelineContent
|
|
200
|
+
sx={{
|
|
201
|
+
display: 'flex',
|
|
202
|
+
justifyContent: 'space-between',
|
|
203
|
+
marginTop: 1,
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
<Typography>{renderMessage(activity)}</Typography>
|
|
207
|
+
<Typography variant="caption">
|
|
208
|
+
{format(
|
|
209
|
+
convertUTCtoIST(activity.timestamp),
|
|
210
|
+
"d MMMM yyyy 'at' hh:mm a",
|
|
211
|
+
)}
|
|
212
|
+
</Typography>
|
|
213
|
+
</TimelineContent>
|
|
214
|
+
</TimelineItem>
|
|
215
|
+
))}
|
|
216
|
+
</StyledTimeline>
|
|
217
|
+
</Box>
|
|
218
|
+
))
|
|
219
|
+
)}
|
|
220
|
+
{isFetchingNextPage && (
|
|
221
|
+
<StyledSpinnerBox>
|
|
222
|
+
<Spinner />
|
|
223
|
+
</StyledSpinnerBox>
|
|
224
|
+
)}
|
|
225
|
+
<ScrollToTopButton />
|
|
226
|
+
</StyledActivityLogViewBox>
|
|
227
|
+
);
|
|
228
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export const DeleteIcon = () => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="16"
|
|
6
|
+
height="16"
|
|
7
|
+
viewBox="0 0 16 16"
|
|
8
|
+
fill="none"
|
|
9
|
+
style={{ display: 'flex', alignItems: 'center' }}
|
|
10
|
+
>
|
|
11
|
+
<g clipPath="url(#clip0_2752_9015)">
|
|
12
|
+
<path
|
|
13
|
+
d="M10.7933 1.3335H5.20659C2.77992 1.3335 1.33325 2.78016 1.33325 5.20683V10.7868C1.33325 13.2202 2.77992 14.6668 5.20659 14.6668H10.7866C13.2133 14.6668 14.6599 13.2202 14.6599 10.7935V5.20683C14.6666 2.78016 13.2199 1.3335 10.7933 1.3335ZM10.6666 8.50016H5.33325C5.20064 8.50016 5.07347 8.44749 4.9797 8.35372C4.88593 8.25995 4.83325 8.13277 4.83325 8.00016C4.83325 7.86756 4.88593 7.74038 4.9797 7.64661C5.07347 7.55284 5.20064 7.50016 5.33325 7.50016H10.6666C10.7992 7.50016 10.9264 7.55284 11.0201 7.64661C11.1139 7.74038 11.1666 7.86756 11.1666 8.00016C11.1666 8.13277 11.1139 8.25995 11.0201 8.35372C10.9264 8.44749 10.7992 8.50016 10.6666 8.50016Z"
|
|
14
|
+
fill="#F2353C"
|
|
15
|
+
/>
|
|
16
|
+
</g>
|
|
17
|
+
<defs>
|
|
18
|
+
<clipPath id="clip0_2752_9015">
|
|
19
|
+
<rect width="16" height="16" fill="white" />
|
|
20
|
+
</clipPath>
|
|
21
|
+
</defs>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const CreateIcon = () => {
|
|
27
|
+
return (
|
|
28
|
+
<svg
|
|
29
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
30
|
+
width="16"
|
|
31
|
+
height="16"
|
|
32
|
+
viewBox="0 0 16 16"
|
|
33
|
+
fill="none"
|
|
34
|
+
>
|
|
35
|
+
<path
|
|
36
|
+
d="M10.793 1.3335H5.20632C2.77965 1.3335 1.33325 2.7799 1.33325 5.20656V10.7868C1.33325 13.2199 2.77965 14.6668 5.20632 14.6668H10.7866C13.2133 14.6668 14.6602 13.2204 14.6602 10.7938V5.20656C14.6666 2.7799 13.2197 1.3335 10.793 1.3335ZM10.6666 8.4999H8.49965V10.6668C8.49965 10.7994 8.44697 10.9266 8.35321 11.0204C8.25944 11.1142 8.13226 11.1668 7.99965 11.1668C7.86704 11.1668 7.73987 11.1142 7.6461 11.0204C7.55233 10.9266 7.49965 10.7994 7.49965 10.6668V8.4999H5.33325C5.20064 8.4999 5.07347 8.44722 4.9797 8.35345C4.88593 8.25968 4.83325 8.1325 4.83325 7.9999C4.83325 7.86729 4.88593 7.74011 4.9797 7.64634C5.07347 7.55257 5.20064 7.4999 5.33325 7.4999H7.49965V5.3335C7.49965 5.20089 7.55233 5.07371 7.6461 4.97994C7.73987 4.88617 7.86704 4.8335 7.99965 4.8335C8.13226 4.8335 8.25944 4.88617 8.35321 4.97994C8.44697 5.07371 8.49965 5.20089 8.49965 5.3335V7.4999H10.6666C10.7992 7.4999 10.9264 7.55257 11.0201 7.64634C11.1139 7.74011 11.1666 7.86729 11.1666 7.9999C11.1666 8.1325 11.1139 8.25968 11.0201 8.35345C10.9264 8.44722 10.7992 8.4999 10.6666 8.4999Z"
|
|
37
|
+
fill="#4BAABE"
|
|
38
|
+
/>
|
|
39
|
+
</svg>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const UpdateIcon = () => {
|
|
44
|
+
return (
|
|
45
|
+
<svg
|
|
46
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
47
|
+
width="16"
|
|
48
|
+
height="16"
|
|
49
|
+
viewBox="0 0 16 16"
|
|
50
|
+
fill="none"
|
|
51
|
+
>
|
|
52
|
+
<g clipPath="url(#clip0_2752_9033)">
|
|
53
|
+
<path
|
|
54
|
+
d="M10.7933 1.3335H5.20659C2.77992 1.3335 1.33325 2.78016 1.33325 5.20683V10.7868C1.33325 13.2202 2.77992 14.6668 5.20659 14.6668H10.7866C13.2133 14.6668 14.6599 13.2202 14.6599 10.7935V5.20683C14.6666 2.78016 13.2199 1.3335 10.7933 1.3335ZM11.1866 6.46683L7.40659 10.2468C7.36025 10.2934 7.30519 10.3303 7.24456 10.3555C7.18392 10.3806 7.11891 10.3936 7.05325 10.3936C6.98759 10.3936 6.92258 10.3806 6.86195 10.3555C6.80131 10.3303 6.74625 10.2934 6.69992 10.2468L4.81325 8.36016C4.76413 8.31439 4.72473 8.25919 4.6974 8.19785C4.67007 8.13652 4.65538 8.07031 4.65419 8.00318C4.65301 7.93604 4.66536 7.86936 4.6905 7.8071C4.71565 7.74484 4.75308 7.68828 4.80056 7.6408C4.84804 7.59332 4.90459 7.5559 4.96685 7.53075C5.02911 7.5056 5.0958 7.49325 5.16293 7.49444C5.23007 7.49562 5.29628 7.51031 5.35761 7.53764C5.41894 7.56497 5.47414 7.60437 5.51992 7.6535L7.05325 9.18683L10.4799 5.76016C10.5747 5.67184 10.7001 5.62376 10.8296 5.62605C10.9591 5.62833 11.0827 5.68081 11.1743 5.77242C11.2659 5.86402 11.3184 5.98761 11.3207 6.11715C11.323 6.24668 11.2749 6.37205 11.1866 6.46683Z"
|
|
55
|
+
fill="#88B053"
|
|
56
|
+
/>
|
|
57
|
+
</g>
|
|
58
|
+
<defs>
|
|
59
|
+
<clipPath id="clip0_2752_9033">
|
|
60
|
+
<rect width="16" height="16" fill="white" />
|
|
61
|
+
</clipPath>
|
|
62
|
+
</defs>
|
|
63
|
+
</svg>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ArrowUpward, Info } from '@mui/icons-material';
|
|
2
|
+
import { Box, Fab, Typography } from '@mui/material';
|
|
3
|
+
import { addHours, addMinutes, parseISO } from 'date-fns';
|
|
4
|
+
import { useCallback, useRef } from 'react';
|
|
5
|
+
import { emptyListImage } from '../../../assets/images/svg';
|
|
6
|
+
import { StyledBox } from '../../Assets/ErrorPages/styles';
|
|
7
|
+
import { ActivityAction } from '../../export';
|
|
8
|
+
import { CreateIcon, DeleteIcon, UpdateIcon } from './Icons';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Converts a given UTC date string to Indian Standard Time (IST).
|
|
12
|
+
*
|
|
13
|
+
* @param dateString - The date string in ISO format to be converted.
|
|
14
|
+
* @returns The converted date object in IST.
|
|
15
|
+
*/
|
|
16
|
+
export const convertUTCtoIST = (dateString: string) => {
|
|
17
|
+
const date = parseISO(dateString);
|
|
18
|
+
return addMinutes(addHours(date, 5), 30);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const ActivityIcon = ({ type }: { type: ActivityAction }) => {
|
|
22
|
+
switch (type) {
|
|
23
|
+
case 'create':
|
|
24
|
+
return <CreateIcon />;
|
|
25
|
+
case 'delete':
|
|
26
|
+
return <DeleteIcon />;
|
|
27
|
+
case 'update':
|
|
28
|
+
return <UpdateIcon />;
|
|
29
|
+
default:
|
|
30
|
+
return <Info />;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const ScrollToTopButton = () => {
|
|
35
|
+
const handleScrollToTop = () => {
|
|
36
|
+
const container = document.querySelector('.scrollable-activity-log');
|
|
37
|
+
if (container) {
|
|
38
|
+
container.scrollTo({
|
|
39
|
+
top: 0,
|
|
40
|
+
behavior: 'smooth',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Box
|
|
47
|
+
sx={{
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
bottom: 20,
|
|
50
|
+
right: 20,
|
|
51
|
+
zIndex: 1500,
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
<Fab
|
|
55
|
+
color="primary"
|
|
56
|
+
size="small"
|
|
57
|
+
onClick={handleScrollToTop}
|
|
58
|
+
aria-label="Scroll to top"
|
|
59
|
+
>
|
|
60
|
+
<ArrowUpward />
|
|
61
|
+
</Fab>
|
|
62
|
+
</Box>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const NoDataFound = ({ message }: { message: string }) => {
|
|
67
|
+
return (
|
|
68
|
+
<>
|
|
69
|
+
<StyledBox>
|
|
70
|
+
<img
|
|
71
|
+
src={emptyListImage}
|
|
72
|
+
alt="page not found"
|
|
73
|
+
width={'350px'}
|
|
74
|
+
style={{ margin: '20px' }}
|
|
75
|
+
/>
|
|
76
|
+
<Typography variant="subtitle1">{message}</Typography>
|
|
77
|
+
</StyledBox>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export function useIntersectionObserver(callback: () => void) {
|
|
83
|
+
const observer = useRef<IntersectionObserver | null>(null);
|
|
84
|
+
|
|
85
|
+
const handleObserver = useCallback(
|
|
86
|
+
(node: HTMLDivElement) => {
|
|
87
|
+
if (observer.current) observer.current.disconnect();
|
|
88
|
+
|
|
89
|
+
observer.current = new IntersectionObserver((entries) => {
|
|
90
|
+
if (entries[0].isIntersecting) {
|
|
91
|
+
callback();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (node) observer.current.observe(node);
|
|
96
|
+
},
|
|
97
|
+
[callback],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return handleObserver;
|
|
101
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Timeline,
|
|
3
|
+
TimelineConnector,
|
|
4
|
+
TimelineDot,
|
|
5
|
+
timelineItemClasses,
|
|
6
|
+
} from '@mui/lab';
|
|
7
|
+
import { Box, styled, Typography } from '@mui/material';
|
|
8
|
+
|
|
9
|
+
export const StyledSpinnerBox = styled(Box)({
|
|
10
|
+
display: 'flex',
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const StyledSectionTitle = styled(Typography)(({ theme }) => ({
|
|
16
|
+
fontSize: '12px',
|
|
17
|
+
color: theme.palette.text.secondary,
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
export const StyledTimeline = styled(Timeline)({
|
|
21
|
+
[`& .${timelineItemClasses.root}:before`]: { flex: 0, padding: 0 },
|
|
22
|
+
[`& .${timelineItemClasses.root}:not(:first-of-type)`]: {
|
|
23
|
+
marginTop: '0px',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const StyledTimelineDot = styled(TimelineDot)(({ theme }) => ({
|
|
28
|
+
backgroundColor: theme.palette.surface.defaultBackground,
|
|
29
|
+
boxShadow: 'none',
|
|
30
|
+
width: 30,
|
|
31
|
+
padding: 0,
|
|
32
|
+
paddingLeft: 5,
|
|
33
|
+
height: 30,
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
export const StyledTimelineConnector = styled(TimelineConnector)(
|
|
37
|
+
({ theme }) => ({
|
|
38
|
+
width: '1px',
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export const StyledActivityLogViewBox = styled(Box)({
|
|
43
|
+
'&::-webkit-scrollbar': { display: 'none' },
|
|
44
|
+
overflowY: 'auto',
|
|
45
|
+
maxHeight: '70vh',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const StyledIconBox = styled(Box)({
|
|
49
|
+
display: 'flex',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
});
|
|
@@ -57,6 +57,10 @@ export const TablePagination = (props: PaginationProps) => {
|
|
|
57
57
|
},
|
|
58
58
|
}}
|
|
59
59
|
menu={[
|
|
60
|
+
<DropdownMenuItem
|
|
61
|
+
label="10 / Page"
|
|
62
|
+
onClick={() => onLimitChange(Number(10))}
|
|
63
|
+
/>,
|
|
60
64
|
<DropdownMenuItem
|
|
61
65
|
label="20 / Page"
|
|
62
66
|
onClick={() => onLimitChange(Number(20))}
|