@kitconcept/volto-light-theme 6.0.0-alpha.8 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/.changelog.draft +1 -5
  2. package/CHANGELOG.md +226 -0
  3. package/README.md +6 -5
  4. package/locales/de/LC_MESSAGES/volto.po +171 -38
  5. package/locales/en/LC_MESSAGES/volto.po +170 -37
  6. package/locales/es/LC_MESSAGES/volto.po +171 -38
  7. package/locales/eu/LC_MESSAGES/volto.po +171 -38
  8. package/locales/pt_BR/volto.po +171 -38
  9. package/locales/volto.pot +171 -38
  10. package/package.json +15 -6
  11. package/src/components/Blocks/EventMetadata/View.jsx +32 -26
  12. package/src/components/Blocks/Listing/DefaultTemplate.jsx +19 -14
  13. package/src/components/Blocks/Listing/GridTemplate.jsx +9 -12
  14. package/src/components/Blocks/Listing/SummaryTemplate.jsx +9 -7
  15. package/src/components/Blocks/Teaser/DefaultBody.jsx +93 -0
  16. package/src/components/Blocks/Teaser/schema.js +1 -7
  17. package/src/components/Footer/ColumnLinks.tsx +35 -0
  18. package/src/components/Footer/Footer.tsx +32 -0
  19. package/src/components/Footer/slots/Colophon.tsx +24 -0
  20. package/src/components/Footer/slots/Copyright.tsx +65 -0
  21. package/src/components/Footer/slots/CoreFooter.tsx +82 -0
  22. package/src/components/Footer/slots/FollowUsLogoAndLinks.tsx +80 -0
  23. package/src/components/Footer/slots/FooterLogos.tsx +44 -0
  24. package/src/components/Header/Header.tsx +257 -0
  25. package/src/components/Logo/Logo.tsx +85 -0
  26. package/src/components/{Footer/FooterLogos.tsx → LogosContainer/LogosContainer.tsx} +24 -25
  27. package/src/components/MobileNavigation/MobileNavigation.jsx +53 -18
  28. package/src/components/Navigation/Navigation.jsx +14 -3
  29. package/src/components/SearchWidget/IntranetSearchWidget.jsx +32 -5
  30. package/src/components/SearchWidget/SearchWidget.jsx +1 -1
  31. package/src/components/StickyMenu/StickyMenu.tsx +36 -0
  32. package/src/components/Summary/DefaultSummary.jsx +16 -0
  33. package/src/components/Summary/EventSummary.jsx +38 -0
  34. package/src/components/Summary/FileSummary.jsx +24 -0
  35. package/src/components/Summary/NewsItemSummary.jsx +40 -0
  36. package/src/components/Tags/Tags.jsx +46 -0
  37. package/src/components/Theme/EventView.jsx +19 -25
  38. package/src/components/Theme/NewsItemView.jsx +13 -9
  39. package/src/components/Theming/Theming.tsx +20 -17
  40. package/src/components/Widgets/{BlockAlignmentWidget.tsx → BlockAlignment.tsx} +9 -2
  41. package/src/components/Widgets/{BlockWidthWidget.tsx → BlockWidth.tsx} +10 -3
  42. package/src/components/Widgets/BlocksObject.tsx +353 -0
  43. package/src/components/Widgets/Buttons.tsx +117 -0
  44. package/src/components/Widgets/ColorContrastChecker.tsx +117 -0
  45. package/src/components/Widgets/ColorPicker.tsx +59 -0
  46. package/src/components/Widgets/{ColorPickerWidget.tsx → ColorSwatch.tsx} +5 -5
  47. package/src/components/Widgets/ObjectList.tsx +342 -0
  48. package/src/components/Widgets/{ThemingColorPicker.tsx → RACThemingColorPicker.tsx} +4 -0
  49. package/src/components/Widgets/Size.tsx +75 -0
  50. package/src/components/Widgets/ThemeColorSwatch.tsx +17 -0
  51. package/src/components/Widgets/schema/footerLinksSchema.ts +64 -0
  52. package/src/components/Widgets/schema/footerLogosSchema.ts +98 -0
  53. package/src/components/Widgets/schema/headerActionsSchema.ts +64 -0
  54. package/src/components/Widgets/schema/iconLinkListSchema.ts +98 -0
  55. package/src/config/blocks.tsx +39 -20
  56. package/src/config/settings.ts +54 -12
  57. package/src/config/slots.ts +36 -1
  58. package/src/config/summary.ts +24 -0
  59. package/src/config/widgets.ts +57 -20
  60. package/src/customizations/volto/components/manage/Blocks/Teaser/DefaultBody.jsx +8 -0
  61. package/src/customizations/volto/components/theme/Tags/Tags.jsx +11 -0
  62. package/src/customizations/volto/components/theme/View/RenderBlocks.jsx +2 -1
  63. package/src/helpers/DndSortableList.tsx +138 -0
  64. package/src/helpers/dates.js +22 -0
  65. package/src/helpers/doesNodeContainClick.js +64 -0
  66. package/src/helpers/useLiveData.ts +29 -0
  67. package/src/index.ts +33 -2
  68. package/src/primitives/IconLinkList.tsx +69 -0
  69. package/src/primitives/LinkList.tsx +35 -0
  70. package/src/theme/_bgcolor-blocks-layout.scss +50 -12
  71. package/src/theme/_container.scss +4 -0
  72. package/src/theme/_content.scss +6 -0
  73. package/src/theme/_footer.scss +295 -43
  74. package/src/theme/_header.scss +132 -19
  75. package/src/theme/_layout.scss +11 -1
  76. package/src/theme/_sitemap.scss +4 -0
  77. package/src/theme/_utils.scss +14 -1
  78. package/src/theme/_variables.scss +12 -3
  79. package/src/theme/_widgets.scss +102 -10
  80. package/src/theme/blocks/_eventMetadata.scss +5 -2
  81. package/src/theme/blocks/_grid.scss +3 -3
  82. package/src/theme/blocks/_highlight.scss +17 -44
  83. package/src/theme/blocks/_listing.scss +25 -16
  84. package/src/theme/blocks/_maps.scss +3 -3
  85. package/src/theme/blocks/_slider.scss +5 -1
  86. package/src/theme/main.scss +1 -0
  87. package/src/theme/sticky-menu.scss +50 -0
  88. package/src/types.d.ts +102 -0
  89. package/tsconfig.json +1 -1
  90. package/src/components/Footer/Footer.jsx +0 -115
  91. package/src/components/Footer/FooterLinks.tsx +0 -57
  92. package/src/components/Header/Header.jsx +0 -161
  93. package/src/components/Logo/Logo.jsx +0 -51
  94. package/src/components/Widgets/AlignWidget.jsx +0 -80
  95. package/src/components/Widgets/BackgroundColorWidget.tsx +0 -17
  96. package/src/components/Widgets/BlocksObjectWidget.tsx +0 -333
  97. package/src/components/Widgets/ButtonsWidget.tsx +0 -68
  98. package/src/components/Widgets/FooterLinksWidget.tsx +0 -106
  99. package/src/components/Widgets/FooterLogosWidget.tsx +0 -120
  100. package/src/static/container-query-polyfill.modern.js +0 -1
  101. package/src/types/index.d.ts +0 -1
