@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.
- package/.changelog.draft +1 -5
- package/CHANGELOG.md +226 -0
- package/README.md +6 -5
- package/locales/de/LC_MESSAGES/volto.po +171 -38
- package/locales/en/LC_MESSAGES/volto.po +170 -37
- package/locales/es/LC_MESSAGES/volto.po +171 -38
- package/locales/eu/LC_MESSAGES/volto.po +171 -38
- package/locales/pt_BR/volto.po +171 -38
- package/locales/volto.pot +171 -38
- package/package.json +15 -6
- package/src/components/Blocks/EventMetadata/View.jsx +32 -26
- package/src/components/Blocks/Listing/DefaultTemplate.jsx +19 -14
- package/src/components/Blocks/Listing/GridTemplate.jsx +9 -12
- package/src/components/Blocks/Listing/SummaryTemplate.jsx +9 -7
- package/src/components/Blocks/Teaser/DefaultBody.jsx +93 -0
- package/src/components/Blocks/Teaser/schema.js +1 -7
- package/src/components/Footer/ColumnLinks.tsx +35 -0
- package/src/components/Footer/Footer.tsx +32 -0
- package/src/components/Footer/slots/Colophon.tsx +24 -0
- package/src/components/Footer/slots/Copyright.tsx +65 -0
- package/src/components/Footer/slots/CoreFooter.tsx +82 -0
- package/src/components/Footer/slots/FollowUsLogoAndLinks.tsx +80 -0
- package/src/components/Footer/slots/FooterLogos.tsx +44 -0
- package/src/components/Header/Header.tsx +257 -0
- package/src/components/Logo/Logo.tsx +85 -0
- package/src/components/{Footer/FooterLogos.tsx → LogosContainer/LogosContainer.tsx} +24 -25
- package/src/components/MobileNavigation/MobileNavigation.jsx +53 -18
- package/src/components/Navigation/Navigation.jsx +14 -3
- package/src/components/SearchWidget/IntranetSearchWidget.jsx +32 -5
- package/src/components/SearchWidget/SearchWidget.jsx +1 -1
- package/src/components/StickyMenu/StickyMenu.tsx +36 -0
- package/src/components/Summary/DefaultSummary.jsx +16 -0
- package/src/components/Summary/EventSummary.jsx +38 -0
- package/src/components/Summary/FileSummary.jsx +24 -0
- package/src/components/Summary/NewsItemSummary.jsx +40 -0
- package/src/components/Tags/Tags.jsx +46 -0
- package/src/components/Theme/EventView.jsx +19 -25
- package/src/components/Theme/NewsItemView.jsx +13 -9
- package/src/components/Theming/Theming.tsx +20 -17
- package/src/components/Widgets/{BlockAlignmentWidget.tsx → BlockAlignment.tsx} +9 -2
- package/src/components/Widgets/{BlockWidthWidget.tsx → BlockWidth.tsx} +10 -3
- package/src/components/Widgets/BlocksObject.tsx +353 -0
- package/src/components/Widgets/Buttons.tsx +117 -0
- package/src/components/Widgets/ColorContrastChecker.tsx +117 -0
- package/src/components/Widgets/ColorPicker.tsx +59 -0
- package/src/components/Widgets/{ColorPickerWidget.tsx → ColorSwatch.tsx} +5 -5
- package/src/components/Widgets/ObjectList.tsx +342 -0
- package/src/components/Widgets/{ThemingColorPicker.tsx → RACThemingColorPicker.tsx} +4 -0
- package/src/components/Widgets/Size.tsx +75 -0
- package/src/components/Widgets/ThemeColorSwatch.tsx +17 -0
- package/src/components/Widgets/schema/footerLinksSchema.ts +64 -0
- package/src/components/Widgets/schema/footerLogosSchema.ts +98 -0
- package/src/components/Widgets/schema/headerActionsSchema.ts +64 -0
- package/src/components/Widgets/schema/iconLinkListSchema.ts +98 -0
- package/src/config/blocks.tsx +39 -20
- package/src/config/settings.ts +54 -12
- package/src/config/slots.ts +36 -1
- package/src/config/summary.ts +24 -0
- package/src/config/widgets.ts +57 -20
- package/src/customizations/volto/components/manage/Blocks/Teaser/DefaultBody.jsx +8 -0
- package/src/customizations/volto/components/theme/Tags/Tags.jsx +11 -0
- package/src/customizations/volto/components/theme/View/RenderBlocks.jsx +2 -1
- package/src/helpers/DndSortableList.tsx +138 -0
- package/src/helpers/dates.js +22 -0
- package/src/helpers/doesNodeContainClick.js +64 -0
- package/src/helpers/useLiveData.ts +29 -0
- package/src/index.ts +33 -2
- package/src/primitives/IconLinkList.tsx +69 -0
- package/src/primitives/LinkList.tsx +35 -0
- package/src/theme/_bgcolor-blocks-layout.scss +50 -12
- package/src/theme/_container.scss +4 -0
- package/src/theme/_content.scss +6 -0
- package/src/theme/_footer.scss +295 -43
- package/src/theme/_header.scss +132 -19
- package/src/theme/_layout.scss +11 -1
- package/src/theme/_sitemap.scss +4 -0
- package/src/theme/_utils.scss +14 -1
- package/src/theme/_variables.scss +12 -3
- package/src/theme/_widgets.scss +102 -10
- package/src/theme/blocks/_eventMetadata.scss +5 -2
- package/src/theme/blocks/_grid.scss +3 -3
- package/src/theme/blocks/_highlight.scss +17 -44
- package/src/theme/blocks/_listing.scss +25 -16
- package/src/theme/blocks/_maps.scss +3 -3
- package/src/theme/blocks/_slider.scss +5 -1
- package/src/theme/main.scss +1 -0
- package/src/theme/sticky-menu.scss +50 -0
- package/src/types.d.ts +102 -0
- package/tsconfig.json +1 -1
- package/src/components/Footer/Footer.jsx +0 -115
- package/src/components/Footer/FooterLinks.tsx +0 -57
- package/src/components/Header/Header.jsx +0 -161
- package/src/components/Logo/Logo.jsx +0 -51
- package/src/components/Widgets/AlignWidget.jsx +0 -80
- package/src/components/Widgets/BackgroundColorWidget.tsx +0 -17
- package/src/components/Widgets/BlocksObjectWidget.tsx +0 -333
- package/src/components/Widgets/ButtonsWidget.tsx +0 -68
- package/src/components/Widgets/FooterLinksWidget.tsx +0 -106
- package/src/components/Widgets/FooterLogosWidget.tsx +0 -120
- package/src/static/container-query-polyfill.modern.js +0 -1
- 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
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
20
|
-
const
|
|
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
|
|
27
|
-
<ul
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
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={
|
|
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
|
|
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
|
|
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
|
-
|
|
83
|
-
<div className="search-
|
|
84
|
-
<div className="search">
|
|
85
|
-
<
|
|
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
|
-
|
|
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
|
-
|
|
222
|
-
<div className="search-
|
|
223
|
-
<div className="search">
|
|
224
|
-
<
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
{
|
|
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
|
-
|
|
86
|
-
|
|
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={
|
|
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(
|
|
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
|
|
11
|
+
import doesNodeContainClick from '../../helpers/doesNodeContainClick';
|
|
12
12
|
|
|
13
13
|
const messages = defineMessages({
|
|
14
14
|
search: {
|