@griddo/ax 11.7.13 → 11.8.0-rc.0

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.
Files changed (95) hide show
  1. package/package.json +3 -2
  2. package/src/GlobalStore.tsx +3 -0
  3. package/src/api/index.tsx +4 -0
  4. package/src/api/logs.tsx +97 -0
  5. package/src/api/navigation.tsx +1 -1
  6. package/src/api/pages.tsx +1 -1
  7. package/src/api/schemas.tsx +18 -0
  8. package/src/api/users.tsx +17 -0
  9. package/src/components/ConfigPanel/Form/ConnectedField/NavConnectedField/index.tsx +3 -2
  10. package/src/components/ConfigPanel/Form/index.tsx +3 -1
  11. package/src/components/ConfigPanel/index.tsx +3 -0
  12. package/src/components/Fields/SummaryButton/index.tsx +6 -4
  13. package/src/components/Fields/TimeField/style.tsx +0 -1
  14. package/src/components/Fields/TranslateButton/index.tsx +3 -0
  15. package/src/components/FloatingMenu/index.tsx +25 -1
  16. package/src/components/FloatingMenu/style.tsx +3 -2
  17. package/src/components/LanguageMenu/index.tsx +1 -1
  18. package/src/components/MainWrapper/AppBar/index.tsx +4 -3
  19. package/src/components/RestoreModal/index.tsx +51 -0
  20. package/src/components/RestoreModal/style.tsx +7 -0
  21. package/src/components/SearchField/index.tsx +1 -1
  22. package/src/components/SearchField/style.tsx +4 -4
  23. package/src/components/TableFilters/CheckGroupFilter/index.tsx +42 -5
  24. package/src/components/TableFilters/CheckGroupFilter/style.tsx +8 -1
  25. package/src/components/TableFilters/SiteFilter/index.tsx +26 -57
  26. package/src/components/Tag/index.tsx +6 -3
  27. package/src/components/Tag/style.tsx +2 -2
  28. package/src/components/index.tsx +2 -0
  29. package/src/containers/ActivityLog/actions.tsx +262 -0
  30. package/src/containers/ActivityLog/constants.tsx +6 -0
  31. package/src/containers/ActivityLog/index.tsx +4 -0
  32. package/src/containers/ActivityLog/interfaces.tsx +12 -0
  33. package/src/containers/ActivityLog/reducer.tsx +25 -0
  34. package/src/containers/Navigation/Defaults/actions.tsx +4 -3
  35. package/src/containers/StructuredData/actions.tsx +7 -4
  36. package/src/containers/StructuredData/interfaces.tsx +2 -8
  37. package/src/containers/StructuredData/reducer.tsx +2 -8
  38. package/src/containers/Users/actions.tsx +22 -19
  39. package/src/modules/ActivityLog/DetailModal/index.tsx +108 -0
  40. package/src/modules/ActivityLog/DetailModal/style.tsx +52 -0
  41. package/src/modules/ActivityLog/DownloadModal/index.tsx +104 -0
  42. package/src/modules/ActivityLog/DownloadModal/style.tsx +12 -0
  43. package/src/modules/ActivityLog/ItemGroup/index.tsx +27 -0
  44. package/src/modules/ActivityLog/ItemGroup/style.tsx +39 -0
  45. package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +167 -0
  46. package/src/modules/ActivityLog/ItemLog/EventItem/style.tsx +79 -0
  47. package/src/modules/ActivityLog/ItemLog/index.tsx +24 -0
  48. package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +170 -0
  49. package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/style.tsx +79 -0
  50. package/src/modules/ActivityLog/ItemLogUser/UserItem/index.tsx +46 -0
  51. package/src/modules/ActivityLog/ItemLogUser/UserItem/style.tsx +60 -0
  52. package/src/modules/ActivityLog/ItemLogUser/index.tsx +25 -0
  53. package/src/modules/ActivityLog/LogFilters/ContentFilter/index.tsx +79 -0
  54. package/src/modules/ActivityLog/LogFilters/DateFilter/index.tsx +91 -0
  55. package/src/modules/ActivityLog/LogFilters/DateFilter/style.tsx +208 -0
  56. package/src/modules/ActivityLog/LogFilters/EventFilter/index.tsx +80 -0
  57. package/src/modules/ActivityLog/LogFilters/OrderFilter/index.tsx +49 -0
  58. package/src/modules/ActivityLog/LogFilters/OrderFilter/style.tsx +35 -0
  59. package/src/modules/ActivityLog/LogFilters/UserFilter/index.tsx +79 -0
  60. package/src/modules/ActivityLog/TableHeader/index.tsx +72 -0
  61. package/src/modules/ActivityLog/TableHeader/style.tsx +73 -0
  62. package/src/modules/ActivityLog/constants.tsx +10 -0
  63. package/src/modules/ActivityLog/hooks.tsx +53 -0
  64. package/src/modules/ActivityLog/index.tsx +313 -0
  65. package/src/modules/ActivityLog/style.tsx +57 -0
  66. package/src/modules/ActivityLog/utils.tsx +31 -0
  67. package/src/modules/Categories/CategoriesList/index.tsx +1 -1
  68. package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/index.tsx +3 -0
  69. package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/index.tsx +3 -0
  70. package/src/modules/Forms/FormEditor/Editor/index.tsx +5 -2
  71. package/src/modules/Forms/FormEditor/index.tsx +20 -3
  72. package/src/modules/GlobalEditor/Editor/index.tsx +3 -0
  73. package/src/modules/GlobalEditor/index.tsx +48 -9
  74. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -1
  75. package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -1
  76. package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +45 -6
  77. package/src/modules/PageEditor/Editor/index.tsx +4 -1
  78. package/src/modules/PageEditor/index.tsx +46 -7
  79. package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +1 -7
  80. package/src/modules/StructuredData/Form/index.tsx +56 -7
  81. package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +2 -2
  82. package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +2 -8
  83. package/src/modules/StructuredData/StructuredDataList/hooks.tsx +9 -9
  84. package/src/modules/StructuredData/StructuredDataList/index.tsx +3 -4
  85. package/src/modules/Users/Roles/index.tsx +0 -2
  86. package/src/modules/Users/UserEdit/index.tsx +12 -28
  87. package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +1 -0
  88. package/src/modules/Users/UserList/UserItem/index.tsx +10 -25
  89. package/src/modules/Users/UserList/index.tsx +8 -10
  90. package/src/routes/multisite.tsx +9 -0
  91. package/src/themes/theme.json +2 -1
  92. package/src/types/forms.tsx +1 -0
  93. package/src/types/index.tsx +8 -0
  94. package/src/types/logs.tsx +12 -0
  95. package/src/components/TableFilters/SiteFilter/style.tsx +0 -28