@@ -0,0 +1,257 @@
1
+ // SemanticUI-free pre-@plone/components
2
+ import { useEffect, useState } from 'react';
3
+ import { useSelector, useDispatch, shallowEqual } from 'react-redux';
4
+ import { Button, Container } from '@plone/components';
5
+ import isEmpty from 'lodash/isEmpty';
6
+ import cx from 'classnames';
7
+
8
+ import {
9
+ setSidebarTab,
10
+ setMetadataFocus,
11
+ } from '@plone/volto/actions/sidebar/sidebar';
12
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
13
+ import LanguageSelector from '@plone/volto/components/theme/LanguageSelector/LanguageSelector';
14
+ import Logo from '@plone/volto/components/theme/Logo/Logo';
15
+ import Navigation from '@plone/volto/components/theme/Navigation/Navigation';
16
+ import SearchWidget from '@plone/volto/components/theme/SearchWidget/SearchWidget';
17
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
18
+ import SlotRenderer from '@plone/volto/components/theme/SlotRenderer/SlotRenderer';
19
+
20
+ import { useLiveData } from '@kitconcept/volto-light-theme/helpers/useLiveData';
21
+
22
+ import MobileNavigation from '../MobileNavigation/MobileNavigation';
23
+ import IntranetSearchWidget from '../SearchWidget/IntranetSearchWidget';
24
+
25
+ import type { SiteHeaderSettings } from '../../types';
26
+ import type { Content } from '@plone/types';
27
+
28
+ type FormState = {
29
+ content: {
30
+ data: Content;
31
+ };
32
+ navroot: {
33
+ data: {
34
+ navroot: Content;
35
+ };
36
+ };
37
+ form: {
38
+ global: Content;
39
+ };
40
+ };
41
+
42
+ const InternetHeader = ({ pathname, content }) => {
43
+ const [isClient, setIsClient] = useState(false);
44
+ useEffect(() => {
45
+ setIsClient(true);
46
+ }, []);
47
+
48
+ const dispatch = useDispatch();
49
+
50
+ const formData = useSelector<FormState, Content>(
51
+ (state) => state.form.global,
52
+ );
53
+
54
+ const intranet_flag = useLiveData<SiteHeaderSettings['intranet_flag']>(
55
+ content,
56
+ 'voltolighttheme.header',
57
+ 'intranet_flag',
58
+ );
59
+
60
+ const header_actions = useLiveData<SiteHeaderSettings['header_actions']>(
61
+ content,
62
+ 'voltolighttheme.header',
63
+ 'header_actions',
64
+ );
65
+
66
+ const pointToSidebar = (fieldSetName, fieldId) => {
67
+ dispatch(setSidebarTab(0));
68
+ dispatch(setMetadataFocus(fieldSetName, fieldId));
69
+ };
70
+
71
+ return (
72
+ <>
73
+ <div className="header">
74
+ <div className="tools-wrapper">
75
+ <LanguageSelector />
76
+
77
+ <div className="tools">
78
+ {header_actions &&
79
+ Array.isArray(header_actions) &&
80
+ header_actions.map((item) => (
81
+ <UniversalLink
82
+ key={item['@id']}
83
+ href={item.href?.[0]['@id']}
84
+ openLinkInNewTab={item.openInNewTab}
85
+ >
86
+ {item.title}
87
+ </UniversalLink>
88
+ ))}
89
+ </div>
90
+ {intranet_flag &&
91
+ isClient &&
92
+ (!isEmpty(formData) ? (
93
+ <Button
94
+ className="intranet-flag"
95
+ onPress={() =>
96
+ pointToSidebar('header customizations', 'intranet_flag')
97
+ }
98
+ >
99
+ <p>{intranet_flag}</p>
100
+ </Button>
101
+ ) : (
102
+ <div className="intranet-flag">
103
+ <p>{intranet_flag}</p>
104
+ </div>
105
+ ))}
106
+ </div>
107
+ <div className="logo-nav-wrapper">
108
+ <div className="logo">
109
+ <Logo />
110
+ </div>
111
+ <Navigation pathname={pathname} />
112
+ <MobileNavigation pathname={pathname} />
113
+ <div className="search-wrapper navigation-desktop">
114
+ <div className="search">
115
+ <SearchWidget />
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </>
121
+ );
122
+ };
123
+
124
+ const IntranetHeader = ({ pathname, content }) => {
125
+ const [isClient, setIsClient] = useState(false);
126
+ useEffect(() => {
127
+ setIsClient(true);
128
+ }, []);
129
+
130
+ const dispatch = useDispatch();
131
+
132
+ const formData = useSelector<FormState, Content>(
133
+ (state) => state.form.global,
134
+ );
135
+
136
+ const intranet_flag = useLiveData<SiteHeaderSettings['intranet_flag']>(
137
+ content,
138
+ 'voltolighttheme.header',
139
+ 'intranet_flag',
140
+ );
141
+
142
+ const complementary_logo = useLiveData<
143
+ SiteHeaderSettings['complementary_logo']
144
+ >(content, 'voltolighttheme.header', 'complementary_logo');
145
+
146
+ const complementaryLogoSrc = complementary_logo?.data
147
+ ? `data:${complementary_logo['content-type']};base64,${complementary_logo.data}`
148
+ : flattenToAppURL(complementary_logo?.download);
149
+
150
+ const header_actions = useLiveData<SiteHeaderSettings['header_actions']>(
151
+ content,
152
+ 'voltolighttheme.header',
153
+ 'header_actions',
154
+ );
155
+
156
+ const pointToSidebar = (fieldSetName, fieldId) => {
157
+ dispatch(setSidebarTab(0));
158
+ dispatch(setMetadataFocus(fieldSetName, fieldId));
159
+ };
160
+
161
+ return (
162
+ <>
163
+ <div className="header">
164
+ <div className="tools-wrapper">
165
+ <LanguageSelector />
166
+
167
+ <div className="tools">
168
+ <SlotRenderer name="headerTools" content={content} />
169
+
170
+ {header_actions &&
171
+ Array.isArray(header_actions) &&
172
+ header_actions.map((item) => (
173
+ <UniversalLink
174
+ key={item['@id']}
175
+ href={item.href?.[0]['@id']}
176
+ openLinkInNewTab={item.openInNewTab}
177
+ >
178
+ {item.title}
179
+ </UniversalLink>
180
+ ))}
181
+ </div>
182
+ {intranet_flag &&
183
+ isClient &&
184
+ (!isEmpty(formData) ? (
185
+ <Button
186
+ className="intranet-flag"
187
+ onPress={() =>
188
+ pointToSidebar('header customizations', 'intranet_flag')
189
+ }
190
+ >
191
+ <p>{intranet_flag}</p>
192
+ </Button>
193
+ ) : (
194
+ <div className="intranet-flag">
195
+ <p>{intranet_flag}</p>
196
+ </div>
197
+ ))}
198
+ </div>
199
+ <div className="logo-nav-wrapper">
200
+ <div className="logo">
201
+ <Logo />
202
+ </div>
203
+ <div className="search-wrapper">
204
+ <div className="search">
205
+ <IntranetSearchWidget />
206
+ </div>
207
+ </div>
208
+ <MobileNavigation pathname={pathname} />
209
+ <div className="complementary-logo">
210
+ {complementary_logo && (
211
+ <img src={complementaryLogoSrc} alt="complementary logo" />
212
+ )}
213
+ </div>
214
+ </div>
215
+ <Navigation pathname={pathname} />
216
+ </div>
217
+ </>
218
+ );
219
+ };
220
+
221
+ const Header = (props) => {
222
+ const { pathname } = props;
223
+ const content = useSelector<FormState, Content>(
224
+ (state) => state.content.data,
225
+ shallowEqual,
226
+ );
227
+
228
+ const navRoot = useSelector<FormState, Content>(
229
+ (state) => state.navroot?.data?.navroot,
230
+ );
231
+
232
+ const has_intranet_header = useLiveData<
233
+ SiteHeaderSettings['has_intranet_header']
234
+ >(content, 'voltolighttheme.header', 'has_intranet_header');
235
+
236
+ return (
237
+ <>
238
+ <SlotRenderer name="aboveHeader" content={content} navRoot={navRoot} />
239
+ <header
240
+ className={cx('header-wrapper', {
241
+ 'intranet-header': has_intranet_header,
242
+ })}
243
+ >
244
+ <Container layout>
245
+ {has_intranet_header ? (
246
+ <IntranetHeader pathname={pathname} content={content} />
247
+ ) : (
248
+ <InternetHeader pathname={pathname} content={content} />
249
+ )}
250
+ </Container>
251
+ </header>
252
+ <SlotRenderer name="belowHeader" content={content} navRoot={navRoot} />
253
+ </>
254
+ );
255
+ };
256
+
257
+ export default Header;
@@ -0,0 +1,85 @@
1
+ // SemanticUI-free pre-@plone/components
2
+ import { defineMessages, useIntl } from 'react-intl';
3
+ import { useSelector, shallowEqual } from 'react-redux';
4
+ import { Link } from 'react-router-dom';
5
+ import LogoImage from '@plone/volto/components/theme/Logo/Logo.svg';
6
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
7
+ import { useLiveData } from '@kitconcept/volto-light-theme/helpers/useLiveData';
8
+ import type { SiteHeaderSettings } from '../../types';
9
+ import type { Content } from '@plone/types';
10
+
11
+ const messages = defineMessages({
12
+ home: {
13
+ id: 'Home',
14
+ defaultMessage: 'Home',
15
+ },
16
+ logoOf: {
17
+ id: 'Logo of',
18
+ defaultMessage: 'Logo of',
19
+ },
20
+ });
21
+
22
+ type FormState = {
23
+ content: {
24
+ data: Content;
25
+ };
26
+ navroot: {
27
+ data: {
28
+ navroot: Content;
29
+ };
30
+ };
31
+ site: {
32
+ data: Content['@components']['site'];
33
+ };
34
+ form: {
35
+ global: Content;
36
+ };
37
+ };
38
+
39
+ const Logo = () => {
40
+ const intl = useIntl();
41
+ const site = useSelector<FormState, Content>((state) => state.site.data);
42
+ const navroot = useSelector<FormState, Content>(
43
+ (state) => state.navroot.data,
44
+ );
45
+ const navRootPath = flattenToAppURL(navroot?.navroot?.['@id']) || '/';
46
+
47
+ const content = useSelector<FormState, Content>(
48
+ (state) => state.content.data,
49
+ shallowEqual,
50
+ );
51
+
52
+ const logo = useLiveData<SiteHeaderSettings['logo']>(
53
+ content,
54
+ 'voltolighttheme.header',
55
+ 'logo',
56
+ );
57
+
58
+ const logoSrc = logo?.data
59
+ ? `data:${logo['content-type']};base64,${logo.data}`
60
+ : flattenToAppURL(logo?.download);
61
+
62
+ const logoWidth = logo?.width || null;
63
+ const logoHeight = logo?.height || null;
64
+
65
+ return (
66
+ <Link to={navRootPath} aria-label={intl.formatMessage(messages.home)}>
67
+ <img
68
+ src={
69
+ logoSrc
70
+ ? logoSrc
71
+ : site['plone.site_logo']
72
+ ? flattenToAppURL(site['plone.site_logo'])
73
+ : LogoImage
74
+ }
75
+ width={logoWidth}
76
+ height={logoHeight}
77
+ alt={
78
+ intl.formatMessage(messages.logoOf) + ' ' + site['plone.site_title']
79
+ }
80
+ />
81
+ </Link>
82
+ );
83
+ };
84
+
85
+ export default Logo;
@@ -1,33 +1,27 @@
1
- import type { Content } from '@plone/types';
2
- import isEmpty from 'lodash/isEmpty';
3
1
  import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
