@griddo/ax 11.7.13 → 11.8.0-rc.1

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,167 @@
1
+ import React, { useState } from "react";
2
+ import { connect } from "react-redux";
3
+
4
+ import { LogActivityDTO, LogContentDTO, LogContentTypeDTO } from "@griddo/api-types";
5
+ import { Avatar, Tag, RestoreModal } from "@ax/components";
6
+ import { useModal } from "@ax/hooks";
7
+ import { pageEditorActions } from "@ax/containers/PageEditor";
8
+ import { activityLogActions } from "@ax/containers/ActivityLog";
9
+ import { navigationActions } from "@ax/containers/Navigation";
10
+ import { structuredDataActions } from "@ax/containers/StructuredData";
11
+ import { IRootState } from "@ax/types";
12
+
13
+ import DetailModal from "../../DetailModal";
14
+ import { eventKey } from "../../constants";
15
+ import { getContentTypeSchemaVersion, getPageSchemaVersion } from "../../utils";
16
+
17
+ import * as S from "./style";
18
+
19
+ const EventItem = (props: IEventItemProps) => {
20
+ const { item, schemaVersion, restorePage, restoreNavigation, restoreStructuredData, goToLogContent, getLog } = props;
21
+ const { user, created, site, contentType, content, eventType } = item;
22
+
23
+ const { isOpen: isDetailOpen, toggleModal: toggleDetailModal } = useModal();
24
+ const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
25
+ const [schemaChange, setSchemaChange] = useState(false);
26
+
27
+ const isDeleteEvent = eventType?.internal_key ? eventType.internal_key.includes("DELETED") : false;
28
+
29
+ const restoreByContent = async (type: string, id: number) => {
30
+ switch (type) {
31
+ case eventKey.DELETED_PAGE:
32
+ case eventKey.DELETED_CONTENT_TYPE_PAGE:
33
+ return await restorePage(id);
34
+ case eventKey.DELETED_HEADER:
35
+ return await restoreNavigation(id, "header");
36
+ case eventKey.DELETED_FOOTER:
37
+ return await restoreNavigation(id, "footer");
38
+ case eventKey.DELETED_CATEGORY:
39
+ case eventKey.DELETED_CONTENT_TYPE:
40
+ return await restoreStructuredData(id);
41
+ default:
42
+ return false;
43
+ }
44
+ };
45
+
46
+ const handleRestore = async () => {
47
+ const contentID = contentType?.id || content?.id;
48
+ if (contentID && eventType?.internal_key) {
49
+ const isRestored = await restoreByContent(eventType.internal_key, contentID);
50
+ if (isRestored) {
51
+ getLog();
52
+ isRestoreOpen && toggleRestoreModal();
53
+ isDetailOpen && toggleDetailModal();
54
+ }
55
+ }
56
+ };
57
+
58
+ const handleDetailRestorePage = async () => {
59
+ const contentID = contentType?.id || content?.id || null;
60
+ const hasSchemaVersion = [
61
+ eventKey.DELETED_PAGE,
62
+ eventKey.DELETED_CONTENT_TYPE_PAGE,
63
+ eventKey.DELETED_CONTENT_TYPE,
64
+ ].includes(eventType?.internal_key || "");
65
+
66
+ if (contentID && hasSchemaVersion) {
67
+ const pageSchemaVersion =
68
+ eventType?.internal_key === eventKey.DELETED_CONTENT_TYPE
69
+ ? await getContentTypeSchemaVersion(contentID)
70
+ : await getPageSchemaVersion(contentID);
71
+ if (schemaVersion !== pageSchemaVersion) {
72
+ setSchemaChange(true);
73
+ } else {
74
+ setSchemaChange(false);
75
+ }
76
+ }
77
+
78
+ toggleRestoreModal();
79
+ };
80
+
81
+ const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
82
+ e.stopPropagation();
83
+ const siteID = site?.id || null;
84
+ goToLogContent(contentType, content, siteID);
85
+ };
86
+
87
+ const handleKeyDown = () => {
88
+ const siteID = site?.id || null;
89
+ goToLogContent(contentType, content, siteID);
90
+ };
91
+
92
+ return (
93
+ <>
94
+ <S.Item onClick={toggleDetailModal}>
95
+ <S.User>
96
+ <S.AvatarWrapper>
97
+ <Avatar image={user.image} name={user.name || ""} />
98
+ </S.AvatarWrapper>
99
+ <S.Name>{user.name}</S.Name>
100
+ </S.User>
101
+ <S.Time>{created.hour}</S.Time>
102
+ <S.Site>
103
+ <Tag
104
+ text={site && site.name ? site.name : "Global"}
105
+ type="square"
106
+ color={site ? undefined : "#C3F4FF"}
107
+ textColor="rgba(32, 34, 76, 0.6)"
108
+ />
109
+ </S.Site>
110
+ <S.ContentType>
111
+ {!!contentType && <Tag text={contentType.content?.title || ""} color="#E6E7F8" small={true} />}
112
+ </S.ContentType>
113
+ <S.Event>
114
+ {eventType?.name || ""}{" "}
115
+ <div
116
+ onClick={!isDeleteEvent ? handleClick : undefined}
117
+ role="button"
118
+ tabIndex={0}
119
+ onKeyDown={!isDeleteEvent ? handleKeyDown : undefined}
120
+ >
121
+ {content?.title || contentType?.title || ""}
122
+ </div>
123
+ </S.Event>
124
+ </S.Item>
125
+ <DetailModal
126
+ isOpen={isDetailOpen}
127
+ toggleModal={toggleDetailModal}
128
+ itemLog={item}
129
+ restorePage={handleDetailRestorePage}
130
+ onClick={handleClick}
131
+ onKeyDown={handleKeyDown}
132
+ />
133
+ {isRestoreOpen && (
134
+ <RestoreModal
135
+ isOpen={isRestoreOpen}
136
+ toggleModal={toggleRestoreModal}
137
+ isChild={true}
138
+ hasIssues={schemaChange}
139
+ restorePage={handleRestore}
140
+ />
141
+ )}
142
+ </>
143
+ );
144
+ };
145
+
146
+ interface IEventItemProps {
147
+ item: LogActivityDTO;
148
+ schemaVersion: string;
149
+ restorePage(id: number): Promise<boolean>;
150
+ restoreNavigation(navID: number, type: string): Promise<boolean>;
151
+ restoreStructuredData(dataID: number): Promise<boolean>;
152
+ goToLogContent(contentType: LogContentTypeDTO | null, content: LogContentDTO | null, site: number | null): void;
153
+ getLog(): void;
154
+ }
155
+
156
+ const mapStateToProps = (state: IRootState) => ({
157
+ schemaVersion: state.structuredData.schemaVersion,
158
+ });
159
+
160
+ const mapDispatchToProps = {
161
+ restorePage: pageEditorActions.restorePage,
162
+ restoreNavigation: navigationActions.restoreNavigation,
163
+ restoreStructuredData: structuredDataActions.restoreStructuredDataContent,
164
+ goToLogContent: activityLogActions.goToLogContent,
165
+ };
166
+
167
+ export default connect(mapStateToProps, mapDispatchToProps)(EventItem);
@@ -0,0 +1,79 @@
1
+ import styled from "styled-components";
2
+
3
+ const Item = styled.div`
4
+ display: flex;
5
+ background-color: ${(p) => p.theme.color.uiBackground02};
6
+ border: ${(p) => `1px solid ${p.theme.color.uiLine}`};
7
+ height: ${(p) => p.theme.spacing.l};
8
+ cursor: pointer;
9
+ position: relative;
10
+ :before {
11
+ content: "";
12
+ background-color: transparent;
13
+ position: absolute;
14
+ top: 0;
15
+ left: 0;
16
+ width: 100%;
17
+ height: 100%;
18
+ pointer-events: none;
19
+ }
20
+ &:hover {
21
+ &:before {
22
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
23
+ }
24
+ }
25
+ `;
26
+
27
+ const User = styled.div`
28
+ display: flex;
29
+ align-items: center;
30
+ width: 24%;
31
+ padding-left: ${(p) => p.theme.spacing.s};
32
+ `;
33
+
34
+ const Name = styled.div`
35
+ ${(p) => p.theme.textStyle.uiS};
36
+ color: ${(p) => p.theme.colors.textHighEmphasis};
37
+ `;
38
+
39
+ const AvatarWrapper = styled.div`
40
+ margin-right: ${(p) => p.theme.spacing.s};
41
+ `;
42
+
43
+ const Time = styled.div`
44
+ ${(p) => p.theme.textStyle.uiXS};
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
49
+ width: 8%;
50
+ `;
51
+
52
+ const Site = styled.div`
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ width: 15%;
57
+ `;
58
+
59
+ const ContentType = styled.div`
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ width: 15%;
64
+ `;
65
+
66
+ const Event = styled.div`
67
+ ${(p) => p.theme.textStyle.uiS};
68
+ display: flex;
69
+ align-items: center;
70
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
71
+ width: 38%;
72
+ padding-right: ${(p) => p.theme.spacing.s};
73
+ div {
74
+ margin-left: ${(p) => p.theme.spacing.xxs};
75
+ color: ${(p) => p.theme.colors.interactive01};
76
+ }
77
+ `;
78
+
79
+ export { Item, User, Name, AvatarWrapper, Time, Site, ContentType, Event };
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { LogActivityGroupedDayDTO } from "@griddo/api-types";
3
+ import ItemGroup from "../ItemGroup";
4
+ import EventItem from "./EventItem";
5
+
6
+ const ItemLog = (props: IItemLogProps) => {
7
+ const { items, getLog } = props;
8
+ const { date, items: dayItems, totalItems } = items;
9
+
10
+ return (
11
+ <ItemGroup date={date} count={totalItems}>
12
+ {dayItems.map((item) => (
13
+ <EventItem key={item.id} item={item} getLog={getLog} />
14
+ ))}
15
+ </ItemGroup>
16
+ );
17
+ };
18
+
19
+ interface IItemLogProps {
20
+ items: LogActivityGroupedDayDTO;
21
+ getLog(): void;
22
+ }
23
+
24
+ export default ItemLog;
@@ -0,0 +1,170 @@
1
+ import React, { useState } from "react";
2
+ import { connect } from "react-redux";
3
+
4
+ import { LogActivityDTO, LogContentDTO, LogContentTypeDTO } from "@griddo/api-types";
5
+ import { useModal } from "@ax/hooks";
6
+ import { pageEditorActions } from "@ax/containers/PageEditor";
7
+ import { activityLogActions } from "@ax/containers/ActivityLog";
8
+ import { navigationActions } from "@ax/containers/Navigation";
9
+ import { structuredDataActions } from "@ax/containers/StructuredData";
10
+ import { IRootState } from "@ax/types";
11
+ import { RestoreModal } from "@ax/components";
12
+
13
+ import DetailModal from "./../../../DetailModal";
14
+ import { eventKey } from "./../../../constants";
15
+ import { getContentTypeSchemaVersion, getPageSchemaVersion } from "./../../../utils";
16
+
17
+ import * as S from "./style";
18
+
19
+ const EventItem = (props: IEventItemProps) => {
20
+ const { item, schemaVersion, restorePage, restoreNavigation, restoreStructuredData, goToLogContent, getLog } = props;
21
+
22
+ const { created, site, contentType, content, eventType } = item;
23
+
24
+ const { isOpen: isDetailOpen, toggleModal: toggleDetailModal } = useModal();
25
+ const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
26
+ const [schemaChange, setSchemaChange] = useState(false);
27
+
28
+ const isDeleteEvent = eventType?.internal_key ? eventType.internal_key.includes("DELETED") : false;
29
+
30
+ const restoreByContent = async (type: string, id: number) => {
31
+ switch (type) {
32
+ case eventKey.DELETED_PAGE:
33
+ case eventKey.DELETED_CONTENT_TYPE_PAGE:
34
+ return await restorePage(id);
35
+ case eventKey.DELETED_HEADER:
36
+ return await restoreNavigation(id, "header");
37
+ case eventKey.DELETED_FOOTER:
38
+ return await restoreNavigation(id, "footer");
39
+ case eventKey.DELETED_CATEGORY:
40
+ case eventKey.DELETED_CONTENT_TYPE:
41
+ return await restoreStructuredData(id);
42
+ default:
43
+ return false;
44
+ }
45
+ };
46
+
47
+ const handleRestore = async () => {
48
+ const contentID = contentType?.id || content?.id;
49
+ if (contentID && eventType?.internal_key) {
50
+ const isRestored = await restoreByContent(eventType.internal_key, contentID);
51
+ if (isRestored) {
52
+ getLog();
53
+ isRestoreOpen && toggleRestoreModal();
54
+ isDetailOpen && toggleDetailModal();
55
+ }
56
+ }
57
+ };
58
+
59
+ const handleDetailRestorePage = async () => {
60
+ const contentID = contentType?.id || content?.id || null;
61
+ const hasSchemaVersion = [
62
+ eventKey.DELETED_PAGE,
63
+ eventKey.DELETED_CONTENT_TYPE_PAGE,
64
+ eventKey.DELETED_CONTENT_TYPE,
65
+ ].includes(eventType?.internal_key || "");
66
+
67
+ if (contentID && hasSchemaVersion) {
68
+ const pageSchemaVersion =
69
+ eventType?.internal_key === eventKey.DELETED_CONTENT_TYPE
70
+ ? await getContentTypeSchemaVersion(contentID)
71
+ : await getPageSchemaVersion(contentID);
72
+ if (schemaVersion !== pageSchemaVersion) {
73
+ setSchemaChange(true);
74
+ } else {
75
+ setSchemaChange(false);
76
+ }
77
+ }
78
+
79
+ toggleRestoreModal();
80
+ };
81
+
82
+ const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
83
+ e.stopPropagation();
84
+ const siteID = site?.id || null;
85
+ goToLogContent(contentType, content, siteID);
86
+ };
87
+
88
+ const handleKeyDown = () => {
89
+ const siteID = site?.id || null;
90
+ goToLogContent(contentType, content, siteID);
91
+ };
92
+
93
+ return (
94
+ <>
95
+ <S.ActivityItem onClick={toggleDetailModal}>
96
+ <S.EventWrapper>
97
+ <S.Time>{created.hour}</S.Time>
98
+ <S.Event>
99
+ {eventType?.name || ""}{" "}
100
+ <div
101
+ onClick={!isDeleteEvent ? handleClick : undefined}
102
+ role="button"
103
+ tabIndex={0}
104
+ onKeyDown={!isDeleteEvent ? handleKeyDown : undefined}
105
+ >
106
+ {content?.title || contentType?.title || ""}
107
+ </div>
108
+ </S.Event>
109
+ </S.EventWrapper>
110
+ <S.Site>
111
+ <S.Label>Site</S.Label>
112
+ <S.StyledTag
113
+ text={site ? site.name : "Global"}
114
+ type="square"
115
+ color={site ? undefined : "#C3F4FF"}
116
+ textColor="rgba(32, 34, 76, 0.6)"
117
+ />
118
+ </S.Site>
119
+ <S.ContentType>
120
+ {!!contentType && (
121
+ <>
122
+ <S.Label>Content type</S.Label>
123
+ <S.StyledTag text={contentType.content?.title || ""} color="#E6E7F8" small={true} />
124
+ </>
125
+ )}
126
+ </S.ContentType>
127
+ </S.ActivityItem>
128
+ <DetailModal
129
+ isOpen={isDetailOpen}
130
+ toggleModal={toggleDetailModal}
131
+ itemLog={item}
132
+ restorePage={handleDetailRestorePage}
133
+ onClick={handleClick}
134
+ onKeyDown={handleKeyDown}
135
+ />
136
+ {isRestoreOpen && (
137
+ <RestoreModal
138
+ isOpen={isRestoreOpen}
139
+ toggleModal={toggleRestoreModal}
140
+ isChild={true}
141
+ restorePage={handleRestore}
142
+ hasIssues={schemaChange}
143
+ />
144
+ )}
145
+ </>
146
+ );
147
+ };
148
+
149
+ interface IEventItemProps {
150
+ item: LogActivityDTO;
151
+ schemaVersion: string;
152
+ restorePage(id: number): Promise<boolean>;
153
+ restoreNavigation(navID: number, type: string): Promise<boolean>;
154
+ restoreStructuredData(dataID: number): Promise<boolean>;
155
+ goToLogContent(contentType: LogContentTypeDTO | null, content: LogContentDTO | null, site: number | null): void;
156
+ getLog(): void;
157
+ }
158
+
159
+ const mapStateToProps = (state: IRootState) => ({
160
+ schemaVersion: state.structuredData.schemaVersion,
161
+ });
162
+
163
+ const mapDispatchToProps = {
164
+ restorePage: pageEditorActions.restorePage,
165
+ restoreNavigation: navigationActions.restoreNavigation,
166
+ restoreStructuredData: structuredDataActions.restoreStructuredDataContent,
167
+ goToLogContent: activityLogActions.goToLogContent,
168
+ };
169
+
170
+ export default connect(mapStateToProps, mapDispatchToProps)(EventItem);
@@ -0,0 +1,79 @@
1
+ import React from "react";
2
+ import styled from "styled-components";
3
+ import { Tag } from "@ax/components";
4
+
5
+ const ActivityItem = styled.div`
6
+ display: flex;
7
+ margin-bottom: ${(p) => p.theme.spacing.xxs};
8
+ position: relative;
9
+ cursor: pointer;
10
+ &:last-child {
11
+ margin-bottom: ${(p) => p.theme.spacing.xs};
12
+ }
13
+ :before {
14
+ content: "";
15
+ background-color: transparent;
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ pointer-events: none;
22
+ }
23
+ &:hover {
24
+ &:before {
25
+ background-color: ${(p) => p.theme.color.overlayHoverPrimary};
26
+ }
27
+ }
28
+ `;
29
+
30
+ const EventWrapper = styled.div`
31
+ display: flex;
32
+ width: 50%;
33
+ `;
34
+
35
+ const Time = styled.div`
36
+ ${(p) => p.theme.textStyle.uiXS};
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
41
+ width: 56px;
42
+ flex-shrink: 0;
43
+ `;
44
+
45
+ const Site = styled.div`
46
+ display: flex;
47
+ align-items: center;
48
+ width: 25%;
49
+ `;
50
+
51
+ const ContentType = styled.div`
52
+ display: flex;
53
+ align-items: center;
54
+ width: 25%;
55
+ `;
56
+
57
+ const Event = styled.div`
58
+ ${(p) => p.theme.textStyle.uiS};
59
+ display: flex;
60
+ align-items: center;
61
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
62
+ flex-grow: 1;
63
+ div {
64
+ margin-left: ${(p) => p.theme.spacing.xxs};
65
+ color: ${(p) => p.theme.colors.interactive01};
66
+ }
67
+ `;
68
+
69
+ const Label = styled.div`
70
+ ${(p) => p.theme.textStyle.uiM};
71
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
72
+ margin-right: ${(p) => p.theme.spacing.xs};
73
+ `;
74
+
75
+ const StyledTag = styled((props) => <Tag {...props} />)`
76
+ margin-bottom: 0;
77
+ `;
78
+
79
+ export { ActivityItem, EventWrapper, Time, Site, ContentType, Event, Label, StyledTag };
@@ -0,0 +1,46 @@
1
+ import React, { useState } from "react";
2
+ import { Avatar } from "@ax/components";
3
+ import EventItem from "./EventItem";
4
+
5
+ import * as S from "./style";
6
+
7
+ const UserItem = (props: IUserItemProps) => {
8
+ const { user, getLog } = props;
9
+ const { logActivity, ...userProps } = user;
10
+ const { image, name } = userProps;
11
+
12
+ const [isOpen, setIsOpen] = useState(false);
13
+
14
+ const handleToggle = () => setIsOpen((state) => !state);
15
+
16
+ const buttonText = isOpen ? "Hide events" : "Show events";
17
+
18
+ return (
19
+ <S.Item>
20
+ <S.User>
21
+ <S.AvatarWrapper>
22
+ <Avatar image={image} name={name || ""} size="s" />
23
+ </S.AvatarWrapper>
24
+ <S.Name>{name}</S.Name>
25
+ {!isOpen && <S.CounterWrapper>{logActivity.length} events created</S.CounterWrapper>}
26
+ <S.ToggleWrapper>
27
+ <S.Toggle onClick={handleToggle} isOpen={isOpen}>
28
+ {buttonText}
29
+ </S.Toggle>
30
+ </S.ToggleWrapper>
31
+ </S.User>
32
+ <S.EventList isOpen={isOpen}>
33
+ {logActivity.map((item: any, index: number) => (
34
+ <EventItem key={index} item={{ ...item, user: userProps }} getLog={getLog} />
35
+ ))}
36
+ </S.EventList>
37
+ </S.Item>
38
+ );
39
+ };
40
+
41
+ interface IUserItemProps {
42
+ user: any;
43
+ getLog(): void;
44
+ }
45
+
46
+ export default UserItem;
@@ -0,0 +1,60 @@
1
+ import styled from "styled-components";
2
+
3
+ const Item = styled.div`
4
+ display: flex;
5
+ flex-direction: column;
6
+ background-color: ${(p) => p.theme.color.uiBackground02};
7
+ border: ${(p) => `1px solid ${p.theme.color.uiLine}`};
8
+ min-height: ${(p) => p.theme.spacing.l};
9
+ `;
10
+
11
+ const User = styled.div`
12
+ display: flex;
13
+ align-items: center;
14
+ padding: ${(p) => `11px ${p.theme.spacing.s} ${p.theme.spacing.xs} ${p.theme.spacing.s}`};
15
+ `;
16
+
17
+ const Name = styled.div`
18
+ ${(p) => p.theme.textStyle.uiS};
19
+ color: ${(p) => p.theme.colors.textHighEmphasis};
20
+ width: 25%;
21
+ `;
22
+
23
+ const AvatarWrapper = styled.div`
24
+ margin-right: ${(p) => p.theme.spacing.s};
25
+ `;
26
+
27
+ const CounterWrapper = styled.div`
28
+ ${(p) => p.theme.textStyle.uiL};
29
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
30
+ `;
31
+
32
+ const ToggleWrapper = styled.div`
33
+ margin-left: auto;
34
+ `;
35
+
36
+ const EventList = styled.div<{ isOpen: boolean }>`
37
+ display: flex;
38
+ flex-direction: column;
39
+ height: ${(p) => (p.isOpen ? "auto" : "0px")};
40
+ overflow: hidden;
41
+ `;
42
+
43
+ const Toggle = styled.button<{ isOpen: boolean }>`
44
+ ${(p) => p.theme.textStyle.uiS};
45
+ position: relative;
46
+ padding-right: ${(p) => p.theme.spacing.s};
47
+ color: ${(p) => p.theme.colors.textMediumEmphasis};
48
+ &:after {
49
+ position: absolute;
50
+ top: 6px;
51
+ right: 0;
52
+ content: "";
53
+ border: solid ${(p) => p.theme.color.interactive01};
54
+ border-width: 0 2px 2px 0;
55
+ padding: 3px;
56
+ transform: ${(p) => (p.isOpen ? `rotate(-135deg) translate(-3px, 0)` : `rotate(45deg) translate(0, -3px)`)};
57
+ }
58
+ `;
59
+
60
+ export { Item, User, Name, AvatarWrapper, EventList, CounterWrapper, ToggleWrapper, Toggle };
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import ItemGroup from "../ItemGroup";
3
+ import UserItem from "./UserItem";
4
+
5
+ const ItemLogUser = (props: IItemLogUserProps) => {
6
+ const { items, getLog } = props;
7
+ const { date, user: users } = items;
8
+
9
+ const count = users.reduce((total: number, user: any) => total + user.logActivity.length, 0);
10
+
11
+ return (
12
+ <ItemGroup date={date} count={count}>
13
+ {users.map((user: any) => (
14
+ <UserItem key={user.id} user={user} getLog={getLog} />
15
+ ))}
16
+ </ItemGroup>
17
+ );
18
+ };
19
+
20
+ interface IItemLogUserProps {
21
+ items: any;
22
+ getLog(): void;
23
+ }
24
+
25
+ export default ItemLogUser;