@griddo/ax 11.14.2 → 11.14.3
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/config/jest/setup.js +13 -7
- package/package.json +2 -2
- package/src/__tests__/components/KeywordsPreviewModal/KeywordsPreviewModal.test.tsx +4 -3
- package/src/components/CategoryCell/index.tsx +3 -1
- package/src/components/ElementsTooltip/index.tsx +8 -4
- package/src/components/ErrorPage/index.tsx +3 -1
- package/src/components/FilterTagsBar/index.tsx +3 -3
- package/src/components/HeadingsPreviewModal/utils.tsx +2 -1
- package/src/components/KeywordsPreviewModal/atoms.tsx +2 -2
- package/src/components/KeywordsPreviewModal/index.tsx +6 -6
- package/src/components/KeywordsPreviewModal/utils.tsx +5 -3
- package/src/components/Modal/style.tsx +5 -5
- package/src/components/TableFilters/CheckGroupFilter/index.tsx +3 -2
- package/src/components/TableFilters/LiveFilter/index.tsx +4 -4
- package/src/components/TableFilters/SiteFilter/index.tsx +11 -12
- package/src/components/TableFilters/TranslationsFilter/index.tsx +2 -2
- package/src/components/TableFilters/TranslationsFilter/style.tsx +2 -2
- package/src/components/Tag/index.tsx +15 -7
- package/src/components/TruncatedTooltip/index.tsx +48 -0
- package/src/components/index.tsx +2 -0
- package/src/constants/index.ts +3 -0
- package/src/helpers/categoryColumns.tsx +55 -0
- package/src/helpers/images.tsx +3 -1
- package/src/helpers/index.tsx +2 -0
- package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +17 -10
- package/src/modules/ActivityLog/ItemLog/EventItem/style.tsx +18 -1
- package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +10 -7
- package/src/modules/ActivityLog/ItemLogUser/UserItem/index.tsx +9 -3
- package/src/modules/ActivityLog/ItemLogUser/UserItem/style.tsx +17 -1
- package/src/modules/App/Routing/NavMenu/NavItem/style.tsx +1 -0
- package/src/modules/App/Routing/index.tsx +2 -2
- package/src/modules/App/Routing/style.tsx +8 -1
- package/src/modules/Categories/CategoriesList/BulkHeader/TableHeader/style.tsx +1 -0
- package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +7 -3
- package/src/modules/Categories/CategoriesList/CategoryItem/style.tsx +38 -5
- package/src/modules/Content/BulkHeader/TableHeader/style.tsx +1 -1
- package/src/modules/Content/PageItem/index.tsx +80 -204
- package/src/modules/Content/PageItem/style.tsx +18 -10
- package/src/modules/Content/atoms.tsx +147 -18
- package/src/modules/Content/index.tsx +2 -9
- package/src/modules/Forms/FormCategoriesList/CategoryItem/index.tsx +7 -3
- package/src/modules/Forms/FormCategoriesList/CategoryItem/style.tsx +34 -0
- package/src/modules/Forms/FormEditor/index.tsx +28 -50
- package/src/modules/Forms/FormList/FormItem/index.tsx +91 -120
- package/src/modules/Forms/FormList/FormItem/style.tsx +19 -0
- package/src/modules/Forms/FormList/index.tsx +27 -48
- package/src/modules/Forms/atoms.tsx +44 -32
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +8 -8
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/style.tsx +2 -2
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +83 -101
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/style.tsx +11 -5
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +31 -54
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/style.tsx +13 -7
- package/src/modules/Users/Roles/BulkHeader/TableHeader/style.tsx +6 -6
- package/src/modules/Users/Roles/RoleItem/index.tsx +3 -4
- package/src/modules/Users/Roles/RoleItem/style.tsx +12 -15
- package/src/modules/Users/Roles/index.tsx +1 -2
- package/src/modules/Users/UserCreate/SiteItem/index.tsx +10 -4
- package/src/modules/Users/UserCreate/SiteItem/style.tsx +33 -1
- package/src/modules/Users/UserForm/index.tsx +6 -4
- package/src/modules/Users/UserList/BulkHeader/TableHeader/index.tsx +2 -4
- package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +1 -1
- package/src/modules/Users/UserList/UserItem/index.tsx +18 -10
- package/src/modules/Users/UserList/UserItem/style.tsx +60 -4
package/config/jest/setup.js
CHANGED
|
@@ -16,10 +16,16 @@ module.exports = () => {
|
|
|
16
16
|
|
|
17
17
|
window.matchMedia =
|
|
18
18
|
window.matchMedia ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
(() => ({
|
|
20
|
+
matches: false,
|
|
21
|
+
addListener: function () {},
|
|
22
|
+
removeListener: function () {},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
class ResizeObserverMock {
|
|
26
|
+
observe() {}
|
|
27
|
+
unobserve() {}
|
|
28
|
+
disconnect() {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
global.ResizeObserver = ResizeObserverMock;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "11.14.
|
|
4
|
+
"version": "11.14.3",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Diego M. Béjar <diego.bejar@secuoyas.com>",
|
|
@@ -219,5 +219,5 @@
|
|
|
219
219
|
"publishConfig": {
|
|
220
220
|
"access": "public"
|
|
221
221
|
},
|
|
222
|
-
"gitHead": "
|
|
222
|
+
"gitHead": "4367bb007b546db463c1a4c03a835af9d8b59709"
|
|
223
223
|
}
|
|
@@ -71,7 +71,8 @@ describe("KeywordsPreviewModal component rendering", () => {
|
|
|
71
71
|
renderComponent({ ...defaultProps, isOpen: true, keywordsFilter: ["seo"] });
|
|
72
72
|
|
|
73
73
|
expect(screen.getByText("Show keyword:")).toBeTruthy();
|
|
74
|
-
|
|
74
|
+
const seoElements = screen.getAllByText("seo");
|
|
75
|
+
expect(seoElements.length).toBeGreaterThan(0);
|
|
75
76
|
});
|
|
76
77
|
|
|
77
78
|
it("should not render the filter section when keywordsFilter is empty", () => {
|
|
@@ -87,8 +88,8 @@ describe("KeywordsPreviewModal component events", () => {
|
|
|
87
88
|
|
|
88
89
|
renderComponent({ ...defaultProps, isOpen: true, toggleModal: toggleModalMock });
|
|
89
90
|
|
|
90
|
-
const
|
|
91
|
-
fireEvent.click(
|
|
91
|
+
const closeButtons = screen.getAllByTestId("icon-action-component");
|
|
92
|
+
fireEvent.click(closeButtons[0]);
|
|
92
93
|
expect(toggleModalMock).toBeCalled();
|
|
93
94
|
});
|
|
94
95
|
|
|
@@ -66,11 +66,15 @@ const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
|
|
|
66
66
|
|
|
67
67
|
if (!elements) return <></>;
|
|
68
68
|
|
|
69
|
-
const
|
|
70
|
-
|
|
69
|
+
const filteredElements = elements.filter((element) => element !== null && element !== "");
|
|
70
|
+
|
|
71
|
+
if (filteredElements.length === 0) return <></>;
|
|
72
|
+
|
|
73
|
+
const visibleElements = filteredElements.slice(0, defaultElements);
|
|
74
|
+
const remainingElements = filteredElements.length - defaultElements;
|
|
71
75
|
|
|
72
76
|
const elementsRows: string[][] = [];
|
|
73
|
-
|
|
77
|
+
filteredElements.forEach((element, idx) => {
|
|
74
78
|
const row = Math.floor(idx / elementsPerRow);
|
|
75
79
|
const isNewRow = idx % elementsPerRow === 0;
|
|
76
80
|
elementsRows[row] = isNewRow ? [element] : [...elementsRows[row], element];
|
|
@@ -91,7 +95,7 @@ const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
|
|
|
91
95
|
<>
|
|
92
96
|
<S.Wrapper data-testid="elements-wrapper">
|
|
93
97
|
{visibleElements.map((fullElement, idx) => {
|
|
94
|
-
const element =
|
|
98
|
+
const element = maxChar ? trimText(fullElement, maxChar) : fullElement;
|
|
95
99
|
const color = defaultColor || colors?.[element];
|
|
96
100
|
|
|
97
101
|
return (
|
|
@@ -40,7 +40,9 @@ const ErrorPage = (props: IProps): JSX.Element => {
|
|
|
40
40
|
title: "Something went wrong",
|
|
41
41
|
description: <>Try refreshing the page, or try again later</>,
|
|
42
42
|
buttonText: "Refresh page",
|
|
43
|
-
buttonAction: () =>
|
|
43
|
+
buttonAction: () => {
|
|
44
|
+
window.location.href = "/logout";
|
|
45
|
+
},
|
|
44
46
|
},
|
|
45
47
|
wrongEditor: {
|
|
46
48
|
icon: "working",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import type { IQueryValue } from "@ax/types";
|
|
2
|
+
|
|
3
3
|
import Button from "../Button";
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
@@ -37,7 +37,7 @@ const FilterTagsBar = (props: IFilterTagsBarProps): JSX.Element => {
|
|
|
37
37
|
<S.TagList>
|
|
38
38
|
{tags.map((tag: string, index: number) => {
|
|
39
39
|
const handleDeleteTag = () => deleteTag(tag);
|
|
40
|
-
return <S.StyledTag key={index} text={tag} color="#FFFFFF" onDeleteAction={handleDeleteTag} />;
|
|
40
|
+
return <S.StyledTag key={index} text={tag} color="#FFFFFF" maxChar={30} onDeleteAction={handleDeleteTag} />;
|
|
41
41
|
})}
|
|
42
42
|
</S.TagList>
|
|
43
43
|
<S.ButtonWrapper>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GRIDDO_ID } from "@ax/constants";
|
|
1
2
|
import type { HeadingFilter, HeadingLevel, HeadingNode } from "@ax/types";
|
|
2
3
|
|
|
3
4
|
const MAX_HEADING_LENGTH = 70;
|
|
@@ -150,7 +151,7 @@ const analyzeHeadings = (headings: HeadingNode[], isFiltering = false): IHeading
|
|
|
150
151
|
|
|
151
152
|
const parseHeadingsTree = (html: HTMLDivElement): HeadingNode[] => {
|
|
152
153
|
const frameObject = html.querySelector<HTMLIFrameElement>(".frame-content");
|
|
153
|
-
const frameContent = frameObject?.contentWindow?.document.getElementById(
|
|
154
|
+
const frameContent = frameObject?.contentWindow?.document.getElementById(GRIDDO_ID) as HTMLElement;
|
|
154
155
|
|
|
155
156
|
if (!frameContent) {
|
|
156
157
|
return [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
|
+
import { FieldsBehavior, Modal } from "@ax/components";
|
|
3
4
|
import type { IModal } from "@ax/types";
|
|
4
|
-
import { Modal, FieldsBehavior } from "@ax/components";
|
|
5
5
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
@@ -39,7 +39,7 @@ const AddKeywordsModal = (props: IAddKeywordsModal) => {
|
|
|
39
39
|
secondaryAction={secondaryModalAction}
|
|
40
40
|
mainAction={mainModalAction}
|
|
41
41
|
size="S"
|
|
42
|
-
height={
|
|
42
|
+
height={288}
|
|
43
43
|
>
|
|
44
44
|
<S.ModalContent>
|
|
45
45
|
<FieldsBehavior
|
|
@@ -69,16 +69,16 @@ const KeywordsPreviewModal = (props: IKeywordsPreviewProps) => {
|
|
|
69
69
|
)}
|
|
70
70
|
<S.KeywordsListWrapper>
|
|
71
71
|
{keywords.length === 0 && <S.StyledSummaryButton />}
|
|
72
|
-
{
|
|
73
|
-
const isSelected = keywordsFilter.includes(
|
|
72
|
+
{keywords.map((keyword, index) => {
|
|
73
|
+
const isSelected = keywordsFilter.includes(keyword);
|
|
74
74
|
return (
|
|
75
75
|
<KeywordItem
|
|
76
|
-
keyword={
|
|
77
|
-
count={keywordCounts[
|
|
76
|
+
keyword={keyword}
|
|
77
|
+
count={keywordCounts[keyword] ?? 0}
|
|
78
78
|
isSelected={isSelected}
|
|
79
|
-
onClick={handleAddTag(
|
|
79
|
+
onClick={handleAddTag(keyword)}
|
|
80
80
|
deleteKeyword={handleDeleteKeyword}
|
|
81
|
-
key={`${
|
|
81
|
+
key={`${keyword}-${index}`}
|
|
82
82
|
/>
|
|
83
83
|
);
|
|
84
84
|
})}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { GRIDDO_ID } from "@ax/constants";
|
|
2
|
+
|
|
1
3
|
const countKeywords = (html: HTMLDivElement, keywords: string[]) => {
|
|
2
4
|
const frameObject = html.querySelector<HTMLIFrameElement>(".frame-content");
|
|
3
|
-
const frameContent = frameObject?.contentWindow?.document.getElementById(
|
|
5
|
+
const frameContent = frameObject?.contentWindow?.document.getElementById(GRIDDO_ID) as HTMLElement;
|
|
4
6
|
|
|
5
7
|
if (!frameContent) {
|
|
6
8
|
return {};
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
const htmlContent = frameContent.innerText.toLowerCase();
|
|
11
|
+
const htmlContent = frameContent.innerText.toLowerCase().normalize("NFC");
|
|
10
12
|
const keywordCounts: Record<string, number> = {};
|
|
11
13
|
|
|
12
14
|
keywords.forEach((keyword) => {
|
|
13
|
-
const lowerKeyword = keyword.toLowerCase();
|
|
15
|
+
const lowerKeyword = keyword.toLowerCase().normalize("NFC");
|
|
14
16
|
const regex = new RegExp(lowerKeyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
15
17
|
const matches = htmlContent.match(regex);
|
|
16
18
|
keywordCounts[keyword] = matches ? matches.length : 0;
|
|
@@ -26,6 +26,11 @@ const getHeight = (size: string | undefined) => {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const getModalHeight = (height?: number | string, size?: string) => {
|
|
30
|
+
const heightProp = typeof height === "number" ? `${height}px` : height;
|
|
31
|
+
return height !== undefined ? heightProp : getHeight(size);
|
|
32
|
+
};
|
|
33
|
+
|
|
29
34
|
const ModalOverlay = styled.div<{ isChild?: boolean }>`
|
|
30
35
|
position: fixed;
|
|
31
36
|
top: 0;
|
|
@@ -51,11 +56,6 @@ const ModalWrapper = styled.div<{ isChild?: boolean }>`
|
|
|
51
56
|
outline: 0;
|
|
52
57
|
`;
|
|
53
58
|
|
|
54
|
-
function getModalHeight(height?: number | string, size?: string) {
|
|
55
|
-
const heightProp = typeof height === "number" ? `${height}px` : height;
|
|
56
|
-
return height !== undefined ? heightProp : getHeight(size);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
59
|
const Modal = styled.div<{ size?: string; height?: number | string }>`
|
|
60
60
|
z-index: 100;
|
|
61
61
|
display: flex;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
2
3
|
import { CheckGroup, FloatingMenu, Icon, ListTitle, SearchField } from "@ax/components";
|
|
3
4
|
import { areEquals } from "@ax/helpers";
|
|
4
|
-
import { IFilterValue, IQueryValue } from "@ax/types";
|
|
5
|
+
import type { IFilterValue, IQueryValue } from "@ax/types";
|
|
5
6
|
|
|
6
7
|
import * as S from "./style";
|
|
7
8
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import { CheckGroup, Icon, FloatingMenu, ListTitle } from "@ax/components";
|
|
4
3
|
import { checkgroups } from "@ax/api";
|
|
4
|
+
import { CheckGroup, FloatingMenu, Icon, ListTitle } from "@ax/components";
|
|
5
5
|
import { areEquals, isReqOk } from "@ax/helpers";
|
|
6
|
-
import { IFilterValue, IPageLiveStatus, IQueryValue } from "@ax/types";
|
|
6
|
+
import type { IFilterValue, IPageLiveStatus, IQueryValue } from "@ax/types";
|
|
7
7
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
@@ -54,7 +54,7 @@ const LiveFilter = (props: ILiveFilterProps): JSX.Element => {
|
|
|
54
54
|
title: item.title,
|
|
55
55
|
icon: item.status,
|
|
56
56
|
};
|
|
57
|
-
if (
|
|
57
|
+
if (filterOptions?.includes(newFilter.value) || !filterOptions) {
|
|
58
58
|
filters.push(newFilter);
|
|
59
59
|
}
|
|
60
60
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
|
+
import { selects } from "@ax/api";
|
|
3
4
|
import { CheckGroupFilter } from "@ax/components";
|
|
4
5
|
import { isReqOk } from "@ax/helpers";
|
|
5
|
-
import {
|
|
6
|
-
import { IFilterValue, IQueryValue } from "@ax/types";
|
|
6
|
+
import type { IFilterValue, IQueryValue } from "@ax/types";
|
|
7
7
|
|
|
8
8
|
const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
|
|
9
9
|
const {
|
|
@@ -47,15 +47,14 @@ const SiteFilter = (props: ISiteFilterProps): JSX.Element => {
|
|
|
47
47
|
useEffect(() => {
|
|
48
48
|
getSelectSites()
|
|
49
49
|
.then((items) => {
|
|
50
|
-
items
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
50
|
+
items?.forEach((item: { value: string; label: string }) => {
|
|
51
|
+
const newFilter = {
|
|
52
|
+
name: item.value,
|
|
53
|
+
value: item.value,
|
|
54
|
+
title: item.label,
|
|
55
|
+
};
|
|
56
|
+
filters.push(newFilter);
|
|
57
|
+
});
|
|
59
58
|
|
|
60
59
|
setOptions(filters);
|
|
61
60
|
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { CheckGroup, FloatingMenu, Icon, ListTitle } from "@ax/components";
|
|
4
4
|
import { areEquals } from "@ax/helpers";
|
|
5
|
-
import { IFilterValue, IQueryValue } from "@ax/types";
|
|
5
|
+
import type { IFilterValue, IQueryValue } from "@ax/types";
|
|
6
6
|
|
|
7
7
|
import * as S from "./style";
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import styled from "styled-components";
|
|
3
1
|
import { Header } from "@ax/components/TableList/style";
|
|
4
2
|
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
|
|
5
5
|
const Translations = styled((props) => <Header {...props} />)<{ isActive: boolean }>`
|
|
6
6
|
width: 115px;
|
|
7
7
|
justify-content: center;
|
|
@@ -3,7 +3,14 @@ import { Icon } from "@ax/components";
|
|
|
3
3
|
import * as S from "./style";
|
|
4
4
|
|
|
5
5
|
const Tag = (props: ITagProps): JSX.Element => {
|
|
6
|
-
const { type, text, color, icon, textColor, rounded = true, onDeleteAction, className, small } = props;
|
|
6
|
+
const { type, text, color, icon, textColor, rounded = true, onDeleteAction, className, small, maxChar } = props;
|
|
7
|
+
|
|
8
|
+
const truncateText = (str: string, max: number) => {
|
|
9
|
+
if (str.length <= max) return str;
|
|
10
|
+
return `${str.slice(0, max)}...`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const displayText = maxChar && text ? truncateText(text, maxChar) : text;
|
|
7
14
|
|
|
8
15
|
const handleClick = () => {
|
|
9
16
|
if (onDeleteAction) {
|
|
@@ -22,27 +29,27 @@ const Tag = (props: ITagProps): JSX.Element => {
|
|
|
22
29
|
switch (type) {
|
|
23
30
|
case "status":
|
|
24
31
|
return (
|
|
25
|
-
<S.TagStatus className={className} data-testid="tag-status">
|
|
32
|
+
<S.TagStatus className={className} data-testid="tag-status" title={text || ""}>
|
|
26
33
|
<S.Bullet color={color} />
|
|
27
|
-
{
|
|
34
|
+
{displayText}
|
|
28
35
|
</S.TagStatus>
|
|
29
36
|
);
|
|
30
37
|
case "square":
|
|
31
38
|
return (
|
|
32
|
-
<S.TagSquare color={color} textColor={textColor} className={className} data-testid="tag-square">
|
|
39
|
+
<S.TagSquare color={color} textColor={textColor} className={className} data-testid="tag-square" title={text || ""}>
|
|
33
40
|
{icon && (
|
|
34
41
|
<S.IconTag>
|
|
35
42
|
<Icon name={icon} size="16" />
|
|
36
43
|
</S.IconTag>
|
|
37
44
|
)}
|
|
38
|
-
<div>{
|
|
45
|
+
<div>{displayText}</div>
|
|
39
46
|
</S.TagSquare>
|
|
40
47
|
);
|
|
41
48
|
default:
|
|
42
49
|
return (
|
|
43
|
-
<S.TagFixed color={color} rounded={rounded} small={small} className={className} data-testid="tag-fixed">
|
|
50
|
+
<S.TagFixed color={color} rounded={rounded} small={small} className={className} data-testid="tag-fixed" title={text || ""}>
|
|
44
51
|
<S.TagText>
|
|
45
|
-
<S.Title data-testid="tag-fixed-title">{
|
|
52
|
+
<S.Title data-testid="tag-fixed-title">{displayText}</S.Title>
|
|
46
53
|
{deleteIcon}
|
|
47
54
|
</S.TagText>
|
|
48
55
|
</S.TagFixed>
|
|
@@ -60,6 +67,7 @@ export interface ITagProps {
|
|
|
60
67
|
onDeleteAction?: () => void;
|
|
61
68
|
className?: string;
|
|
62
69
|
small?: boolean;
|
|
70
|
+
maxChar?: number;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
export default Tag;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { Tooltip } from "@ax/components";
|
|
4
|
+
|
|
5
|
+
const TruncatedTooltip = ({ content, children, ...props }: any) => {
|
|
6
|
+
const [isTruncated, setIsTruncated] = React.useState(false);
|
|
7
|
+
const elementRef = React.useRef<HTMLElement | null>(null);
|
|
8
|
+
|
|
9
|
+
const checkTruncation = React.useCallback(() => {
|
|
10
|
+
if (elementRef.current) {
|
|
11
|
+
const isTrunc = elementRef.current.scrollWidth > elementRef.current.clientWidth;
|
|
12
|
+
setIsTruncated(isTrunc);
|
|
13
|
+
}
|
|
14
|
+
}, []);
|
|
15
|
+
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const element = elementRef.current;
|
|
18
|
+
if (!element) return;
|
|
19
|
+
|
|
20
|
+
checkTruncation();
|
|
21
|
+
|
|
22
|
+
const observer = new ResizeObserver(() => {
|
|
23
|
+
checkTruncation();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
observer.observe(element);
|
|
27
|
+
|
|
28
|
+
return () => {
|
|
29
|
+
observer.disconnect();
|
|
30
|
+
};
|
|
31
|
+
}, [checkTruncation]);
|
|
32
|
+
|
|
33
|
+
const ChildWithRef = React.cloneElement(children, {
|
|
34
|
+
ref: elementRef,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!isTruncated) {
|
|
38
|
+
return ChildWithRef;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Tooltip content={content} {...props}>
|
|
43
|
+
{ChildWithRef}
|
|
44
|
+
</Tooltip>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default TruncatedTooltip;
|
package/src/components/index.tsx
CHANGED
|
@@ -125,6 +125,7 @@ import Tabs from "./Tabs";
|
|
|
125
125
|
import Tag from "./Tag";
|
|
126
126
|
import Toast from "./Toast";
|
|
127
127
|
import Tooltip from "./Tooltip";
|
|
128
|
+
import TruncatedTooltip from "./TruncatedTooltip";
|
|
128
129
|
import UserRolesAndSites from "./UserRolesAndSites";
|
|
129
130
|
|
|
130
131
|
export {
|
|
@@ -246,6 +247,7 @@ export {
|
|
|
246
247
|
Tooltip,
|
|
247
248
|
TranslateButton,
|
|
248
249
|
TranslationsFilter,
|
|
250
|
+
TruncatedTooltip,
|
|
249
251
|
TypeFilter,
|
|
250
252
|
UniqueCheck,
|
|
251
253
|
UrlField,
|
package/src/constants/index.ts
CHANGED
|
@@ -29,6 +29,8 @@ const VALID_DOCUMENT_FORMATS = ["pdf", "doc", "docx", "xls", "xlsx", "zip", "csv
|
|
|
29
29
|
const VALID_VIDEO_FORMATS = ["mov", "mp4", "wmv", "avi", "webm", "mkv"];
|
|
30
30
|
const VALID_FILE_FORMATS = [...VALID_DOCUMENT_FORMATS, ...VALID_VIDEO_FORMATS];
|
|
31
31
|
|
|
32
|
+
const GRIDDO_ID = "___griddo" as const;
|
|
33
|
+
|
|
32
34
|
export {
|
|
33
35
|
itemLabel,
|
|
34
36
|
type ItemLabel,
|
|
@@ -36,4 +38,5 @@ export {
|
|
|
36
38
|
VALID_DOCUMENT_FORMATS,
|
|
37
39
|
VALID_VIDEO_FORMATS,
|
|
38
40
|
VALID_FILE_FORMATS,
|
|
41
|
+
GRIDDO_ID,
|
|
39
42
|
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { CategoryCell } from "@ax/components";
|
|
4
|
+
import { Cell } from "@ax/components/TableList/TableItem/style";
|
|
5
|
+
import type { ISchemaField } from "@ax/types";
|
|
6
|
+
|
|
7
|
+
import styled from "styled-components";
|
|
8
|
+
|
|
9
|
+
const ColumnCell = styled(Cell)`
|
|
10
|
+
flex: 0 0 215px;
|
|
11
|
+
position: relative;
|
|
12
|
+
align-items: center;
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const buildCategoryColumns = (
|
|
16
|
+
categoryColumns: ISchemaField[],
|
|
17
|
+
activeColumns: string[],
|
|
18
|
+
contentData: Record<string, any> | undefined,
|
|
19
|
+
categoryColors: any,
|
|
20
|
+
addCategoryColors: (cats: string[]) => void,
|
|
21
|
+
onClick: () => void,
|
|
22
|
+
) => {
|
|
23
|
+
return categoryColumns.map((col) => {
|
|
24
|
+
if (!activeColumns.includes(col.key)) {
|
|
25
|
+
return <React.Fragment key={col.key} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const type: any = contentData?.[col.key];
|
|
29
|
+
|
|
30
|
+
if (typeof type !== "object") {
|
|
31
|
+
return (
|
|
32
|
+
<ColumnCell key={col.key} onClick={onClick}>
|
|
33
|
+
{type}
|
|
34
|
+
</ColumnCell>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const categories: string[] = !type
|
|
39
|
+
? []
|
|
40
|
+
: Array.isArray(type)
|
|
41
|
+
? type.map((cat: any) => cat.label || cat.title)
|
|
42
|
+
: [type.label || type.title];
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<CategoryCell
|
|
46
|
+
key={col.key}
|
|
47
|
+
categories={categories}
|
|
48
|
+
categoryColors={categoryColors}
|
|
49
|
+
addCategoryColors={addCategoryColors}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { buildCategoryColumns, ColumnCell };
|
package/src/helpers/images.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Area } from "react-easy-crop";
|
|
2
2
|
|
|
3
|
+
import { GRIDDO_ID } from "@ax/constants";
|
|
4
|
+
|
|
3
5
|
import { toBlob } from "html-to-image";
|
|
4
6
|
|
|
5
7
|
const formatBytes = (bytes: number | null, decimals = 2) => {
|
|
@@ -65,7 +67,7 @@ const getImageFromHtml = async (html: HTMLDivElement, fileName: string): Promise
|
|
|
65
67
|
|
|
66
68
|
const getImageFromIFrame = async (html: HTMLDivElement, fileName: string): Promise<File | null> => {
|
|
67
69
|
const frameOBject = html.querySelector<HTMLIFrameElement>(".frame-content");
|
|
68
|
-
const frameContentFirst = frameOBject?.contentWindow?.document.getElementById(
|
|
70
|
+
const frameContentFirst = frameOBject?.contentWindow?.document.getElementById(GRIDDO_ID)?.firstChild as HTMLElement;
|
|
69
71
|
const frameContentId = frameOBject?.contentWindow?.document.getElementById("griddoFormThumb") as HTMLElement;
|
|
70
72
|
|
|
71
73
|
const frameContent = frameContentId || frameContentFirst;
|
package/src/helpers/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { arrayInsert, isEmptyArray, moveArrayElement } from "./arrays";
|
|
2
|
+
import { buildCategoryColumns } from "./categoryColumns";
|
|
2
3
|
import {
|
|
3
4
|
areAllComponentsEmpty,
|
|
4
5
|
areEqual,
|
|
@@ -117,6 +118,7 @@ export {
|
|
|
117
118
|
areEqualDates,
|
|
118
119
|
areEquals,
|
|
119
120
|
arrayInsert,
|
|
121
|
+
buildCategoryColumns,
|
|
120
122
|
camelize,
|
|
121
123
|
capitalize,
|
|
122
124
|
compressImage,
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { useState } from "react";
|
|
2
3
|
import { connect } from "react-redux";
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
import { Avatar, Tag, RestoreModal } from "@ax/components";
|
|
6
|
-
import { useModal } from "@ax/hooks";
|
|
7
|
-
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
5
|
+
import { Avatar, RestoreModal, Tag, TruncatedTooltip } from "@ax/components";
|
|
8
6
|
import { activityLogActions } from "@ax/containers/ActivityLog";
|
|
9
7
|
import { navigationActions } from "@ax/containers/Navigation";
|
|
8
|
+
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
10
9
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
11
|
-
import {
|
|
10
|
+
import { useModal } from "@ax/hooks";
|
|
11
|
+
import type { IRootState } from "@ax/types";
|
|
12
|
+
|
|
13
|
+
import type { LogActivityDTO, LogContentDTO, LogContentTypeDTO } from "@griddo/api-types";
|
|
12
14
|
|
|
13
|
-
import DetailModal from "../../DetailModal";
|
|
14
15
|
import { eventKey } from "../../constants";
|
|
16
|
+
import DetailModal from "../../DetailModal";
|
|
15
17
|
import { getContentTypeSchemaVersion, getPageSchemaVersion } from "../../utils";
|
|
16
18
|
|
|
17
19
|
import * as S from "./style";
|
|
@@ -96,19 +98,24 @@ const EventItem = (props: IEventItemProps) => {
|
|
|
96
98
|
<S.AvatarWrapper>
|
|
97
99
|
<Avatar image={user.image} name={user.name || ""} />
|
|
98
100
|
</S.AvatarWrapper>
|
|
99
|
-
<S.Name>
|
|
101
|
+
<S.Name>
|
|
102
|
+
<TruncatedTooltip content={user.name || ""} expanded top={-5}>
|
|
103
|
+
<S.Title>{user.name}</S.Title>
|
|
104
|
+
</TruncatedTooltip>
|
|
105
|
+
</S.Name>
|
|
100
106
|
</S.User>
|
|
101
107
|
<S.Time>{created.hour}</S.Time>
|
|
102
108
|
<S.Site>
|
|
103
109
|
<Tag
|
|
104
|
-
text={site
|
|
110
|
+
text={site?.name ? site.name : "Global"}
|
|
105
111
|
type="square"
|
|
106
112
|
color={site ? undefined : "#C3F4FF"}
|
|
107
113
|
textColor="rgba(32, 34, 76, 0.6)"
|
|
114
|
+
maxChar={30}
|
|
108
115
|
/>
|
|
109
116
|
</S.Site>
|
|
110
117
|
<S.ContentType>
|
|
111
|
-
{!!contentType && <Tag text={contentType.content?.title || ""} color="#E6E7F8" small={true} />}
|
|
118
|
+
{!!contentType && <Tag text={contentType.content?.title || ""} color="#E6E7F8" small={true} maxChar={30} />}
|
|
112
119
|
</S.ContentType>
|
|
113
120
|
<S.Event>
|
|
114
121
|
{eventType?.name || ""}{" "}
|
|
@@ -32,8 +32,25 @@ const User = styled.div`
|
|
|
32
32
|
`;
|
|
33
33
|
|
|
34
34
|
const Name = styled.div`
|
|
35
|
+
position: relative;
|
|
35
36
|
${(p) => p.theme.textStyle.uiS};
|
|
36
37
|
color: ${(p) => p.theme.colors.textHighEmphasis};
|
|
38
|
+
min-width: 0;
|
|
39
|
+
> * {
|
|
40
|
+
min-width: 0;
|
|
41
|
+
max-width: 100%;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
const Title = styled.div`
|
|
46
|
+
width: 100%;
|
|
47
|
+
${(p) => p.theme.textStyle.uiS};
|
|
48
|
+
color: ${(p) => p.theme.colors.textHighEmphasis};
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
text-overflow: ellipsis;
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
display: block;
|
|
53
|
+
min-width: 0;
|
|
37
54
|
`;
|
|
38
55
|
|
|
39
56
|
const AvatarWrapper = styled.div`
|
|
@@ -78,4 +95,4 @@ const Event = styled.div`
|
|
|
78
95
|
}
|
|
79
96
|
`;
|
|
80
97
|
|
|
81
|
-
export { Item, User, Name, AvatarWrapper, Time, Site, ContentType, Event };
|
|
98
|
+
export { Item, User, Name, Title, AvatarWrapper, Time, Site, ContentType, Event };
|