4
2
  import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
5
- import { useSelector } from 'react-redux';
6
3
  import { Container } from '@plone/components';
4
+ import cx from 'classnames';
5
+ import type { SiteFooterSettings } from '../../types';
7
6
 
8
- type FormState = {
9
- content: {
10
- data: Content;
11
- };
12
- navroot: {
13
- data: {
14
- navroot: Content;
15
- };
16
- };
7
+ type LogosContainerProps = {
8
+ logos: SiteFooterSettings['footer_logos'];
9
+ logos_size: SiteFooterSettings['footer_logos_size'];
10
+ logos_container_width: SiteFooterSettings['footer_logos_container_width'];
17
11
  };
18
12
 
19
- const FooterLogos = () => {
20
- const navroot = useSelector<FormState, Content>(
21
- (state) => state.navroot.data.navroot,
22
- );
23
- const logos = navroot?.footer_logos;
13
+ const LogosContainer = (props: LogosContainerProps) => {
14
+ const { logos, logos_size, logos_container_width } = props;
24
15
 
25
16
  return (
26
- <Container layout>
27
- <ul className="footer-logos">
28
- {!isEmpty(logos?.blocks)
29
- ? logos.blocks_layout.items.map((itemId) => {
30
- const logo = logos.blocks[itemId];
17
+ <Container className={cx({ [logos_container_width]: 1 })}>
18
+ <ul
19
+ className={cx('logos-container', {
20
+ [logos_size]: logos_size,
21
+ })}
22
+ >
23
+ {logos && Array.isArray(logos)
24
+ ? logos.map((logo) => {
31
25
  const logoInfo: {
32
26
  hrefTitle: string;
33
27
  href: string;
@@ -41,7 +35,7 @@ const FooterLogos = () => {
41
35
  src: '',
42
36
  srcAlt: '',
43
37
  };
44
- if (logo?.href) {
38
+ if (logo?.href?.length > 0) {
45
39
  logoInfo.hrefTitle = logo.href[0]['title'];
46
40
  logoInfo.href = flattenToAppURL(logo.href[0]['@id']);
47
41
  }
@@ -49,17 +43,22 @@ const FooterLogos = () => {
49
43
  logoInfo.logoHref = logo.logo[0]['@id'];
50
44
  logoInfo.srcAlt = logo['alt'];
51
45
  logoInfo.src = `${flattenToAppURL(logoInfo.logoHref)}/${logo.logo[0].image_scales[logo.logo[0].image_field][0].download}`;
46
+ } else if (logo?.logo && logo.logo[0]) {
47
+ logoInfo.logoHref = logo.logo[0]['@id'];
48
+ logoInfo.srcAlt = logo['alt'];
49
+ logoInfo.src = `${flattenToAppURL(logoInfo.logoHref)}/@@images/image`;
52
50
  }
53
51
 
54
52
  if (!logoInfo.src) return null;
55
53
 
56
54
  return (
57
- <li className="item" key={logoInfo.href}>
55
+ <li className="item" key={logo['@id']}>
58
56
  {/* @ts-ignore */}
59
57
  <ConditionalLink
60
58
  condition={logoInfo.href}
61
59
  to={logoInfo.href}
62
60
  title={logoInfo.hrefTitle || logoInfo.srcAlt}
61
+ openLinkInNewTab={logo.openInNewTab}
63
62
  >
64
63
  <img src={logoInfo.src} alt={logoInfo.srcAlt} />
65
64
  </ConditionalLink>
@@ -72,4 +71,4 @@ const FooterLogos = () => {
72
71
  );
73
72
  };
74
73
 
75
- export default FooterLogos;
74
+ export default LogosContainer;
@@ -4,8 +4,8 @@ import { useSelector } from 'react-redux';
4
4
  import { Link, useHistory } from 'react-router-dom';
5
5
  import cx from 'classnames';
6
6
  import { CSSTransition } from 'react-transition-group';
7
- import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
8
-
7
+ import doesNodeContainClick from '../../helpers/doesNodeContainClick';
8
+ import isEmpty from 'lodash/isEmpty';
9
9
  import config from '@plone/volto/registry';
10
10
  import Icon from '@plone/volto/components/theme/Icon/Icon';
11
11
  import SearchWidget from '@plone/volto/components/theme/SearchWidget/SearchWidget';
@@ -61,6 +61,17 @@ const MenuItem = ({
61
61
  }
62
62
  }, [resetToRoot]);
63
63
 
64
+ const headerSettings = useSelector(
65
+ (state) =>
66
+ state.content.data?.['@components']?.inherit?.['voltolighttheme.header']
67
+ ?.data,
68
+ );
69
+ const formData = useSelector((state) => state.form.global);
70
+
71
+ const has_intranet_header = !isEmpty(formData)
72
+ ? formData.has_intranet_header
73
+ : headerSettings?.has_intranet_header;
74
+
64
75
  return (
65
76
  <li className={section.url === pathname ? 'current' : ''}>
66
77
  <Link
@@ -79,19 +90,31 @@ const MenuItem = ({
79
90
  unmountOnExit
80
91
  >
81
92
  <div className="menu-drawer subsection">
82
- <div className="search-header">
83
- <div className="search-wrapper">
84
- <div className="search">
85
- <SearchWidget />
93
+ {!has_intranet_header ? (
94
+ <div className="search-header">
95
+ <div className="search-wrapper">
96
+ <div className="search">
97
+ <SearchWidget />
98
+ </div>
86
99
  </div>
100
+
101
+ <button onClick={closeSubMenu}>
102
+ <Icon name={arrowLeftSVG} size="60px" />
103
+ <span>
104
+ <FormattedMessage {...messages.back} />
105
+ </span>
106
+ </button>
107
+ </div>
108
+ ) : (
109
+ <div>
110
+ <button onClick={closeSubMenu}>
111
+ <Icon name={arrowLeftSVG} size="60px" />
112
+ <span>
113
+ <FormattedMessage {...messages.back} />
114
+ </span>
115
+ </button>
87
116
  </div>
88
- <button onClick={closeSubMenu}>
89
- <Icon name={arrowLeftSVG} size="60px" />
90
- <span>
91
- <FormattedMessage {...messages.back} />
92
- </span>
93
- </button>
94
- </div>
117
+ )}
95
118
  <ul className="sections">
96
119
  <li className="header">{section.nav_title || section.title}</li>
97
120
  <li>
@@ -132,6 +155,16 @@ const MobileNavigation = (props) => {
132
155
  const items = useSelector((state) => state.navigation.items || []);
133
156
  const history = useHistory();
134
157
 
158
+ const headerSettings = useSelector(
159
+ (state) =>
160
+ state.content.data?.['@components']?.inherit?.['voltolighttheme.header']
161
+ ?.data,
162
+ );
163
+ const formData = useSelector((state) => state.form.global);
164
+ const has_intranet_header = !isEmpty(formData)
165
+ ? formData.has_intranet_header
166
+ : headerSettings?.has_intranet_header;
167
+
135
168
  const Footer = props.MobileToolsFooter || MobileToolsFooter;
136
169
 
137
170
  const toggleMobileMenu = useCallback(() => {
@@ -218,13 +251,15 @@ const MobileNavigation = (props) => {
218
251
  classNames="menu-drawer"
219
252
  >
220
253
  <div className="menu-drawer">
221
- <div className="search-header">
222
- <div className="search-wrapper">
223
- <div className="search">
224
- <SearchWidget />
254
+ {!has_intranet_header && (
255
+ <div className="search-header">
256
+ <div className="search-wrapper">
257
+ <div className="search">
258
+ <SearchWidget />
259
+ </div>
225
260
  </div>
226
261
  </div>
227
- </div>
262
+ )}
228
263
  <ul className="sections">
229
264
  <li className="header">
230
265
  <Link
@@ -2,9 +2,10 @@
2
2
 
3
3
  import React, { useState, useEffect, useRef } from 'react';
4
4
  import PropTypes from 'prop-types';
5
+ import isEmpty from 'lodash/isEmpty';
5
6
  import { useDispatch, useSelector, shallowEqual } from 'react-redux';
6
7
  import { NavLink } from 'react-router-dom';
7
- import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
8
+ import doesNodeContainClick from '../../helpers/doesNodeContainClick';
8
9
  import { useIntl, defineMessages, injectIntl } from 'react-intl';
9
10
  import cx from 'classnames';
10
11
  import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
@@ -33,7 +34,17 @@ const Navigation = ({ pathname }) => {
33
34
  const navigation = useRef(null);
34
35
  const dispatch = useDispatch();
35
36
  const intl = useIntl();
36
- const enableFatMenu = config.settings.enableFatMenu;
37
+ const headerSettings = useSelector(
38
+ (state) =>
39
+ state.content.data?.['@components']?.inherit?.['voltolighttheme.header']
40
+ ?.data,
41
+ );
42
+ const formData = useSelector((state) => state.form.global);
43
+
44
+ const has_fat_menu =
45
+ !isEmpty(formData) && formData?.has_fat_menu
46
+ ? formData.has_fat_menu
47
+ : headerSettings?.has_fat_menu;
37
48
 
38
49
  const lang = useSelector((state) => state.intl.locale);
39
50
  const token = useSelector((state) => state.userSession.token, shallowEqual);
@@ -102,7 +113,7 @@ const Navigation = ({ pathname }) => {
102
113
  <ul className="desktop-menu">
103
114
  {items.map((item, index) => (
104
115
  <li key={item.url}>
105
- {enableFatMenu ? (
116
+ {has_fat_menu ? (
106
117
  <>
107
118
  <button
108
119
  onClick={() => openMenu(index)}
@@ -9,6 +9,7 @@ import { Form, Input } from 'semantic-ui-react';
9
9
  import { compose } from 'redux';
10
10
  import { PropTypes } from 'prop-types';
11
11
  import { defineMessages, injectIntl } from 'react-intl';
12
+ import { connect } from 'react-redux';
12
13
 
13
14
  import Icon from '@plone/volto/components/theme/Icon/Icon';
14
15
  import zoomSVG from '@plone/volto/icons/zoom.svg';
@@ -78,13 +79,24 @@ class IntranetSearchWidget extends Component {
78
79
  * @returns {undefined}
79
80
  */
80
81
  onSubmit(event) {
82
+ const searchURL =
83
+ this.props.site['kitconcept.intranet.external_search_url'];
81
84
  const path =
82
85
  this.props.pathname?.length > 0
83
86
  ? `&path=${encodeURIComponent(this.props.pathname)}`
84
87
  : '';
85
- this.props.history.push(
86
- `/search?SearchableText=${encodeURIComponent(this.state.text)}${path}`,
87
- );
88
+
89
+ if (searchURL) {
90
+ window.open(
91
+ `${searchURL}?SearchableText=${encodeURIComponent(this.state.text)}${path}`,
92
+ '_blank',
93
+ 'noopener,noreferrer',
94
+ );
95
+ } else {
96
+ this.props.history.push(
97
+ `/search?SearchableText=${encodeURIComponent(this.state.text)}${path}`,
98
+ );
99
+ }
88
100
  // reset input value
89
101
  this.setState({
90
102
  text: '',
@@ -99,6 +111,8 @@ class IntranetSearchWidget extends Component {
99
111
  */
100
112
  render() {
101
113
  const { intl } = this.props;
114
+ const searchFieldPlaceholder =
115
+ this.props.site['kitconcept.intranet.search_field_placeholder'];
102
116
  return (
103
117
  <Form action="/search" onSubmit={this.onSubmit}>
104
118
  <Form.Field className="searchbox">
@@ -109,7 +123,14 @@ class IntranetSearchWidget extends Component {
109
123
  value={this.state.text}
110
124
  transparent
111
125
  autoComplete="off"
112
- placeholder={intl.formatMessage(messages.placeholder)}
126
+ placeholder={
127
+ searchFieldPlaceholder
128
+ ? intl.formatMessage({
129
+ id: searchFieldPlaceholder,
130
+ defaultMessage: searchFieldPlaceholder,
131
+ })
132
+ : intl.formatMessage(messages.placeholder)
133
+ }
113
134
  title={intl.formatMessage(messages.search)}
114
135
  />
115
136
  <button aria-label={intl.formatMessage(messages.search)}>
@@ -121,4 +142,10 @@ class IntranetSearchWidget extends Component {
121
142
  }
122
143
  }
123
144
 
124
- export default compose(withRouter, injectIntl)(IntranetSearchWidget);
145
+ export default compose(
146
+ withRouter,
147
+ injectIntl,
148
+ connect((state, props) => ({
149
+ site: state.site.data,
150
+ })),
151
+ )(IntranetSearchWidget);
@@ -8,7 +8,7 @@ import { defineMessages, injectIntl } from 'react-intl';
8
8
 
9
9
  import Icon from '@plone/volto/components/theme/Icon/Icon';
10
10
  import zoomSVG from '@plone/volto/icons/zoom.svg';
11
- import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
11
+ import doesNodeContainClick from '../../helpers/doesNodeContainClick';
12
12
 
13
13
  const messages = defineMessages({
14
14
  search: {