@griddo/ax 10.1.96 → 10.2.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.
- package/package.json +3 -2
- package/src/__mocks__/axios/Roles.ts +10 -0
- package/src/__mocks__/axios/UserList.ts +545 -0
- package/src/__mocks__/store/GenericStore.ts +25 -0
- package/src/__mocks__/store/Roles.ts +1050 -0
- package/src/__mocks__/store/SitesList.ts +7 -1
- package/src/__mocks__/store/UserList.ts +482 -0
- package/src/__mocks__/store/UsersCreate.ts +298 -0
- package/src/__tests__/components/Avatar/Avatar.test.tsx +49 -48
- package/src/__tests__/components/ConfigPanel/ConfigPanel.test.tsx +2 -0
- package/src/__tests__/components/ConfigPanel/Form/Form.test.tsx +2 -0
- package/src/__tests__/components/ConfigPanel/GlobalPageForm/GlobalPageForm.test.tsx +25 -0
- package/src/__tests__/components/Fields/Button/Button.test.tsx +2 -2
- package/src/__tests__/components/Fields/ImageField/ImageField.test.tsx +2 -0
- package/src/__tests__/components/Fields/IntegrationsField/IntegrationsField.test.tsx +44 -2
- package/src/__tests__/components/Fields/Tooltip/Tooltip.test.tsx +0 -1
- package/src/__tests__/components/Gallery/Gallery.test.tsx +4 -0
- package/src/__tests__/components/Gallery/GalleryPanel/DetailPanel/DetailPanel.test.tsx +14 -0
- package/src/__tests__/components/Gallery/GalleryPanel/GalleryPanel.test.tsx +2 -1
- package/src/__tests__/components/Lists/Lists.test.tsx +3 -3
- package/src/__tests__/components/Login/Login.test.tsx +1 -1
- package/src/__tests__/components/TableFilters/DateFilter/DateFilter.test.tsx +1 -1
- package/src/__tests__/components/TableFilters/NameFilter/NameFilter.test.tsx +1 -1
- package/src/__tests__/components/TableFilters/RoleFilter/RoleFilter.test.tsx +165 -0
- package/src/__tests__/components/TableFilters/StatusFilter/StatusFilter.test.tsx +2 -2
- package/src/__tests__/components/TableFilters/UsersFilter/UsersFilter.test.tsx +153 -0
- package/src/__tests__/components/Tabs/Tabs.test.tsx +1 -1
- package/src/__tests__/modules/Settings/Integrations/Integrations.test.tsx +6 -0
- package/src/__tests__/modules/Sites/Sites.test.tsx +2 -1
- package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +14 -5
- package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +6 -4
- package/src/__tests__/modules/Users/Roles/BulkHeader/BulkHeader.test.tsx +158 -0
- package/src/__tests__/modules/Users/Roles/Roles.test.tsx +619 -0
- package/src/__tests__/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/RoleItem.test.tsx +107 -0
- package/src/__tests__/modules/Users/UserCreate/SiteItem/RolesModal/RolesModal.test.tsx +159 -0
- package/src/__tests__/modules/Users/UserCreate/SiteItem/SiteItem.test.tsx +175 -0
- package/src/__tests__/modules/Users/UserCreate/UserCreate.test.tsx +320 -0
- package/src/__tests__/modules/Users/UserList/UserItem/UserItem.test.tsx +417 -0
- package/src/__tests__/modules/Users/UserList/UserList.test.tsx +310 -0
- package/src/api/index.tsx +2 -0
- package/src/api/roles.tsx +77 -0
- package/src/api/users.tsx +22 -2
- package/src/components/ActionMenu/index.tsx +12 -6
- package/src/components/Avatar/index.tsx +5 -3
- package/src/components/Avatar/style.tsx +8 -9
- package/src/components/BulkSelectionOptions/index.tsx +19 -12
- package/src/components/BulkSelectionOptions/style.tsx +6 -11
- package/src/components/ConfigPanel/Form/index.tsx +24 -1
- package/src/components/ConfigPanel/GlobalPageForm/index.tsx +17 -4
- package/src/components/ElementsTooltip/index.tsx +1 -1
- package/src/components/Fields/IntegrationsField/index.tsx +5 -6
- package/src/components/Fields/RadioField/index.tsx +1 -1
- package/src/components/Fields/ReferenceField/AutoPanel/index.tsx +3 -3
- package/src/components/Fields/ReferenceField/ItemList/index.tsx +1 -1
- package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +3 -3
- package/src/components/Fields/TagsField/index.tsx +4 -2
- package/src/components/Fields/TextField/index.tsx +3 -0
- package/src/components/Fields/UrlField/index.tsx +5 -5
- package/src/components/Gallery/GalleryPanel/DetailPanel/index.tsx +42 -15
- package/src/components/Gallery/GalleryPanel/GalleryDragAndDrop/index.tsx +1 -1
- package/src/components/Gallery/GalleryPanel/index.tsx +20 -5
- package/src/components/Gallery/index.tsx +12 -6
- package/src/components/Icon/index.tsx +9 -1
- package/src/components/MainWrapper/AppBar/atoms.tsx +2 -2
- package/src/components/MainWrapper/AppBar/index.tsx +12 -10
- package/src/components/MainWrapper/AppBar/style.tsx +2 -1
- package/src/components/Modal/style.tsx +2 -2
- package/src/components/Nav/index.tsx +12 -2
- package/src/components/PageFinder/index.tsx +2 -2
- package/src/components/SearchField/index.tsx +3 -8
- package/src/components/TableFilters/PermissionsFilter/index.tsx +50 -0
- package/src/{modules/Users/UserList/HeaderMenus/Name → components/TableFilters/PermissionsFilter}/style.tsx +6 -2
- package/src/components/TableFilters/RoleFilter/index.tsx +61 -0
- package/src/components/TableFilters/RoleFilter/style.tsx +28 -0
- package/src/components/TableFilters/UsersFilter/index.tsx +55 -0
- package/src/components/TableFilters/UsersFilter/style.tsx +31 -0
- package/src/components/TableFilters/index.tsx +6 -0
- package/src/components/TableList/TableItem/style.tsx +2 -2
- package/src/components/TableList/style.tsx +1 -1
- package/src/components/index.tsx +7 -1
- package/src/containers/App/actions.tsx +3 -3
- package/src/containers/PageEditor/actions.tsx +14 -20
- package/src/containers/Redirects/actions.tsx +1 -0
- package/src/containers/Sites/actions.tsx +22 -14
- package/src/containers/Sites/interfaces.tsx +3 -3
- package/src/containers/Sites/reducer.tsx +1 -1
- package/src/containers/StructuredData/actions.tsx +15 -3
- package/src/containers/Users/actions.tsx +160 -26
- package/src/containers/Users/constants.tsx +8 -10
- package/src/containers/Users/interfaces.tsx +25 -3
- package/src/containers/Users/reducer.tsx +24 -15
- package/src/guards/index.tsx +2 -1
- package/src/guards/restricted/index.tsx +21 -0
- package/src/hooks/index.tsx +3 -0
- package/src/hooks/users.tsx +38 -0
- package/src/modules/App/Routing/NavMenu/NavItem/index.tsx +10 -5
- package/src/modules/App/Routing/NavMenu/index.tsx +16 -7
- package/src/modules/App/Routing/PrivateRoute/index.tsx +13 -5
- package/src/modules/App/Routing/index.tsx +17 -6
- package/src/modules/Categories/CategoriesList/BulkHeader/TableHeader/style.tsx +1 -0
- package/src/modules/Categories/CategoriesList/BulkHeader/index.tsx +2 -10
- package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +27 -12
- package/src/modules/Categories/CategoriesList/CategoryItem/style.tsx +4 -2
- package/src/modules/Categories/CategoriesList/index.tsx +27 -8
- package/src/modules/Content/BulkHeader/index.tsx +7 -3
- package/src/modules/Content/PageImporter/index.tsx +1 -1
- package/src/modules/Content/PageItem/index.tsx +45 -31
- package/src/modules/Content/PageItem/style.tsx +2 -1
- package/src/modules/Content/index.tsx +22 -13
- package/src/modules/FramePreview/index.tsx +2 -2
- package/src/modules/GlobalEditor/index.tsx +68 -53
- package/src/modules/GlobalSettings/index.tsx +2 -0
- package/src/modules/Navigation/Defaults/BulkHeader/index.tsx +2 -10
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +9 -11
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +5 -1
- package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +10 -5
- package/src/modules/Navigation/Defaults/Item/index.tsx +41 -27
- package/src/modules/Navigation/Defaults/Item/style.tsx +2 -1
- package/src/modules/Navigation/Defaults/index.tsx +29 -10
- package/src/modules/Navigation/Menus/List/Table/Header/index.tsx +7 -5
- package/src/modules/Navigation/Menus/List/Table/Item/index.tsx +10 -10
- package/src/modules/Navigation/Menus/List/Table/Item/style.tsx +2 -1
- package/src/modules/Navigation/Menus/List/index.tsx +6 -2
- package/src/modules/Navigation/Menus/index.tsx +12 -7
- package/src/modules/PageEditor/Editor/index.tsx +5 -1
- package/src/modules/PageEditor/PageBrowser/index.tsx +9 -3
- package/src/modules/PageEditor/index.tsx +67 -57
- package/src/modules/Redirects/index.tsx +97 -98
- package/src/modules/Settings/ContentTypes/DataPacks/AddModal/index.tsx +5 -1
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/TemplateBrowser/index.tsx +8 -9
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/index.tsx +7 -3
- package/src/modules/Settings/ContentTypes/DataPacks/Config/index.tsx +5 -1
- package/src/modules/Settings/ContentTypes/DataPacks/Item/index.tsx +5 -1
- package/src/modules/Settings/Integrations/BulkHeader/index.tsx +2 -17
- package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +6 -2
- package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +18 -8
- package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +6 -3
- package/src/modules/Settings/Integrations/index.tsx +32 -7
- package/src/modules/Settings/Languages/LanguagePanel/index.tsx +6 -2
- package/src/modules/Settings/Languages/Table/Header/index.tsx +4 -2
- package/src/modules/Settings/Languages/Table/Item/index.tsx +19 -43
- package/src/modules/Settings/Languages/Table/Item/style.tsx +11 -54
- package/src/modules/Settings/Languages/index.tsx +2 -2
- package/src/modules/Settings/SeoAnalyticsSettings/Analytics/index.tsx +2 -4
- package/src/modules/Settings/SeoAnalyticsSettings/index.tsx +4 -2
- package/src/modules/Settings/Social/index.tsx +1 -1
- package/src/modules/Settings/index.tsx +17 -11
- package/src/modules/Sites/SitesList/GridView/GridSiteItem/index.tsx +31 -18
- package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +21 -12
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +31 -18
- package/src/modules/Sites/SitesList/RecentSiteItem/index.tsx +1 -1
- package/src/modules/Sites/SitesList/index.tsx +16 -24
- package/src/modules/Sites/index.tsx +7 -3
- package/src/modules/StructuredData/Form/index.tsx +1 -1
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +8 -5
- package/src/modules/StructuredData/StructuredDataList/ContentFilters/index.tsx +8 -5
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +29 -15
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +50 -19
- package/src/modules/StructuredData/StructuredDataList/index.tsx +9 -6
- package/src/modules/Users/Profile/index.tsx +16 -4
- package/src/modules/Users/Roles/BulkHeader/TableHeader/index.tsx +52 -0
- package/src/modules/Users/Roles/BulkHeader/TableHeader/style.tsx +43 -0
- package/src/modules/Users/Roles/BulkHeader/index.tsx +74 -0
- package/src/modules/Users/Roles/RoleItem/index.tsx +104 -0
- package/src/modules/Users/Roles/RoleItem/style.tsx +127 -0
- package/src/modules/Users/Roles/SideModal/index.tsx +81 -0
- package/src/modules/Users/Roles/SideModal/style.tsx +132 -0
- package/src/modules/Users/Roles/hooks.tsx +78 -0
- package/src/modules/Users/Roles/index.tsx +256 -0
- package/src/modules/Users/Roles/style.tsx +23 -0
- package/src/modules/Users/Roles/utils.tsx +12 -0
- package/src/modules/Users/UserCreate/OptionItem/index.tsx +45 -0
- package/src/modules/Users/UserCreate/OptionItem/style.tsx +48 -0
- package/src/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/index.tsx +48 -0
- package/src/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/style.tsx +42 -0
- package/src/modules/Users/UserCreate/SiteItem/RolesModal/index.tsx +140 -0
- package/src/modules/Users/UserCreate/SiteItem/RolesModal/style.tsx +94 -0
- package/src/modules/Users/UserCreate/SiteItem/index.tsx +103 -22
- package/src/modules/Users/UserCreate/SiteItem/style.tsx +49 -6
- package/src/modules/Users/UserCreate/index.tsx +278 -121
- package/src/modules/Users/UserCreate/style.tsx +71 -4
- package/src/modules/Users/UserEdit/index.tsx +71 -24
- package/src/modules/Users/UserForm/atoms.tsx +40 -8
- package/src/modules/Users/UserForm/index.tsx +335 -116
- package/src/modules/Users/UserForm/style.tsx +70 -6
- package/src/modules/Users/UserList/BulkHeader/TableHeader/index.tsx +61 -31
- package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +18 -4
- package/src/modules/Users/UserList/BulkHeader/index.tsx +10 -3
- package/src/modules/Users/UserList/UserItem/index.tsx +121 -38
- package/src/modules/Users/UserList/UserItem/style.tsx +32 -14
- package/src/modules/Users/UserList/hooks.tsx +13 -8
- package/src/modules/Users/UserList/index.tsx +67 -29
- package/src/modules/Users/UserList/utils.tsx +1 -1
- package/src/modules/Users/index.tsx +20 -3
- package/src/routes/index.tsx +9 -17
- package/src/routes/multisite.tsx +73 -8
- package/src/routes/site.tsx +96 -10
- package/src/types/index.tsx +42 -1
- package/tsconfig.paths.json +1 -0
- package/src/__tests__/components/Avatar/__snapshots__/Avatar.test.tsx.snap +0 -61
- package/src/modules/Users/UserList/HeaderMenus/Name/index.tsx +0 -55
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
import { ISchema, ISchemaTab, ISchemaField } from "@ax/types";
|
|
4
4
|
import { Tabs } from "@ax/components";
|
|
5
|
+
import { usePermission } from "@ax/hooks";
|
|
5
6
|
|
|
6
7
|
import ConnectedField from "./ConnectedField";
|
|
7
8
|
|
|
@@ -22,6 +23,16 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
22
23
|
isEditLive,
|
|
23
24
|
} = props;
|
|
24
25
|
|
|
26
|
+
const isAllowedToEditPageContent =
|
|
27
|
+
(!isGlobal && usePermission("content.editContentPages")) ||
|
|
28
|
+
(isGlobal && usePermission("global.globalData.editAllGlobalData"));
|
|
29
|
+
const isAllowedToEditPageConfig =
|
|
30
|
+
(!isGlobal && usePermission("content.editConfigPages")) ||
|
|
31
|
+
(isGlobal && usePermission("global.globalData.editAllGlobalData"));
|
|
32
|
+
const isAllowedToEditPageSEO =
|
|
33
|
+
(!isGlobal && usePermission("seoAnalytics.editSeoAnalyticsPages")) ||
|
|
34
|
+
(isGlobal && usePermission("global.seoAnalytics.editSeoAnalyticsInGlobalPages"));
|
|
35
|
+
|
|
25
36
|
const tabContent = schema.configTabs.find((tab: ISchemaTab) => tab.title === selectedTab);
|
|
26
37
|
const setTab = (tab: string) => setSelectedTab(tab);
|
|
27
38
|
|
|
@@ -53,6 +64,7 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
53
64
|
const getTabs = () => {
|
|
54
65
|
let mappedTabs;
|
|
55
66
|
const isHeader = schema.type === "header";
|
|
67
|
+
const isPageSchema = schema.schemaType === "page";
|
|
56
68
|
if (isHeader && isPage) {
|
|
57
69
|
mappedTabs = schema.configTabs
|
|
58
70
|
.map((tab: ISchemaTab) => {
|
|
@@ -61,7 +73,18 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
61
73
|
})
|
|
62
74
|
.filter((value: string | boolean) => !!value);
|
|
63
75
|
} else {
|
|
64
|
-
mappedTabs = schema.configTabs.
|
|
76
|
+
mappedTabs = schema.configTabs.reduce((acc: string[], curr: ISchemaTab) => {
|
|
77
|
+
if (
|
|
78
|
+
!isPageSchema ||
|
|
79
|
+
(isPageSchema &&
|
|
80
|
+
((curr.title === "content" && isAllowedToEditPageContent) ||
|
|
81
|
+
(curr.title === "config" && isAllowedToEditPageConfig) ||
|
|
82
|
+
(curr.title === "SEO & Analytics" && isAllowedToEditPageSEO)))
|
|
83
|
+
) {
|
|
84
|
+
return [...acc, curr.title];
|
|
85
|
+
}
|
|
86
|
+
return acc;
|
|
87
|
+
}, []);
|
|
65
88
|
}
|
|
66
89
|
|
|
67
90
|
return mappedTabs;
|
|
@@ -2,27 +2,39 @@ import React from "react";
|
|
|
2
2
|
import { themes } from "components";
|
|
3
3
|
|
|
4
4
|
import { Icon, NoteField, Tabs } from "@ax/components";
|
|
5
|
-
import { ISchema } from "@ax/types";
|
|
5
|
+
import { INotification, ISchema } from "@ax/types";
|
|
6
|
+
import { useGlobalPermission } from "@ax/hooks";
|
|
7
|
+
|
|
6
8
|
import ConnectedField from "../Form/ConnectedField";
|
|
7
9
|
|
|
8
10
|
import * as S from "./style";
|
|
9
11
|
|
|
10
12
|
const noteText = "This is Global content and you cannot edit it here. To do so, you must go to the Global page";
|
|
11
13
|
const noteTitle = "Global content";
|
|
14
|
+
const errorText = "You don't have the permissions to edit the original content."
|
|
12
15
|
|
|
13
16
|
const GlobalPageForm = (props: IGlobalPageFormProps): JSX.Element => {
|
|
14
17
|
const { selectedTab, setSelectedTab, schema, pageTitle, setHistoryPush, actions, header, footer } = props;
|
|
15
18
|
const tabs = ["content", "config"];
|
|
16
19
|
|
|
20
|
+
const isAllowedToEditGlobalData = useGlobalPermission("global.globalData.editAllGlobalData");
|
|
21
|
+
|
|
17
22
|
const handleGetGlobalPage = async () => {
|
|
18
23
|
actions.saveCurrentSiteInfoAction();
|
|
19
24
|
await actions.getGlobalFromLocalPageAction();
|
|
20
25
|
};
|
|
21
26
|
|
|
22
27
|
const handleClick = async () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
if (isAllowedToEditGlobalData) {
|
|
29
|
+
await handleGetGlobalPage();
|
|
30
|
+
const path = "/data/pages/editor";
|
|
31
|
+
setHistoryPush && setHistoryPush(path, true);
|
|
32
|
+
} else {
|
|
33
|
+
actions.setNotificationAction({
|
|
34
|
+
type: "error",
|
|
35
|
+
text: errorText,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
const parentField = {
|
|
@@ -172,6 +184,7 @@ export interface IGlobalPageFormProps {
|
|
|
172
184
|
getGlobalFromLocalPageAction(): Promise<void>;
|
|
173
185
|
saveCurrentSiteInfoAction(): Promise<void>;
|
|
174
186
|
restorePageNavigationAction(type: string): Promise<void>;
|
|
187
|
+
setNotificationAction(notification: INotification): void;
|
|
175
188
|
};
|
|
176
189
|
}
|
|
177
190
|
|
|
@@ -21,7 +21,7 @@ const ElementsTooltip = (props: IElementsTooltipProps): JSX.Element => {
|
|
|
21
21
|
return (
|
|
22
22
|
<S.Wrapper data-testid="elements-wrapper">
|
|
23
23
|
{visibleElements.map((fullElement, idx) => {
|
|
24
|
-
const element =
|
|
24
|
+
const element = maxChar ? trimText(fullElement, maxChar) : fullElement;
|
|
25
25
|
const color = colors && colors[element] ? colors[element] : undefined;
|
|
26
26
|
|
|
27
27
|
return (
|
|
@@ -33,8 +33,8 @@ const IntegrationsField = (props: IIntegrationsFieldProps): JSX.Element => {
|
|
|
33
33
|
pagination: false,
|
|
34
34
|
filterState: "enable",
|
|
35
35
|
};
|
|
36
|
-
getIntegrations(site.id, params, true);
|
|
37
|
-
}, [getIntegrations, site
|
|
36
|
+
site && getIntegrations(site.id, params, true);
|
|
37
|
+
}, [getIntegrations, site]);
|
|
38
38
|
|
|
39
39
|
useEffect(() => {
|
|
40
40
|
onChange && state && onChange(state);
|
|
@@ -63,10 +63,9 @@ const IntegrationsField = (props: IIntegrationsFieldProps): JSX.Element => {
|
|
|
63
63
|
!state?.some((_integration: Partial<IIntegration>) => Number(_integration.id) === Number(integration.id))
|
|
64
64
|
);
|
|
65
65
|
|
|
66
|
-
const timeSinceIntegrationCopy = !!integrationCopy
|
|
66
|
+
const timeSinceIntegrationCopy = !!integrationCopy ? differenceInSeconds(new Date(), new Date(integrationCopy.date)) : null;
|
|
67
67
|
const eightHoursInSeconds = 8 * 60 * 60;
|
|
68
|
-
const showPasteIntegrationButton =
|
|
69
|
-
!disabled && !!integrationCopy && timeSinceIntegrationCopy < eightHoursInSeconds;
|
|
68
|
+
const showPasteIntegrationButton = !disabled && !!integrationCopy && timeSinceIntegrationCopy !== null && timeSinceIntegrationCopy < eightHoursInSeconds;
|
|
70
69
|
|
|
71
70
|
const pasteIntegration = () => {
|
|
72
71
|
integrationCopy && handleAdd(integrationCopy.integration);
|
|
@@ -127,7 +126,7 @@ interface IStateProps {
|
|
|
127
126
|
value: Partial<IIntegration>[];
|
|
128
127
|
onChange: (value: Partial<IIntegration>[]) => void;
|
|
129
128
|
disabled: boolean;
|
|
130
|
-
site: ISite;
|
|
129
|
+
site: ISite | null;
|
|
131
130
|
languages: ILanguage[];
|
|
132
131
|
integrationCopy: { date: Date; integration: IIntegration } | null;
|
|
133
132
|
}
|
|
@@ -186,11 +186,11 @@ const AutoPanel = (props: IProps): JSX.Element => {
|
|
|
186
186
|
<S.SourceActions>
|
|
187
187
|
{state.source && `${state.source.length} items`} {addSource}
|
|
188
188
|
</S.SourceActions>
|
|
189
|
-
{state.source &&
|
|
189
|
+
{state.source && state.source.length > 0 &&
|
|
190
190
|
state.source.map((singleSource: string) => {
|
|
191
191
|
const sourceFilters = state.filter.filter((f: any) => f.source === singleSource);
|
|
192
192
|
const source = state.sourceTitles.find((el: IDataSource) => el.id === singleSource);
|
|
193
|
-
return (
|
|
193
|
+
return source ? (
|
|
194
194
|
<AutoItem
|
|
195
195
|
key={singleSource}
|
|
196
196
|
source={source}
|
|
@@ -201,7 +201,7 @@ const AutoPanel = (props: IProps): JSX.Element => {
|
|
|
201
201
|
site={site}
|
|
202
202
|
structuredDataSite={[...structuredData.site, ...categories.site]}
|
|
203
203
|
/>
|
|
204
|
-
)
|
|
204
|
+
) : <></>;
|
|
205
205
|
})}
|
|
206
206
|
</S.SourcesWrapper>
|
|
207
207
|
<S.AllLanguagesWrapper>
|
|
@@ -24,7 +24,7 @@ const ManualPanel = (props: IProps) => {
|
|
|
24
24
|
const { state, setState } = useReference();
|
|
25
25
|
|
|
26
26
|
const [isLoading, setIsLoading] = useState(false);
|
|
27
|
-
const [selectedSource, setSelectedSource] = useState(state.sourceTitles[0]
|
|
27
|
+
const [selectedSource, setSelectedSource] = useState(state.sourceTitles[0]?.id);
|
|
28
28
|
const [selectedLang, setSelectedLang] = useState(lang.id);
|
|
29
29
|
const debouncedSearch = useDebounce(state.search);
|
|
30
30
|
|
|
@@ -58,7 +58,7 @@ const ManualPanel = (props: IProps) => {
|
|
|
58
58
|
}
|
|
59
59
|
setIsLoading(false);
|
|
60
60
|
};
|
|
61
|
-
getAndSetItems();
|
|
61
|
+
selectedSource && getAndSetItems();
|
|
62
62
|
|
|
63
63
|
return function cleanup() {
|
|
64
64
|
isMounted = false;
|
|
@@ -193,7 +193,7 @@ const ManualPanel = (props: IProps) => {
|
|
|
193
193
|
};
|
|
194
194
|
|
|
195
195
|
interface IProps {
|
|
196
|
-
currentSite: number;
|
|
196
|
+
currentSite: number | null;
|
|
197
197
|
onChange: (value: any) => void;
|
|
198
198
|
hasMaxItems: boolean;
|
|
199
199
|
handleValidation?: (value: string, validators?: Record<string, unknown>) => void;
|
|
@@ -4,7 +4,7 @@ import { Tag } from "@ax/components";
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const TagsField = (props: IProps): JSX.Element => {
|
|
7
|
-
const { value, onChange } = props;
|
|
7
|
+
const { value, onChange, disabled } = props;
|
|
8
8
|
const valueArray = value && Array.isArray(value) ? value : [];
|
|
9
9
|
const [inputValue, setInputValue] = useState("");
|
|
10
10
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
@@ -40,7 +40,7 @@ const TagsField = (props: IProps): JSX.Element => {
|
|
|
40
40
|
{valueArray &&
|
|
41
41
|
valueArray.map((tag: string, index: number) => {
|
|
42
42
|
const handleDelete = () => deleteTag(index);
|
|
43
|
-
return <Tag key={tag} text={tag} onDeleteAction={handleDelete} />;
|
|
43
|
+
return <Tag key={tag} text={tag} onDeleteAction={disabled ? undefined : handleDelete} />;
|
|
44
44
|
})}
|
|
45
45
|
<S.Input
|
|
46
46
|
data-testid="tag-field-input"
|
|
@@ -50,6 +50,7 @@ const TagsField = (props: IProps): JSX.Element => {
|
|
|
50
50
|
onChange={_handleChange}
|
|
51
51
|
placeholder={placeholder}
|
|
52
52
|
onKeyDown={_handleKeyDown}
|
|
53
|
+
disabled={disabled}
|
|
53
54
|
/>
|
|
54
55
|
</S.Wrapper>
|
|
55
56
|
);
|
|
@@ -59,6 +60,7 @@ interface IProps {
|
|
|
59
60
|
value: string[];
|
|
60
61
|
placeholder?: string;
|
|
61
62
|
onChange: (value: string[]) => void;
|
|
63
|
+
disabled?: boolean;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export default TagsField;
|
|
@@ -23,6 +23,7 @@ const TextField = (props: ITextFieldProps): JSX.Element => {
|
|
|
23
23
|
handleValidation,
|
|
24
24
|
validators,
|
|
25
25
|
editorID,
|
|
26
|
+
autoFocus,
|
|
26
27
|
inversed = false,
|
|
27
28
|
} = props;
|
|
28
29
|
|
|
@@ -98,6 +99,7 @@ const TextField = (props: ITextFieldProps): JSX.Element => {
|
|
|
98
99
|
hasPrefix={!!prefix}
|
|
99
100
|
prefixWidth={width}
|
|
100
101
|
aria-label={name}
|
|
102
|
+
autoFocus={autoFocus}
|
|
101
103
|
/>
|
|
102
104
|
{hasBackgroundIcon && (
|
|
103
105
|
<S.BackgroundIcon data-testid="background-icon-component" onClick={onClickIcon} inversed={inversed}>
|
|
@@ -132,6 +134,7 @@ interface ITextFieldProps {
|
|
|
132
134
|
handleValidation?: (value: string, validators?: Record<string, unknown>) => void;
|
|
133
135
|
validators?: Record<string, unknown>;
|
|
134
136
|
editorID?: number;
|
|
137
|
+
autoFocus?: boolean;
|
|
135
138
|
inversed?: boolean;
|
|
136
139
|
}
|
|
137
140
|
|
|
@@ -113,12 +113,12 @@ const UrlField = (props: IUrlFieldProps): JSX.Element => {
|
|
|
113
113
|
};
|
|
114
114
|
|
|
115
115
|
const validator = { format: "fullURL" };
|
|
116
|
-
const defensiveHref = value ? value.href : "";
|
|
116
|
+
const defensiveHref = value && value.href ? value.href : "";
|
|
117
117
|
|
|
118
118
|
let field = (
|
|
119
119
|
<TextField
|
|
120
120
|
{...props}
|
|
121
|
-
value={defensiveHref
|
|
121
|
+
value={defensiveHref}
|
|
122
122
|
onChange={handleChange}
|
|
123
123
|
placeholder="http://"
|
|
124
124
|
icon="urlLink"
|
|
@@ -145,14 +145,14 @@ const UrlField = (props: IUrlFieldProps): JSX.Element => {
|
|
|
145
145
|
type: "TextField" as Field,
|
|
146
146
|
name: "title",
|
|
147
147
|
title: "Title",
|
|
148
|
-
value: value ? value.title
|
|
148
|
+
value: value && value.title ? value.title : internalPageName ? internalPageName : "",
|
|
149
149
|
onChange: handleTitleChange,
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
type: "UniqueCheck" as Field,
|
|
153
153
|
name: "newTab",
|
|
154
154
|
options: [{ title: "Open in new tab" }],
|
|
155
|
-
value: value ? value.newTab : null,
|
|
155
|
+
value: value && value.newTab ? value.newTab : null,
|
|
156
156
|
onChange: handleNewTabChange,
|
|
157
157
|
},
|
|
158
158
|
{
|
|
@@ -225,7 +225,7 @@ const UrlField = (props: IUrlFieldProps): JSX.Element => {
|
|
|
225
225
|
};
|
|
226
226
|
|
|
227
227
|
export interface IUrlFieldProps {
|
|
228
|
-
value
|
|
228
|
+
value?: IUrlField | null;
|
|
229
229
|
title: string;
|
|
230
230
|
onChange: (value: IUrlField | null) => void;
|
|
231
231
|
showAdvanced: boolean;
|
|
@@ -3,6 +3,7 @@ import { connect } from "react-redux";
|
|
|
3
3
|
import { IImage, IRootState, IImageForm } from "@ax/types";
|
|
4
4
|
import { Button, CheckField, FieldsBehavior, Toast, IconAction } from "@ax/components";
|
|
5
5
|
import { formatBytes, getFileExtension, getFormattedDateWithTimezone } from "@ax/helpers";
|
|
6
|
+
import { usePermission } from "@ax/hooks";
|
|
6
7
|
|
|
7
8
|
import { galleryActions } from "@ax/containers/Gallery";
|
|
8
9
|
import { IIsSaving } from "@ax/containers/Gallery/reducer";
|
|
@@ -34,6 +35,14 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
34
35
|
const [addToGlobal, setAddToGlobal] = useState({ value: "addToGlobal", isChecked: false });
|
|
35
36
|
const [deletedToast, setDeletedToast] = useState(false);
|
|
36
37
|
|
|
38
|
+
const isAllowedToDelete =
|
|
39
|
+
(isGlobalTab && usePermission("mediaGallery.deleteGlobalImagesInSite")) ||
|
|
40
|
+
(!isGlobalTab && usePermission("mediaGallery.deleteImages"));
|
|
41
|
+
const isAllowedToEdit =
|
|
42
|
+
(isGlobalTab && usePermission("mediaGallery.editGlobalImagesInSite")) ||
|
|
43
|
+
(!isGlobalTab && usePermission("mediaGallery.editImages"));
|
|
44
|
+
const isAllowedToUploadGlobal = usePermission("mediaGallery.addGlobalImagesFromSite");
|
|
45
|
+
|
|
37
46
|
const setInitForm = (imageSelected: IImage) => {
|
|
38
47
|
const form = {
|
|
39
48
|
id: imageSelected.id,
|
|
@@ -89,7 +98,13 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
89
98
|
const handleSaveAndAdd = async () => {
|
|
90
99
|
if (imageForm.id) {
|
|
91
100
|
await updateImage(imageForm.id, imageForm, true);
|
|
92
|
-
handleSetAsGlobal();
|
|
101
|
+
await handleSetAsGlobal();
|
|
102
|
+
setImage(imageForm);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handleAdd = async () => {
|
|
107
|
+
if (imageForm.id) {
|
|
93
108
|
setImage(imageForm);
|
|
94
109
|
}
|
|
95
110
|
};
|
|
@@ -134,7 +149,7 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
134
149
|
</S.AddToGlobal>
|
|
135
150
|
);
|
|
136
151
|
|
|
137
|
-
const canSetAsGlobal = !isGlobalTab && imageSelected?.file;
|
|
152
|
+
const canSetAsGlobal = !isGlobalTab && imageSelected?.file && isAllowedToUploadGlobal;
|
|
138
153
|
|
|
139
154
|
const renderImageForm = !imageSelected ? null : (
|
|
140
155
|
<S.PanelForm>
|
|
@@ -170,6 +185,7 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
170
185
|
value={imageForm.title}
|
|
171
186
|
fieldType="TextField"
|
|
172
187
|
onChange={handleTitle}
|
|
188
|
+
disabled={!isAllowedToEdit}
|
|
173
189
|
/>
|
|
174
190
|
<FieldsBehavior
|
|
175
191
|
title="Alternative text"
|
|
@@ -177,6 +193,7 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
177
193
|
value={imageForm.alt}
|
|
178
194
|
fieldType="TextField"
|
|
179
195
|
onChange={handleAlt}
|
|
196
|
+
disabled={!isAllowedToEdit}
|
|
180
197
|
/>
|
|
181
198
|
<FieldsBehavior
|
|
182
199
|
title="Description"
|
|
@@ -184,8 +201,9 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
184
201
|
value={imageForm.description}
|
|
185
202
|
fieldType="TextArea"
|
|
186
203
|
onChange={handleDescription}
|
|
204
|
+
disabled={!isAllowedToEdit}
|
|
187
205
|
/>
|
|
188
|
-
<FieldsBehavior title="Tags" value={imageForm.tags} fieldType="TagsField" onChange={handleTags} />
|
|
206
|
+
<FieldsBehavior title="Tags" value={imageForm.tags} fieldType="TagsField" onChange={handleTags} disabled={!isAllowedToEdit} />
|
|
189
207
|
</S.FormWrapper>
|
|
190
208
|
</S.PanelForm>
|
|
191
209
|
);
|
|
@@ -194,29 +212,38 @@ const GalleryDetailPanel = (props: IProps) => {
|
|
|
194
212
|
<S.DetailPanelWrapper data-testid="detail-panel-wrapper" hidden={!isImageSelected}>
|
|
195
213
|
{renderImageForm}
|
|
196
214
|
<S.PanelActions>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
215
|
+
{isAllowedToDelete && (
|
|
216
|
+
<Button
|
|
217
|
+
type="button"
|
|
218
|
+
buttonStyle="text"
|
|
219
|
+
onClick={handleDelete}
|
|
220
|
+
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
221
|
+
>
|
|
222
|
+
{isSaving.delete ? `Deleting` : `Delete`}
|
|
223
|
+
</Button>
|
|
224
|
+
)}
|
|
225
|
+
{isAllowedToEdit && <Button
|
|
206
226
|
type="button"
|
|
207
227
|
buttonStyle="line"
|
|
208
228
|
onClick={handleSave}
|
|
209
229
|
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
210
230
|
>
|
|
211
231
|
{isSaving.save ? `Saving` : `Save`}
|
|
212
|
-
</Button>
|
|
213
|
-
<Button
|
|
232
|
+
</Button>}
|
|
233
|
+
{isAllowedToEdit && <Button
|
|
214
234
|
type="button"
|
|
215
235
|
onClick={handleSaveAndAdd}
|
|
216
236
|
disabled={isSaving.save || isSaving.saveAdd || isSaving.delete}
|
|
217
237
|
>
|
|
218
238
|
{isSaving.saveAdd ? `Saving` : `Save & Add`}
|
|
219
|
-
</Button>
|
|
239
|
+
</Button>}
|
|
240
|
+
{!isAllowedToEdit && <Button
|
|
241
|
+
type="button"
|
|
242
|
+
onClick={handleAdd}
|
|
243
|
+
disabled={isSaving.delete}
|
|
244
|
+
>
|
|
245
|
+
Add
|
|
246
|
+
</Button>}
|
|
220
247
|
</S.PanelActions>
|
|
221
248
|
{deletedToast && <Toast message="1 image deleted" setIsVisible={setDeletedToast} />}
|
|
222
249
|
</S.DetailPanelWrapper>
|
|
@@ -188,7 +188,7 @@ const GalleryDragAndDrop = (props: IProps) => {
|
|
|
188
188
|
export interface IGalleryDragAndDropProps {
|
|
189
189
|
isImageSelected: boolean;
|
|
190
190
|
validFormats: string[];
|
|
191
|
-
site: number |
|
|
191
|
+
site: number | "global";
|
|
192
192
|
allowUpload: boolean;
|
|
193
193
|
refreshImages: () => Promise<void>;
|
|
194
194
|
isUploading: boolean;
|
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
import React, { memo } from "react";
|
|
2
2
|
|
|
3
|
-
import { IImage } from "@ax/types";
|
|
3
|
+
import { IImage, ISite } from "@ax/types";
|
|
4
|
+
import { usePermission } from "@ax/hooks";
|
|
4
5
|
|
|
5
6
|
import GalleryDragAndDrop from "./GalleryDragAndDrop";
|
|
6
7
|
import DetailPanel from "./DetailPanel";
|
|
7
8
|
import * as S from "./style";
|
|
8
9
|
|
|
9
10
|
const GalleryPanel = (props: IGalleryPanelProps) => {
|
|
10
|
-
const {
|
|
11
|
-
|
|
11
|
+
const {
|
|
12
|
+
imageSelected,
|
|
13
|
+
validFormats,
|
|
14
|
+
setImage,
|
|
15
|
+
isGlobalTab,
|
|
16
|
+
scope,
|
|
17
|
+
selectedTab,
|
|
18
|
+
site,
|
|
19
|
+
refreshImages,
|
|
20
|
+
selectImage
|
|
21
|
+
} = props;
|
|
22
|
+
|
|
23
|
+
const isAllowedToUpload = usePermission("mediaGallery.addImages");
|
|
24
|
+
|
|
25
|
+
const allowUpload = (site && (!isGlobalTab || !selectedTab) && isAllowedToUpload) || (!site && isAllowedToUpload);
|
|
12
26
|
|
|
13
27
|
return (
|
|
14
28
|
<S.GalleryPanel>
|
|
15
29
|
<GalleryDragAndDrop
|
|
16
30
|
isImageSelected={!!imageSelected}
|
|
17
31
|
validFormats={validFormats}
|
|
18
|
-
site={
|
|
32
|
+
site={scope}
|
|
19
33
|
allowUpload={allowUpload}
|
|
20
34
|
refreshImages={refreshImages}
|
|
21
35
|
selectImage={selectImage}
|
|
@@ -37,9 +51,10 @@ export interface IGalleryPanelProps {
|
|
|
37
51
|
validFormats: string[];
|
|
38
52
|
setImage: (imageData: any) => void;
|
|
39
53
|
isGlobalTab: boolean;
|
|
40
|
-
|
|
54
|
+
scope: number | "global";
|
|
41
55
|
selectedTab: string;
|
|
42
56
|
refreshImages: () => Promise<void>;
|
|
57
|
+
site: ISite | null;
|
|
43
58
|
selectImage(item: IImage | null): void;
|
|
44
59
|
}
|
|
45
60
|
|
|
@@ -5,6 +5,7 @@ import { galleryActions } from "@ax/containers/Gallery";
|
|
|
5
5
|
import { IData, IIsLoading } from "@ax/containers/Gallery/reducer";
|
|
6
6
|
import { IGetSiteImages, IImage, IRootState, ISite } from "@ax/types";
|
|
7
7
|
import { Icon, Loader, Tabs, SearchField, EmptyState, ErrorToast, Notification } from "@ax/components";
|
|
8
|
+
import { usePermission } from "@ax/hooks";
|
|
8
9
|
|
|
9
10
|
import Orientation from "./GalleryFilters/Orientation";
|
|
10
11
|
import SortBy from "./GalleryFilters/SortBy";
|
|
@@ -21,13 +22,17 @@ const firstPage = 1;
|
|
|
21
22
|
const Gallery = (props: IProps): JSX.Element => {
|
|
22
23
|
const { data, isLoading, getSiteImages, getImageSelected, toggleModal, site, uploadError } = props;
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const [
|
|
25
|
+
const isAllowedToAccessGlobalImages = usePermission("mediaGallery.accessToGlobalGalleryFromSite");
|
|
26
|
+
|
|
27
|
+
const tabs: string[] = [];
|
|
28
|
+
if (site && isAllowedToAccessGlobalImages) {
|
|
29
|
+
tabs.unshift(...["Local", "Global"]);
|
|
30
|
+
}
|
|
31
|
+
const [selectedTab, setSelectedTab] = useState(site ? "Local" : "Global");
|
|
27
32
|
const [selectedImage, setSelectedImage] = useState<IImage | null>(null);
|
|
28
33
|
const isLocalTab = selectedTab === "Local";
|
|
29
34
|
const isGlobalTab = selectedTab === "Global";
|
|
30
|
-
const galleryScope = isLocalTab ? site.id : "global";
|
|
35
|
+
const galleryScope = isLocalTab && site ? site.id : "global";
|
|
31
36
|
|
|
32
37
|
const validFormats = ["jpeg", "jpg", "png", "svg", "gif"];
|
|
33
38
|
|
|
@@ -213,9 +218,10 @@ const Gallery = (props: IProps): JSX.Element => {
|
|
|
213
218
|
validFormats={validFormats}
|
|
214
219
|
setImage={setImage}
|
|
215
220
|
isGlobalTab={!isLocalTab}
|
|
216
|
-
|
|
221
|
+
scope={galleryScope}
|
|
217
222
|
selectedTab={selectedTab}
|
|
218
223
|
refreshImages={refreshImages}
|
|
224
|
+
site={site}
|
|
219
225
|
selectImage={setSelectedImage}
|
|
220
226
|
/>
|
|
221
227
|
</S.Wrapper>
|
|
@@ -225,7 +231,7 @@ const Gallery = (props: IProps): JSX.Element => {
|
|
|
225
231
|
export interface IGalleryProps {
|
|
226
232
|
getImageSelected: (img: IImage | null) => void;
|
|
227
233
|
toggleModal: () => void;
|
|
228
|
-
site: ISite;
|
|
234
|
+
site: ISite | null;
|
|
229
235
|
data: IData;
|
|
230
236
|
isLoading: IIsLoading;
|
|
231
237
|
}
|
|
@@ -23,7 +23,15 @@ const Icon = (props: IProps) => {
|
|
|
23
23
|
const Svg = getImage(name);
|
|
24
24
|
|
|
25
25
|
if (Svg) {
|
|
26
|
-
return
|
|
26
|
+
return (
|
|
27
|
+
<Svg
|
|
28
|
+
data-testid={`icon-component-${name.toLowerCase()}`}
|
|
29
|
+
height={size}
|
|
30
|
+
width={size}
|
|
31
|
+
viewBox="0 0 24 24"
|
|
32
|
+
fill={fill}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
return null;
|
|
@@ -32,7 +32,7 @@ const ActionMenu = (props: any) => {
|
|
|
32
32
|
const { menu } = props;
|
|
33
33
|
return (
|
|
34
34
|
menu &&
|
|
35
|
-
menu.options && (
|
|
35
|
+
menu.options.length > 0 && (
|
|
36
36
|
<S.ActionMenu>
|
|
37
37
|
<S.ActionMenuTitle> More actions </S.ActionMenuTitle>
|
|
38
38
|
<ActionMenuBtn menu={menu} />
|
|
@@ -52,7 +52,7 @@ const ActionSimpleMenu = (props: any) => {
|
|
|
52
52
|
const { menu } = props;
|
|
53
53
|
return (
|
|
54
54
|
menu &&
|
|
55
|
-
menu.options && (
|
|
55
|
+
menu.options.length > 0 && (
|
|
56
56
|
<S.ActionMenu data-testid="action-simple-menu">
|
|
57
57
|
{menu.options.map((item: any, i: number) => ActionMenuItem(item, true))}
|
|
58
58
|
</S.ActionMenu>
|
|
@@ -142,14 +142,16 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
142
142
|
options: pageStatusActions,
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
-
const PageStatus = () =>
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
const PageStatus = () => {
|
|
146
|
+
const offset = rightButton || rightLineButton ? -20 : -135;
|
|
147
|
+
return statusMenu.options && statusMenu.options.length > 0 ? (
|
|
148
|
+
<FloatingMenu Button={StatusBtn} isInAppBar={true} position="left" offset={offset}>
|
|
148
149
|
<ActionSimpleMenu menu={statusMenu} />
|
|
149
150
|
</FloatingMenu>
|
|
150
151
|
) : (
|
|
151
152
|
<Icon name={pageStatus ?? "offline"} size="24" />
|
|
152
153
|
);
|
|
154
|
+
}
|
|
153
155
|
|
|
154
156
|
const languageTooltip = typeof currentPageID === "number" && "Add language";
|
|
155
157
|
|
|
@@ -195,34 +197,34 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
195
197
|
closeOnInactive
|
|
196
198
|
/>
|
|
197
199
|
</S.SearchWrapper>
|
|
198
|
-
<S.Separator />
|
|
200
|
+
{(language || pageStatus || rightButton || rightLineButton) && <S.Separator />}
|
|
199
201
|
</>
|
|
200
202
|
)}
|
|
201
203
|
{language && (
|
|
202
204
|
<>
|
|
203
205
|
<S.LanguageWrapper data-testid="language-wrapper">
|
|
204
206
|
<Tooltip content={languageTooltip} hideOnClick bottom>
|
|
205
|
-
<FloatingMenu Button={LanguageBtn} isInAppBar={true} position="left">
|
|
207
|
+
<FloatingMenu Button={LanguageBtn} isInAppBar={true} position="left" offset={rightButton || rightLineButton ? 0 : -85}>
|
|
206
208
|
{languageMenu}
|
|
207
209
|
</FloatingMenu>
|
|
208
210
|
</Tooltip>
|
|
209
211
|
</S.LanguageWrapper>
|
|
210
|
-
<S.Separator />
|
|
212
|
+
{(pageStatus || rightButton || rightLineButton ) && <S.Separator />}
|
|
211
213
|
</>
|
|
212
214
|
)}
|
|
213
215
|
{pageStatus && (
|
|
214
216
|
<>
|
|
215
|
-
<S.IconStatusWrapper data-testid="page-status-wrapper">
|
|
217
|
+
<S.IconStatusWrapper data-testid="page-status-wrapper" last={!rightButton && !rightLineButton}>
|
|
216
218
|
<Tooltip content={publishedTooltip[pageStatus]} bottom>
|
|
217
219
|
<PageStatus />
|
|
218
220
|
</Tooltip>
|
|
219
221
|
</S.IconStatusWrapper>
|
|
220
|
-
<S.Separator />
|
|
222
|
+
{(rightButton || rightLineButton ) && <S.Separator />}
|
|
221
223
|
</>
|
|
222
224
|
)}
|
|
223
225
|
{isFromEditor && errors && errors.length > 0 && (
|
|
224
226
|
<>
|
|
225
|
-
<S.IconStatusWrapper data-testid="error-center-wrapper">
|
|
227
|
+
<S.IconStatusWrapper last={false} data-testid="error-center-wrapper">
|
|
226
228
|
<FloatingMenu Button={ErrorCenterBtn} isInAppBar={true} position="left" offset={-20}>
|
|
227
229
|
<ErrorCenter errors={errors} actions={errorActions} />
|
|
228
230
|
</FloatingMenu>
|
|
@@ -246,7 +248,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
246
248
|
{rightButton.label}
|
|
247
249
|
</Button>
|
|
248
250
|
)}
|
|
249
|
-
{downArrowMenu && downArrowMenu.displayed && (
|
|
251
|
+
{downArrowMenu && downArrowMenu.displayed && (downArrowMenu.button || downArrowMenu.options.length > 0) && (
|
|
250
252
|
<Tooltip content="Actions" hideOnClick bottom>
|
|
251
253
|
<FloatingMenu Button={DownArrowButton} isInAppBar={true}>
|
|
252
254
|
<ActionMenu menu={downArrowMenu} />
|