@@ -0,0 +1,79 @@
1
+ import React, { useEffect, useState } from "react";
2
+
3
+ import { CheckGroupFilter } from "@ax/components";
4
+ import { IQueryValue } from "@ax/types";
5
+ import { isReqOk } from "@ax/helpers";
6
+ import { schemas } from "@ax/api";
7
+
8
+ const ContentFilter = (props: IContentFilterProps): JSX.Element => {
9
+ const { filterItems, value } = props;
10
+
11
+ const filters = [
12
+ {
13
+ name: "all",
14
+ value: "all",
15
+ title: "ALL",
16
+ },
17
+ {
18
+ name: "none",
19
+ value: "none",
20
+ title: "None",
21
+ },
22
+ ];
23
+
24
+ const [options, setOptions] = useState(filters);
25
+
26
+ const getEvents = async () => {
27
+ try {
28
+ const items = await schemas.getSchemasSelectAll();
29
+ if (items && isReqOk(items.status)) {
30
+ return items.data;
31
+ }
32
+ } catch (e) {
33
+ console.log(e);
34
+ }
35
+ return false;
36
+ };
37
+
38
+ useEffect(() => {
39
+ getEvents()
40
+ .then((items: { id: string; title: string }[]) => {
41
+ items &&
42
+ items.forEach((item) => {
43
+ const newFilter = {
44
+ name: item.id,
45
+ value: item.id,
46
+ title: item.title,
47
+ };
48
+ filters.push(newFilter);
49
+ });
50
+
51
+ setOptions(filters);
52
+ })
53
+ .catch((apiError) => console.log(apiError));
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ }, []);
56
+
57
+ return (
58
+ <CheckGroupFilter
59
+ filterItems={filterItems}
60
+ value={value}
61
+ pointer="contentTypes"
62
+ label="Content Type"
63
+ description="Filter by Content Type"
64
+ initialState={["all"]}
65
+ selectAllOption="all"
66
+ filters={options}
67
+ menuPosition="center"
68
+ multipleSelection={true}
69
+ search={true}
70
+ />
71
+ );
72
+ };
73
+
74
+ export interface IContentFilterProps {
75
+ filterItems(pointer: string, filter: IQueryValue[]): void;
76
+ value: IQueryValue[];
77
+ }
78
+
79
+ export default ContentFilter;
@@ -0,0 +1,91 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import DatePicker, { registerLocale } from "react-datepicker";
3
+ import "react-datepicker/dist/react-datepicker.css";
4
+ import en from "date-fns/locale/en-GB";
5
+
6
+ import { IQueryValue } from "@ax/types";
7
+ import { Button, FloatingMenu, Icon } from "@ax/components";
8
+ import { dateToString, stringToDate } from "@ax/helpers";
9
+
10
+ import * as S from "./style";
11
+
12
+ const ContentFilter = (props: IContentFilterProps): JSX.Element => {
13
+ const { filterItems, value } = props;
14
+
15
+ const initialState = value?.length ? value[0].label.split("-") : null;
16
+ const startInitial = initialState ? stringToDate(initialState[0]) : null;
17
+ const endInitial = initialState ? stringToDate(initialState[1]) : null;
18
+
19
+ registerLocale("en", en);
20
+
21
+ const [startDate, setStartDate] = useState<Date | null>(startInitial);
22
+ const [endDate, setEndDate] = useState<Date | null>(endInitial);
23
+
24
+ useEffect(() => {
25
+ if (!value.length) {
26
+ setStartDate(null);
27
+ setEndDate(null);
28
+ }
29
+ }, [value]);
30
+
31
+ const handleChange = (dates: [Date | null, Date | null]) => {
32
+ const [start, end] = dates;
33
+ setStartDate(start);
34
+ setEndDate(end);
35
+ };
36
+
37
+ const handleClick = () => {
38
+ if (startDate) {
39
+ const startString = dateToString(startDate, "yyyy/MM/dd");
40
+ const startHuman = dateToString(startDate, "MMM d yyyy");
41
+ const endString = endDate ? dateToString(endDate, "yyyy/MM/dd") : startString;
42
+ const endHuman = endDate ? dateToString(endDate, "MMM d yyyy") : startHuman;
43
+ const selectedDate = `${startString}-${endString}`;
44
+ const label = startHuman !== endHuman ? `${startHuman} - ${endHuman}` : startHuman;
45
+ filterItems("date", [{ label, value: selectedDate }]);
46
+ }
47
+ };
48
+
49
+ const isActive = false;
50
+
51
+ const Header = () => (
52
+ <S.StyledHeader isActive={isActive}>
53
+ Date
54
+ <S.IconsWrapper>
55
+ {isActive ? <Icon name="Filter" size="16" /> : <Icon name="DownArrow" size="16" />}
56
+ </S.IconsWrapper>
57
+ </S.StyledHeader>
58
+ );
59
+
60
+ return (
61
+ <FloatingMenu Button={Header} position="left" closeOnSelect={false}>
62
+ <S.DatePickerWrapper data-testid="dateWrapper">
63
+ <DatePicker
64
+ locale={"en"}
65
+ selected={startDate}
66
+ onChange={handleChange}
67
+ startDate={startDate}
68
+ endDate={endDate}
69
+ maxDate={new Date()}
70
+ selectsRange
71
+ inline
72
+ disabledKeyboardNavigation
73
+ />
74
+ </S.DatePickerWrapper>
75
+ {!!startDate && (
76
+ <S.ButtonWrapper>
77
+ <Button type="button" onClick={handleClick} buttonStyle="minimal">
78
+ Apply
79
+ </Button>
80
+ </S.ButtonWrapper>
81
+ )}
82
+ </FloatingMenu>
83
+ );
84
+ };
85
+
86
+ export interface IContentFilterProps {
87
+ filterItems(pointer: string, filter: IQueryValue[]): void;
88
+ value: IQueryValue[];
89
+ }
90
+
91
+ export default ContentFilter;
@@ -0,0 +1,208 @@
1
+ import styled from "styled-components";
2
+
3
+ const StyledHeader = styled.div<{ isActive: boolean }>`
4
+ ${(p) => p.theme.textStyle.uiS};
5
+ box-sizing: border-box;
6
+ display: flex;
7
+ flex-flow: column wrap;
8
+ flex-direction: row;
9
+ color: ${(p) => (p.isActive ? p.theme.color.textHighEmphasis : p.theme.color.textMediumEmphasis)};
10
+ width: 100%;
11
+ justify-content: center;
12
+ position: relative;
13
+ &:hover {
14
+ color: ${(p) => p.theme.color.interactive01};
15
+ }
16
+ `;
17
+
18
+ const IconsWrapper = styled.div`
19
+ display: flex;
20
+ align-items: center;
21
+ flex-direction: row;
22
+ svg {
23
+ margin-left: 4px;
24
+ }
25
+ `;
26
+
27
+ const DatePickerWrapper = styled.div`
28
+ .react-datepicker-popper,
29
+ .react-datepicker-popper[data-placement^="bottom"],
30
+ .react-datepicker-popper[data-placement^="bottom-start"] {
31
+ margin-top: 0;
32
+ z-index: 2;
33
+ }
34
+
35
+ .react-datepicker__triangle {
36
+ display: none;
37
+ }
38
+
39
+ .react-datepicker-wrapper {
40
+ width: 100%;
41
+ }
42
+
43
+ .react-datepicker {
44
+ font-family: Source Sans Pro;
45
+ border: none;
46
+ min-width: 240px;
47
+ }
48
+
49
+ .react-datepicker__header {
50
+ background-color: white;
51
+ border-bottom: 0;
52
+ padding-top: ${(p) => p.theme.spacing.xs};
53
+ }
54
+
55
+ .react-datepicker__current-month {
56
+ ${(p) => p.theme.textStyle.headingXS};
57
+ margin: 0 0 ${(p) => p.theme.spacing.xs} 0;
58
+ }
59
+
60
+ .react-datepicker__navigation {
61
+ width: ${(p) => p.theme.spacing.m};
62
+ height: ${(p) => p.theme.spacing.m};
63
+ border: none;
64
+ margin-bottom: ${(p) => p.theme.spacing.xs};
65
+ &:hover {
66
+ border-radius: 50%;
67
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
68
+ }
69
+ &:focus,
70
+ &:active {
71
+ outline: 0;
72
+ -moz-outline-style: none;
73
+ border: none;
74
+ }
75
+
76
+ .react-datepicker__navigation-icon {
77
+ display: none;
78
+ }
79
+
80
+ &.react-datepicker__navigation--next {
81
+ background-image: url(/img/icons/Right-arrow.svg);
82
+ margin-right: ${(p) => p.theme.spacing.s};
83
+ margin-top: ${(p) => p.theme.spacing.xxs};
84
+ }
85
+
86
+ &.react-datepicker__navigation--previous {
87
+ background-image: url(/img/icons/Left-arrow.svg);
88
+ margin-left: ${(p) => p.theme.spacing.s};
89
+ margin-top: ${(p) => p.theme.spacing.xxs};
90
+ }
91
+ }
92
+
93
+ .react-datepicker__day-names {
94
+ min-width: 240px;
95
+ .react-datepicker__day-name {
96
+ line-height: 15px;
97
+ color: ${(p) => p.theme.color.textMediumEmphasis};
98
+ }
99
+ }
100
+
101
+ .react-datepicker__month-container {
102
+ min-width: 240px;
103
+
104
+ .react-datepicker__day {
105
+ font-size: 15px;
106
+ box-sizing: content-box;
107
+ border-radius: 50%;
108
+ :hover :not(.react-datepicker__day--selected) {
109
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
110
+ }
111
+ :focus,
112
+ :active {
113
+ outline: 0;
114
+ border-radius: 50%;
115
+ }
116
+ }
117
+
118
+ .react-datepicker__month {
119
+ min-width: 240px;
120
+ margin: ${(p) => p.theme.spacing.xxs} 0 0 0;
121
+ }
122
+
123
+ .react-datepicker__week {
124
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
125
+ }
126
+
127
+ .react-datepicker__day-name,
128
+ .react-datepicker__day,
129
+ .react-datepicker__time-name {
130
+ margin: 0 ${(p) => p.theme.spacing.xxs};
131
+ }
132
+
133
+ .react-datepicker__day--today {
134
+ :not(.react-datepicker__day--selected) {
135
+ color: ${(p) => p.theme.color.interactive01};
136
+ }
137
+ }
138
+
139
+ .react-datepicker__day--in-range:not(.react-datepicker__day--selected) {
140
+ background-color:${(p) => p.theme.color.interactive01};
141
+ border-radius: 0;
142
+ color: white;
143
+ &:not(.react-datepicker__day--range-end) {
144
+ margin: 0;
145
+ padding: 0 4px;
146
+ }
147
+ }
148
+
149
+ .react-datepicker__day--in-selecting-range:not(.react-datepicker__day--selected){
150
+ background-color: #FFF;
151
+ color: #000;
152
+ }
153
+
154
+ .react-datepicker__day--selected.react-datepicker__day--range-start:not(.react-datepicker__day--range-end){
155
+ background-color: ${(p) => p.theme.color.interactive01};
156
+ border-radius: 50% 0 0 50%;
157
+ margin-right: 0;
158
+ padding: 0 4px 0 0;
159
+ }
160
+
161
+ .react-datepicker__day--in-range.react-datepicker__day--range-end:not(.react-datepicker__day--range-start) {
162
+ border-radius: 0 50% 50% 0;
163
+ margin-left: 0;
164
+ padding: 0 0 0 4px;
165
+ }
166
+
167
+ .react-datepicker__day--selected {
168
+ background-color: ${(p) => p.theme.color.interactive01};
169
+ border-radius: 50%;
170
+ }
171
+
172
+ .react-datepicker__week .react-datepicker__day--in-range:last-of-type,
173
+ .react-datepicker__week .react-datepicker__day--in-selecting-range:last-of-type {
174
+ padding-right: 0;
175
+ margin-right: 4px;
176
+ }
177
+
178
+ .react-datepicker__week .react-datepicker__day--in-range:first-of-type,
179
+ .react-datepicker__week .react-datepicker__day--in-selecting-range:first-of-type {
180
+ padding-left: 0;
181
+ margin-left: 4px;
182
+ }
183
+
184
+ .react-datepicker__day--selected,
185
+ .react-datepicker__day--in-range.react-datepicker__day--range-end {
186
+ font-weight: ${(p) => p.theme.fontWeight.semibold}
187
+ background-color: ${(p) => p.theme.color.interactive01};
188
+ color: white;
189
+ :hover {
190
+ background-color: ${(p) => p.theme.color.interactive01};
191
+ }
192
+ }
193
+
194
+ .react-datepicker__day--outside-month {
195
+ color: ${(p) => p.theme.color.textLowEmphasis};
196
+ &.react-datepicker__day--in-range {
197
+ color: ${(p) => p.theme.color.textLowEmphasisInverse};
198
+ }
199
+ }
200
+ `;
201
+
202
+ const ButtonWrapper = styled.div`
203
+ border-top: 1px solid ${(p) => p.theme.color.uiLine};
204
+ text-align: center;
205
+ padding-top: ${(p) => p.theme.spacing.xs};
206
+ `;
207
+
208
+ export { StyledHeader, IconsWrapper, DatePickerWrapper, ButtonWrapper };
@@ -0,0 +1,80 @@
1
+ import React, { useEffect, useState } from "react";
2
+
3
+ import { CheckGroupFilter } from "@ax/components";
4
+ import { isReqOk } from "@ax/helpers";
5
+ import { logs } from "@ax/api";
6
+ import { IQueryValue } from "@ax/types";
7
+
8
+ const EventFilter = (props: IEventFilterProps): JSX.Element => {
9
+ const { filterItems, value } = props;
10
+
11
+ const filters = [
12
+ {
13
+ name: "all",
14
+ value: "all",
15
+ title: "ALL",
16
+ },
17
+ ];
18
+
19
+ const [options, setOptions] = useState(filters);
20
+
21
+ const getEvents = async () => {
22
+ try {
23
+ const items = await logs.getLogActivityEventTypes();
24
+ if (items && isReqOk(items.status)) {
25
+ return items.data;
26
+ }
27
+ } catch (e) {
28
+ console.log(e);
29
+ }
30
+ return false;
31
+ };
32
+
33
+ useEffect(() => {
34
+ getEvents()
35
+ .then((items: IEventType[]) => {
36
+ items &&
37
+ items.forEach((item) => {
38
+ const newFilter = {
39
+ name: item.id.toString(),
40
+ value: item.id.toString(),
41
+ title: item.title,
42
+ };
43
+ filters.push(newFilter);
44
+ });
45
+
46
+ setOptions(filters);
47
+ })
48
+ .catch((apiError) => console.log(apiError));
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ }, []);
51
+
52
+ return (
53
+ <CheckGroupFilter
54
+ filterItems={filterItems}
55
+ value={value}
56
+ pointer="eventTypes"
57
+ label="Event"
58
+ description="Filter by Event"
59
+ initialState={["all"]}
60
+ selectAllOption="all"
61
+ filters={options}
62
+ menuPosition="center"
63
+ multipleSelection={true}
64
+ search={true}
65
+ />
66
+ );
67
+ };
68
+
69
+ interface IEventType {
70
+ id: number;
71
+ title: string;
72
+ description: string;
73
+ }
74
+
75
+ export interface IEventFilterProps {
76
+ filterItems(pointer: string, filter: IQueryValue[]): void;
77
+ value: IQueryValue[];
78
+ }
79
+
80
+ export default EventFilter;
@@ -0,0 +1,49 @@
1
+ import React from "react";
2
+
3
+ import { Icon, FloatingMenu, ListTitle, ListItem } from "@ax/components";
4
+
5
+ import * as S from "./style";
6
+
7
+ const OrderFilter = (props: IStatusFilterProps) => {
8
+ const { sortItems, isAscending } = props;
9
+
10
+ const sortOldest = () => sortItems(true);
11
+ const sortMostRecent = () => sortItems(false);
12
+
13
+ const SortedStateArrow = () =>
14
+ isAscending ? <Icon name="FullArrowUp" size="16" /> : <Icon name="FullArrowDown" size="16" />;
15
+
16
+ const Header = () => (
17
+ <S.Status data-testid="status-filter-header">
18
+ Time
19
+ <S.IconsWrapper>
20
+ {isAscending ? (
21
+ <SortedStateArrow />
22
+ ) : (
23
+ <S.InteractiveArrow data-testid="status-filter-interactive-arrow">
24
+ <Icon name="DownArrow" size="16" />
25
+ </S.InteractiveArrow>
26
+ )}
27
+ </S.IconsWrapper>
28
+ </S.Status>
29
+ );
30
+
31
+ return (
32
+ <FloatingMenu Button={Header} position="center">
33
+ <ListTitle>Sort by time</ListTitle>
34
+ <ListItem isSelected={!isAscending} onClick={sortMostRecent}>
35
+ Most recent
36
+ </ListItem>
37
+ <ListItem isSelected={isAscending} onClick={sortOldest}>
38
+ Oldest
39
+ </ListItem>
40
+ </FloatingMenu>
41
+ );
42
+ };
43
+
44
+ export interface IStatusFilterProps {
45
+ isAscending: boolean;
46
+ sortItems(isAscendent: boolean): void;
47
+ }
48
+
49
+ export default OrderFilter;
@@ -0,0 +1,35 @@
1
+ import styled from "styled-components";
2
+
3
+ const Status = styled.div`
4
+ ${(p) => p.theme.textStyle.uiS};
5
+ box-sizing: border-box;
6
+ display: flex;
7
+ flex-flow: column wrap;
8
+ flex-direction: row;
9
+ justify-content: center;
10
+ width: 100%;
11
+ position: relative;
12
+ &:hover {
13
+ color: ${(p) => p.theme.color.interactive01};
14
+ }
15
+ `;
16
+
17
+ const IconsWrapper = styled.div`
18
+ display: flex;
19
+ align-items: center;
20
+ flex-direction: row;
21
+ svg {
22
+ margin-left: 4px;
23
+ }
24
+ `;
25
+
26
+ const InteractiveArrow = styled.div`
27
+ display: flex;
28
+ svg {
29
+ path {
30
+ fill: ${(p) => p.theme.color.interactive01};
31
+ }
32
+ }
33
+ `;
34
+
35
+ export { Status, IconsWrapper, InteractiveArrow };
@@ -0,0 +1,79 @@
1
+ import React, { useEffect, useState } from "react";
2
+
3
+ import { CheckGroupFilter } from "@ax/components";
4
+ import { isReqOk } from "@ax/helpers";
5
+ import { users } from "@ax/api";
6
+ import { IQueryValue, IUser } from "@ax/types";
7
+
8
+ const UserFilter = (props: IUserFilterProps): JSX.Element => {
9
+ const { filterItems, value } = props;
10
+
11
+ const filters = [
12
+ {
13
+ name: "all",
14
+ value: "all",
15
+ title: "All users (bot not included)",
16
+ },
17
+ {
18
+ name: "bot",
19
+ value: "bot",
20
+ title: "View bot events",
21
+ },
22
+ ];
23
+
24
+ const [options, setOptions] = useState(filters);
25
+
26
+ const getUsers = async () => {
27
+ try {
28
+ const items = await users.getUsers({ filterQuery: "?order=name-asc" });
29
+ if (items && isReqOk(items.status)) {
30
+ return items.data;
31
+ }
32
+ } catch (e) {
33
+ console.log(e);
34
+ }
35
+ return false;
36
+ };
37
+
38
+ useEffect(() => {
39
+ getUsers()
40
+ .then((items: IUser[]) => {
41
+ items &&
42
+ items.forEach((item) => {
43
+ const newFilter = {
44
+ name: item.id?.toString() || "",
45
+ value: item.id?.toString() || "",
46
+ title: item.name,
47
+ };
48
+ filters.push(newFilter);
49
+ });
50
+
51
+ setOptions(filters);
52
+ })
53
+ .catch((apiError) => console.log(apiError));
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ }, []);
56
+
57
+ return (
58
+ <CheckGroupFilter
59
+ filterItems={filterItems}
60
+ value={value}
61
+ pointer="users"
62
+ label="User"
63
+ description="Filter by User"
64
+ initialState={["all"]}
65
+ selectAllOption="all"
66
+ filters={options}
67
+ menuPosition="center"
68
+ multipleSelection={true}
69
+ search={true}
70
+ />
71
+ );
72
+ };
73
+
74
+ export interface IUserFilterProps {
75
+ filterItems(pointer: string, filter: IQueryValue[]): void;
76
+ value: IQueryValue[];
77
+ }
78
+
79
+ export default UserFilter;
@@ -0,0 +1,72 @@
1
+ import React from "react";
2
+ import { SiteFilter } from "@ax/components";
3
+ import { IQueryValue } from "@ax/types";
4
+
5
+ import UserFilter from "../LogFilters/UserFilter";
6
+ import EventFilter from "../LogFilters/EventFilter";
7
+ import ContentFilter from "../LogFilters/ContentFilter";
8
+ import DateFilter from "../LogFilters/DateFilter";
9
+ import OrderFilter from "../LogFilters/OrderFilter";
10
+
11
+ import * as S from "./style";
12
+
13
+ const TableHeader = (props: IProps): JSX.Element => {
14
+ const { isScrolling, filterValues, filterItems, sortItems, isSortAscending, isModeUser } = props;
15
+
16
+ return (
17
+ <S.TableHeader isScrolling={isScrolling}>
18
+ {isModeUser ? (
19
+ <>
20
+ <S.FiltersHeader>
21
+ <DateFilter filterItems={filterItems} value={filterValues["date"]} />
22
+ <UserFilter filterItems={filterItems} value={filterValues["users"]} />
23
+ <EventFilter filterItems={filterItems} value={filterValues["eventTypes"]} />
24
+ <OrderFilter sortItems={sortItems} isAscending={isSortAscending} />
25
+ </S.FiltersHeader>
26
+ <S.SiteUserHeader>
27
+ <SiteFilter
28
+ filterItems={filterItems}
29
+ value={filterValues}
30
+ pointer="sites"
31
+ addGlobal={true}
32
+ center={false}
33
+ />
34
+ </S.SiteUserHeader>
35
+ <S.ContentUserHeader>
36
+ <ContentFilter filterItems={filterItems} value={filterValues["contentTypes"]} />
37
+ </S.ContentUserHeader>
38
+ </>
39
+ ) : (
40
+ <>
41
+ <S.UserHeader>
42
+ <DateFilter filterItems={filterItems} value={filterValues["date"]} />
43
+ <UserFilter filterItems={filterItems} value={filterValues["users"]} />
44
+ </S.UserHeader>
45
+ <S.TimeHeader>
46
+ <OrderFilter sortItems={sortItems} isAscending={isSortAscending} />
47
+ </S.TimeHeader>
48
+ <S.SiteHeader>
49
+ <SiteFilter filterItems={filterItems} value={filterValues} pointer="sites" addGlobal={true} />
50
+ </S.SiteHeader>
51
+ <S.ContentHeader>
52
+ <ContentFilter filterItems={filterItems} value={filterValues["contentTypes"]} />
53
+ </S.ContentHeader>
54
+ <S.EventHeader>
55
+ <EventFilter filterItems={filterItems} value={filterValues["eventTypes"]} />
56
+ </S.EventHeader>
57
+ </>
58
+ )}
59
+ </S.TableHeader>
60
+ );
61
+ };
62
+
63
+ interface IProps {
64
+ isScrolling: boolean;
65
+ filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
66
+ sortItems: (isAscending: boolean) => void;
67
+ isSortAscending: boolean;
68
+ filterValues: Record<string, IQueryValue[]>;
69
+ isModeUser: boolean;
70
+ }
71
+
72
+ export default TableHeader;