@ndla/ui 3.3.8 → 3.3.13
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/es/Article/Article.js +23 -1
- package/es/Article/ArticleNotions.js +80 -32
- package/es/Breadcrumblist/Breadcrumblist.js +14 -10
- package/es/CloseButton/CloseButton.js +62 -0
- package/es/CloseButton/index.js +9 -0
- package/es/Frontpage/FrontpageAllSubjects.js +7 -7
- package/es/Frontpage/FrontpageProgramMenu.js +10 -10
- package/es/Frontpage/FrontpageSearch.js +2 -4
- package/es/MediaList/MediaList.js +22 -73
- package/es/MessageBox/MessageBox.js +146 -78
- package/es/MessageBox/MessageBoxTag.js +37 -0
- package/es/MessageBox/index.js +3 -1
- package/es/NDLAFilm/FilmSlideshow.js +2 -1
- package/es/NDLAFilm/shapes.js +10 -0
- package/es/Programme/Programme.js +15 -8
- package/es/Search/SearchResultSleeve.js +12 -15
- package/es/SearchTypeResult/SearchFieldHeader.js +5 -5
- package/es/SearchTypeResult/SearchHeader.js +9 -9
- package/es/SearchTypeResult/SearchItem.js +19 -19
- package/es/SearchTypeResult/SearchNotionItem.js +12 -12
- package/es/SearchTypeResult/SearchNotionsResult.js +9 -14
- package/es/index.js +2 -1
- package/es/locale/messages-en.js +10 -0
- package/es/locale/messages-nb.js +10 -0
- package/es/locale/messages-nn.js +10 -0
- package/lib/Article/Article.d.ts +3 -1
- package/lib/Article/Article.js +25 -3
- package/lib/Article/ArticleNotions.js +79 -30
- package/lib/Breadcrumblist/Breadcrumblist.d.ts +2 -1
- package/lib/Breadcrumblist/Breadcrumblist.js +15 -10
- package/lib/CloseButton/CloseButton.d.ts +6 -0
- package/lib/CloseButton/CloseButton.js +69 -0
- package/lib/CloseButton/index.d.ts +9 -0
- package/lib/CloseButton/index.js +15 -0
- package/lib/Frontpage/FrontpageAllSubjects.d.ts +1 -1
- package/lib/Frontpage/FrontpageAllSubjects.js +7 -7
- package/lib/Frontpage/FrontpageProgramMenu.js +10 -10
- package/lib/Frontpage/FrontpageSearch.d.ts +3 -5
- package/lib/Frontpage/FrontpageSearch.js +2 -4
- package/lib/MediaList/MediaList.d.ts +48 -0
- package/lib/MediaList/MediaList.js +24 -78
- package/lib/MediaList/index.d.ts +8 -0
- package/lib/MessageBox/MessageBox.d.ts +22 -6
- package/lib/MessageBox/MessageBox.js +146 -77
- package/lib/MessageBox/MessageBoxTag.d.ts +12 -0
- package/lib/MessageBox/MessageBoxTag.js +44 -0
- package/lib/MessageBox/index.d.ts +3 -1
- package/lib/MessageBox/index.js +22 -2
- package/lib/NDLAFilm/shapes.d.ts +10 -0
- package/lib/NDLAFilm/shapes.js +14 -1
- package/lib/Programme/Programme.d.ts +2 -1
- package/lib/Programme/Programme.js +18 -9
- package/lib/Search/SearchResultSleeve.d.ts +4 -6
- package/lib/Search/SearchResultSleeve.js +10 -11
- package/lib/SearchTypeResult/SearchFieldHeader.d.ts +3 -3
- package/lib/SearchTypeResult/SearchFieldHeader.js +5 -5
- package/lib/SearchTypeResult/SearchHeader.d.ts +3 -3
- package/lib/SearchTypeResult/SearchHeader.js +9 -9
- package/lib/SearchTypeResult/SearchItem.d.ts +2 -3
- package/lib/SearchTypeResult/SearchItem.js +19 -19
- package/lib/SearchTypeResult/SearchNotionItem.d.ts +1 -1
- package/lib/SearchTypeResult/SearchNotionItem.js +12 -12
- package/lib/SearchTypeResult/SearchNotionsResult.js +8 -13
- package/lib/SearchTypeResult/index.d.ts +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +23 -0
- package/lib/locale/messages-en.d.ts +10 -0
- package/lib/locale/messages-en.js +10 -0
- package/lib/locale/messages-nb.d.ts +10 -0
- package/lib/locale/messages-nb.js +10 -0
- package/lib/locale/messages-nn.d.ts +10 -0
- package/lib/locale/messages-nn.js +10 -0
- package/lib/types.d.ts +2 -2
- package/package.json +9 -9
- package/src/Article/Article.tsx +17 -0
- package/src/Article/ArticleNotions.tsx +10 -7
- package/src/Breadcrumblist/Breadcrumblist.tsx +5 -3
- package/src/CloseButton/CloseButton.tsx +40 -0
- package/src/CloseButton/index.ts +11 -0
- package/src/Frontpage/FrontpageAllSubjects.tsx +2 -2
- package/src/Frontpage/FrontpageProgramMenu.tsx +1 -0
- package/src/Frontpage/FrontpageSearch.tsx +3 -7
- package/src/MediaList/MediaList.tsx +158 -0
- package/src/MediaList/{index.js → index.ts} +0 -0
- package/src/MessageBox/MessageBox.tsx +117 -96
- package/src/MessageBox/MessageBoxTag.tsx +35 -0
- package/src/MessageBox/index.ts +3 -1
- package/src/NDLAFilm/FilmSlideshow.tsx +1 -0
- package/src/NDLAFilm/shapes.ts +11 -0
- package/src/Programme/Programme.tsx +7 -3
- package/src/Search/SearchResultSleeve.tsx +7 -19
- package/src/SearchTypeResult/SearchFieldHeader.tsx +3 -3
- package/src/SearchTypeResult/SearchHeader.tsx +3 -3
- package/src/SearchTypeResult/SearchItem.tsx +4 -5
- package/src/SearchTypeResult/SearchNotionItem.tsx +1 -2
- package/src/SearchTypeResult/SearchNotionsResult.tsx +3 -8
- package/src/SearchTypeResult/index.ts +2 -0
- package/src/index.ts +2 -1
- package/src/locale/messages-en.ts +14 -0
- package/src/locale/messages-nb.ts +14 -0
- package/src/locale/messages-nn.ts +14 -0
- package/src/types.ts +2 -2
- package/src/MediaList/MediaList.jsx +0 -182
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2016-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { ReactNode } from 'react';
|
|
10
|
+
import {
|
|
11
|
+
LicenseDescription,
|
|
12
|
+
getLicenseByAbbreviation,
|
|
13
|
+
getResourceTypeNamespace,
|
|
14
|
+
isCreativeCommonsLicense,
|
|
15
|
+
metaTypes,
|
|
16
|
+
} from '@ndla/licenses';
|
|
17
|
+
import BEMHelper from 'react-bem-helper';
|
|
18
|
+
import { uuid } from '@ndla/util';
|
|
19
|
+
|
|
20
|
+
const oClasses = new BEMHelper({
|
|
21
|
+
name: 'media',
|
|
22
|
+
prefix: 'o-',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const cClasses = new BEMHelper({
|
|
26
|
+
name: 'medialist',
|
|
27
|
+
prefix: 'c-',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
interface MediaListProps {
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const MediaList = ({ children }: MediaListProps) => <ul {...cClasses()}>{children}</ul>;
|
|
35
|
+
|
|
36
|
+
interface MediaListItemProps {
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export const MediaListItem = ({ children }: MediaListItemProps) => (
|
|
40
|
+
<li {...oClasses(undefined, undefined, cClasses('item').className)}>{children}</li>
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
interface MediaListItemImageProps {
|
|
44
|
+
children: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
export const MediaListItemImage = ({ children }: MediaListItemImageProps) => (
|
|
47
|
+
<div {...oClasses('img', undefined, cClasses('img').className)}>
|
|
48
|
+
<div>{children}</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
interface MediaListCCLinkProps {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
url: string;
|
|
55
|
+
}
|
|
56
|
+
export const MediaListCCLink = ({ children, url }: MediaListCCLinkProps) => (
|
|
57
|
+
<a className="c-figure-license__link" target="_blank" rel="noopener noreferrer license" href={url}>
|
|
58
|
+
{children}
|
|
59
|
+
</a>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
interface MediaListItemBodyProps {
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
license: string;
|
|
65
|
+
locale: string;
|
|
66
|
+
resourceUrl?: string;
|
|
67
|
+
resourceType?: 'video' | 'image' | 'audio' | 'text' | 'h5p';
|
|
68
|
+
messages?: {
|
|
69
|
+
modelPremission?: string;
|
|
70
|
+
};
|
|
71
|
+
title?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const MediaListItemBody = ({
|
|
75
|
+
children,
|
|
76
|
+
license: licenseAbbreviation,
|
|
77
|
+
messages,
|
|
78
|
+
title,
|
|
79
|
+
locale,
|
|
80
|
+
resourceUrl = '', // defaults to current page
|
|
81
|
+
resourceType,
|
|
82
|
+
}: MediaListItemBodyProps) => {
|
|
83
|
+
const license = getLicenseByAbbreviation(licenseAbbreviation, locale);
|
|
84
|
+
const containerProps = isCreativeCommonsLicense(license.rights)
|
|
85
|
+
? {
|
|
86
|
+
...oClasses('body', undefined, cClasses('body').className),
|
|
87
|
+
'xmlns:cc': 'https://creativecommons.org/ns#',
|
|
88
|
+
'xmlns:dct': 'http://purl.org/dc/terms/',
|
|
89
|
+
about: resourceUrl,
|
|
90
|
+
}
|
|
91
|
+
: {
|
|
92
|
+
...oClasses('body', undefined, cClasses('body').className),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const metaResourceType = getResourceTypeNamespace(resourceType);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div {...containerProps}>
|
|
99
|
+
{/* @ts-ignore */}
|
|
100
|
+
{metaResourceType && <span rel="dct:type" href={metaResourceType} style={{ display: 'none' }} />}
|
|
101
|
+
{title ? <h3 className="c-medialist__title">{title} </h3> : null}
|
|
102
|
+
<LicenseDescription locale={locale} messages={messages} licenseRights={license.rights} highlightCC />
|
|
103
|
+
<MediaListCCLink url={license.url}>{license.linkText}</MediaListCCLink>
|
|
104
|
+
{children}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
interface MediaListItemActionsProps {
|
|
110
|
+
children: ReactNode;
|
|
111
|
+
}
|
|
112
|
+
export const MediaListItemActions = ({ children }: MediaListItemActionsProps) => (
|
|
113
|
+
<div {...cClasses('actions')}>{children}</div>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const isLink = (text: string) => text.startsWith('http') || text.startsWith('https');
|
|
117
|
+
|
|
118
|
+
interface HandleLinkProps {
|
|
119
|
+
text: string;
|
|
120
|
+
children: ReactNode;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const HandleLink = ({ text, children }: HandleLinkProps) => {
|
|
124
|
+
if (isLink(text)) {
|
|
125
|
+
return (
|
|
126
|
+
<a href={text} target="_blank" rel="noopener noreferrer">
|
|
127
|
+
{children}
|
|
128
|
+
</a>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return <span>{children}</span>;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const attributionTypes = [metaTypes.author, metaTypes.copyrightHolder, metaTypes.contributor];
|
|
135
|
+
|
|
136
|
+
interface MediaListItemMetaProps {
|
|
137
|
+
items?: {
|
|
138
|
+
label: string;
|
|
139
|
+
description: string;
|
|
140
|
+
metaType: string;
|
|
141
|
+
}[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const MediaListItemMeta = ({ items = [] }: MediaListItemMetaProps) => {
|
|
145
|
+
const attributionItems = items.filter((item) => attributionTypes.some((type) => type === item.metaType));
|
|
146
|
+
const attributionMeta = attributionItems.map((item) => `${item.label}: ${item.description}`).join(', ');
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
//@ts-ignore
|
|
150
|
+
<ul {...cClasses('actions')} property="cc:attributionName" content={attributionMeta}>
|
|
151
|
+
{items.map((item) => (
|
|
152
|
+
<li key={uuid()} className="c-medialist__meta-item">
|
|
153
|
+
{item.label}: <HandleLink text={item.description}>{item.description}</HandleLink>
|
|
154
|
+
</li>
|
|
155
|
+
))}
|
|
156
|
+
</ul>
|
|
157
|
+
);
|
|
158
|
+
};
|
|
File without changes
|
|
@@ -1,63 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useState } from 'react';
|
|
2
10
|
import styled from '@emotion/styled';
|
|
3
11
|
import Sticky from 'react-sticky-el';
|
|
4
12
|
import { breakpoints, fonts, mq, spacing } from '@ndla/core';
|
|
5
|
-
|
|
6
|
-
import Button from '@ndla/button';
|
|
7
|
-
import { Cross } from '@ndla/icons/action';
|
|
8
|
-
import { InformationOutline } from '@ndla/icons/common';
|
|
13
|
+
import { InformationOutline, HumanMaleBoard } from '@ndla/icons/common';
|
|
9
14
|
import { WithTranslation, withTranslation } from 'react-i18next';
|
|
15
|
+
import { CloseButton } from '../CloseButton';
|
|
10
16
|
|
|
17
|
+
export enum MessageBoxType {
|
|
18
|
+
ghost = 'ghost',
|
|
19
|
+
fullpage = 'fullpage',
|
|
20
|
+
medium = 'medium',
|
|
21
|
+
}
|
|
11
22
|
type WrapperProps = {
|
|
12
|
-
boxType?:
|
|
23
|
+
boxType?: MessageBoxType;
|
|
13
24
|
};
|
|
14
25
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
26
|
+
const StyleByType = (type: WrapperProps['boxType']) => {
|
|
27
|
+
const styles = {
|
|
28
|
+
margin: '1px',
|
|
29
|
+
color: '#444444',
|
|
30
|
+
backgroundColor: '#f9f4c8',
|
|
31
|
+
border: 'none',
|
|
32
|
+
display: 'flex',
|
|
33
|
+
width: 'auto',
|
|
34
|
+
position: 'relative',
|
|
35
|
+
transform: 'auto',
|
|
36
|
+
left: 'auto',
|
|
37
|
+
}; //Different CSS properties for different types of message-boxes
|
|
20
38
|
switch (type) {
|
|
21
|
-
case '
|
|
22
|
-
|
|
39
|
+
case 'fullpage':
|
|
40
|
+
styles.margin = '0 auto';
|
|
41
|
+
styles.display = 'none';
|
|
42
|
+
styles.width = '100vw';
|
|
43
|
+
styles.position = 'relative';
|
|
44
|
+
styles.left = '50%';
|
|
45
|
+
styles.transform = 'translateX(-50%)';
|
|
46
|
+
break;
|
|
47
|
+
case 'medium':
|
|
48
|
+
styles.margin = '0px';
|
|
49
|
+
break;
|
|
50
|
+
case 'ghost':
|
|
51
|
+
styles.backgroundColor = 'transparent';
|
|
52
|
+
styles.border = '1px solid #D1D6DB';
|
|
53
|
+
styles.color = '#444444';
|
|
54
|
+
|
|
23
55
|
break;
|
|
24
56
|
}
|
|
25
|
-
return
|
|
57
|
+
return styles;
|
|
26
58
|
};
|
|
27
59
|
|
|
28
60
|
const Wrapper = styled.div<WrapperProps>`
|
|
29
|
-
background: ${(props) =>
|
|
30
|
-
color: ${(props) =>
|
|
61
|
+
background: ${(props) => StyleByType(props.boxType).backgroundColor};
|
|
62
|
+
color: ${(props) => StyleByType(props.boxType).color};
|
|
31
63
|
font-size: 18px;
|
|
32
64
|
line-height: 32px;
|
|
33
|
-
|
|
65
|
+
font-family: ${fonts.sans};
|
|
34
66
|
display: flex;
|
|
35
67
|
padding: ${spacing.small};
|
|
36
|
-
position:
|
|
68
|
+
position: ${(props) => StyleByType(props.boxType).position};
|
|
69
|
+
border: ${(props) => StyleByType(props.boxType).border};
|
|
70
|
+
border-radius: 5px;
|
|
71
|
+
transform: ${(props) => StyleByType(props.boxType).transform};
|
|
72
|
+
left: ${(props) => StyleByType(props.boxType).left};
|
|
73
|
+
z-index: 10;
|
|
74
|
+
width: ${(props) => StyleByType(props.boxType).width};
|
|
37
75
|
`;
|
|
38
76
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
margin-right: ${spacing.small};
|
|
43
|
-
${mq.range({ until: breakpoints.tabletWide })} {
|
|
44
|
-
font-size: 18px;
|
|
45
|
-
font-weight: ${fonts.weight.semibold};
|
|
46
|
-
}
|
|
47
|
-
`;
|
|
48
|
-
|
|
49
|
-
const InfoWrapper = styled.div`
|
|
50
|
-
margin: 0 auto;
|
|
51
|
-
padding: 0 100px;
|
|
77
|
+
const InfoWrapper = styled.div<WrapperProps>`
|
|
78
|
+
margin: ${(props) => StyleByType(props.boxType).margin};
|
|
79
|
+
padding: 10px;
|
|
52
80
|
display: flex;
|
|
53
81
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
54
82
|
padding: 0 90px 0 0;
|
|
55
83
|
}
|
|
56
84
|
${mq.range({ until: breakpoints.mobileWide })} {
|
|
57
|
-
padding: 0
|
|
85
|
+
padding: 0 5px 0 0;
|
|
86
|
+
font-size: 16px;
|
|
58
87
|
}
|
|
59
88
|
`;
|
|
60
|
-
const TextWrapper = styled.div
|
|
89
|
+
const TextWrapper = styled.div<WrapperProps>`
|
|
61
90
|
display: flex;
|
|
62
91
|
align-items: center;
|
|
63
92
|
flex-wrap: wrap;
|
|
@@ -67,88 +96,80 @@ const TextWrapper = styled.div`
|
|
|
67
96
|
}
|
|
68
97
|
`;
|
|
69
98
|
|
|
70
|
-
const IconWrapper = styled.div
|
|
99
|
+
const IconWrapper = styled.div<WrapperProps>`
|
|
71
100
|
padding-right: ${spacing.small};
|
|
72
|
-
display:
|
|
101
|
+
display: ${(props) => StyleByType(props.boxType).display};
|
|
73
102
|
align-items: flex-start;
|
|
74
103
|
${mq.range({ from: breakpoints.tabletWide })} {
|
|
75
104
|
padding-top: 4px;
|
|
76
105
|
}
|
|
77
106
|
`;
|
|
78
107
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
const CloseButton = styled(Button)`
|
|
91
|
-
display: flex;
|
|
92
|
-
justify-content: center;
|
|
93
|
-
align-items: center;
|
|
94
|
-
font-weight: ${fonts.weight.semibold};
|
|
95
|
-
font-size: 16px;
|
|
96
|
-
color: ${(props) => colorsByType(props.boxType).color};
|
|
97
|
-
&:hover {
|
|
98
|
-
color: ${(props) => colorsByType(props.boxType).color};
|
|
99
|
-
}
|
|
108
|
+
const LinkWrapper = styled.div`
|
|
109
|
+
display: block;
|
|
110
|
+
width: 100%;
|
|
111
|
+
background-color: #f9f4c8;
|
|
112
|
+
padding-bottom: 20px;
|
|
113
|
+
margin-top: -2px;
|
|
114
|
+
padding-left: 58px;
|
|
115
|
+
border-radius: 0px 0px 5px 5px;
|
|
100
116
|
${mq.range({ until: breakpoints.mobileWide })} {
|
|
101
|
-
|
|
117
|
+
padding-left: 45px;
|
|
102
118
|
}
|
|
103
119
|
`;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
120
|
+
const Link = styled.a`
|
|
121
|
+
color: #20588f;
|
|
122
|
+
font-size: 16px;
|
|
123
|
+
padding-bottom: 1px;
|
|
124
|
+
margin: 0px 40px 1px 2px;
|
|
125
|
+
font-family: ${fonts.sans};
|
|
108
126
|
${mq.range({ until: breakpoints.mobileWide })} {
|
|
109
|
-
margin
|
|
110
|
-
|
|
111
|
-
font-weight: ${fonts.weight.normal};
|
|
127
|
+
margin: 0px 15px 1px 5px;
|
|
128
|
+
box-shadow: none;
|
|
112
129
|
}
|
|
113
130
|
`;
|
|
114
131
|
|
|
132
|
+
type LinkProps = {
|
|
133
|
+
href?: string;
|
|
134
|
+
text?: string;
|
|
135
|
+
};
|
|
115
136
|
type Props = {
|
|
116
137
|
type?: WrapperProps['boxType'];
|
|
117
|
-
heading?: string;
|
|
118
138
|
sticky?: boolean;
|
|
119
|
-
onClose?:
|
|
120
|
-
children
|
|
139
|
+
onClose?: boolean;
|
|
140
|
+
children?: string;
|
|
141
|
+
links?: LinkProps[];
|
|
121
142
|
};
|
|
122
143
|
|
|
123
|
-
export const MessageBox = ({
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
</
|
|
144
|
+
export const MessageBox = ({ type, sticky = false, onClose, children, links, t }: Props & WithTranslation) => {
|
|
145
|
+
const [hideMessageBox, setHideMessageBox] = useState(false);
|
|
146
|
+
const onCloseMessageBox = () => {
|
|
147
|
+
setHideMessageBox(true);
|
|
148
|
+
};
|
|
149
|
+
const Icon = type === 'ghost' ? HumanMaleBoard : InformationOutline;
|
|
150
|
+
return (
|
|
151
|
+
//StickyStyle top:84 makes sure that the messagebox sits beneath the masthead (header ) and the topOffsett sets it so that it applies when reaching the top of the messagebox
|
|
152
|
+
<Sticky disabled={!sticky} stickyStyle={{ zIndex: 9998, top: 84 }} topOffset={-84}>
|
|
153
|
+
<Wrapper boxType={type} style={{ display: hideMessageBox ? 'none' : 'flex' }}>
|
|
154
|
+
<InfoWrapper boxType={type}>
|
|
155
|
+
<IconWrapper boxType={type}>
|
|
156
|
+
<Icon style={{ width: '24px', height: '24px' }} />
|
|
157
|
+
</IconWrapper>
|
|
158
|
+
<TextWrapper>{children}</TextWrapper>
|
|
159
|
+
</InfoWrapper>
|
|
160
|
+
{onClose && <CloseButton onClick={onCloseMessageBox} color="#444444" />}
|
|
161
|
+
</Wrapper>
|
|
162
|
+
|
|
163
|
+
{links && (
|
|
164
|
+
//loops through the links passed in as properties if there are any and creates a working link for each of them
|
|
165
|
+
<LinkWrapper style={{ display: hideMessageBox ? 'none' : 'flex' }}>
|
|
166
|
+
{links.map((x) => (
|
|
167
|
+
<Link href={x.href}>{x.text}</Link>
|
|
168
|
+
))}
|
|
169
|
+
</LinkWrapper>
|
|
149
170
|
)}
|
|
150
|
-
</
|
|
151
|
-
|
|
152
|
-
|
|
171
|
+
</Sticky>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
153
174
|
|
|
154
175
|
export default withTranslation()(MessageBox);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022-present, NDLA.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
|
|
12
|
+
import styled from '@emotion/styled';
|
|
13
|
+
|
|
14
|
+
const MiniMesssage = styled.div`
|
|
15
|
+
background-color: #f9f4c8;
|
|
16
|
+
text-align: center;
|
|
17
|
+
display: inline-block;
|
|
18
|
+
padding: 5px;
|
|
19
|
+
text-transform: uppercase;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
font-size: 14px;
|
|
22
|
+
margin-left: 10px;
|
|
23
|
+
margin-bottom: 10px;
|
|
24
|
+
border-radius: 5px;
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
type Props = {
|
|
28
|
+
tagMessage: string;
|
|
29
|
+
};
|
|
30
|
+
export const MessageBoxTag = ({ tagMessage }: Props) => {
|
|
31
|
+
const { t } = useTranslation();
|
|
32
|
+
return <MiniMesssage>{t(tagMessage)}</MiniMesssage>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default MessageBoxTag;
|
package/src/MessageBox/index.ts
CHANGED
package/src/NDLAFilm/shapes.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
|
|
3
|
+
export const movieShape = PropTypes.shape({
|
|
4
|
+
id: PropTypes.string.isRequired,
|
|
5
|
+
metaDescription: PropTypes.string.isRequired,
|
|
6
|
+
title: PropTypes.string.isRequired,
|
|
7
|
+
metaImage: PropTypes.shape({
|
|
8
|
+
url: PropTypes.string.isRequired,
|
|
9
|
+
alt: PropTypes.string.isRequired,
|
|
10
|
+
}),
|
|
11
|
+
path: PropTypes.string.isRequired,
|
|
12
|
+
});
|
|
13
|
+
|
|
3
14
|
export const topicShape = PropTypes.shape({
|
|
4
15
|
id: PropTypes.string,
|
|
5
16
|
name: PropTypes.string,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from '@emotion/styled';
|
|
3
3
|
import { breakpoints, mq, spacing } from '@ndla/core';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
4
5
|
import LayoutItem, { OneColumn } from '../Layout';
|
|
5
|
-
import { NavigationHeading } from '../Navigation';
|
|
6
6
|
import ProgrammeSubjects from './ProgrammeSubjects';
|
|
7
7
|
import { GradesProps } from './ProgrammeSubjects';
|
|
8
|
-
|
|
8
|
+
import MessageBox from '../MessageBox/MessageBox';
|
|
9
|
+
import { NavigationHeading } from '..';
|
|
9
10
|
const StyledWrapper = styled.div`
|
|
10
11
|
display: flex;
|
|
11
12
|
flex-direction: column;
|
|
@@ -63,9 +64,11 @@ const SubjectsWrapper = styled.div`
|
|
|
63
64
|
type Props = GradesProps & {
|
|
64
65
|
heading?: string;
|
|
65
66
|
image?: string;
|
|
67
|
+
messageBoxText?: string;
|
|
66
68
|
};
|
|
67
69
|
|
|
68
|
-
export const Programme = ({ heading, image, grades, selectedGrade, onChangeGrade }: Props) => {
|
|
70
|
+
export const Programme = ({ heading, image, grades, selectedGrade, onChangeGrade, messageBoxText }: Props) => {
|
|
71
|
+
const { t } = useTranslation();
|
|
69
72
|
return (
|
|
70
73
|
<StyledWrapper>
|
|
71
74
|
<StyledBackground image={image} />
|
|
@@ -74,6 +77,7 @@ export const Programme = ({ heading, image, grades, selectedGrade, onChangeGrade
|
|
|
74
77
|
<LayoutItem layout="extend">
|
|
75
78
|
<StyledContentWrapper>
|
|
76
79
|
<NavigationHeading>{heading}</NavigationHeading>
|
|
80
|
+
{messageBoxText && <MessageBox>{t(messageBoxText)}</MessageBox>}
|
|
77
81
|
<SubjectsWrapper>
|
|
78
82
|
<ProgrammeSubjects grades={grades} selectedGrade={selectedGrade} onChangeGrade={onChangeGrade} />
|
|
79
83
|
</SubjectsWrapper>
|
|
@@ -7,20 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import React, { useEffect, useRef, useState } from 'react';
|
|
10
|
-
import { History } from 'history';
|
|
11
10
|
import styled from '@emotion/styled';
|
|
12
11
|
import { breakpoints, colors, fonts, misc, mq, spacing } from '@ndla/core';
|
|
13
|
-
import {
|
|
14
|
-
ChevronDown,
|
|
15
|
-
ChevronUp,
|
|
16
|
-
Esc,
|
|
17
|
-
KeyboardReturn,
|
|
18
|
-
Search as SearchIcon,
|
|
19
|
-
Wrench,
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
} from '@ndla/icons/common';
|
|
12
|
+
import { ChevronDown, ChevronUp, Esc, KeyboardReturn, Search as SearchIcon, Wrench } from '@ndla/icons/common';
|
|
22
13
|
import SafeLink from '@ndla/safelink';
|
|
23
|
-
// @ts-ignore
|
|
24
14
|
import { useTranslation } from 'react-i18next';
|
|
25
15
|
import ContentTypeResult from './ContentTypeResult';
|
|
26
16
|
import { highlightStyle } from './ContentTypeResultStyles';
|
|
@@ -218,14 +208,13 @@ type Props = {
|
|
|
218
208
|
to: string;
|
|
219
209
|
};
|
|
220
210
|
onNavigate?: VoidFunction;
|
|
221
|
-
infoText
|
|
222
|
-
ignoreContentTypeBadge
|
|
211
|
+
infoText?: string;
|
|
212
|
+
ignoreContentTypeBadge?: boolean;
|
|
223
213
|
searchString: string;
|
|
224
214
|
loading: boolean;
|
|
225
215
|
frontpage?: boolean;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
suggestionUrl: string;
|
|
216
|
+
suggestion?: string;
|
|
217
|
+
suggestionUrl?: string;
|
|
229
218
|
};
|
|
230
219
|
|
|
231
220
|
const SearchResultSleeve: React.FC<Props> = ({
|
|
@@ -238,7 +227,6 @@ const SearchResultSleeve: React.FC<Props> = ({
|
|
|
238
227
|
searchString,
|
|
239
228
|
loading,
|
|
240
229
|
frontpage,
|
|
241
|
-
history,
|
|
242
230
|
suggestion,
|
|
243
231
|
suggestionUrl,
|
|
244
232
|
}) => {
|
|
@@ -332,7 +320,7 @@ const SearchResultSleeve: React.FC<Props> = ({
|
|
|
332
320
|
<strong ref={searchAllRef}>{searchString}</strong>
|
|
333
321
|
<small>{t('welcomePage.searchAllInfo')}</small>
|
|
334
322
|
</StyledSearchLink>
|
|
335
|
-
{suggestion && (
|
|
323
|
+
{suggestion && suggestionUrl && (
|
|
336
324
|
<StyledSearchLink css={keyboardPathNavigation === GO_TO_SUGGESTION && highlightStyle} to={suggestionUrl}>
|
|
337
325
|
<SearchIcon className="c-icon--22" />
|
|
338
326
|
<small>{t('searchPage.resultType.searchPhraseSuggestion')}</small>
|
|
@@ -342,7 +330,7 @@ const SearchResultSleeve: React.FC<Props> = ({
|
|
|
342
330
|
</SearchLinkContainer>
|
|
343
331
|
{result.map((contentTypeResult: ContentTypeResultType) => (
|
|
344
332
|
<ContentTypeResult
|
|
345
|
-
ignoreContentTypeBadge={ignoreContentTypeBadge}
|
|
333
|
+
ignoreContentTypeBadge={!!ignoreContentTypeBadge}
|
|
346
334
|
onNavigate={onNavigate}
|
|
347
335
|
contentTypeResult={contentTypeResult}
|
|
348
336
|
resourceToLinkProps={resourceToLinkProps}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
9
|
+
import React, { FormEvent, useEffect, useRef, useState } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
11
|
import { colors, breakpoints, mq } from '@ndla/core';
|
|
12
12
|
// @ts-ignore
|
|
@@ -76,8 +76,8 @@ const SearchInput = styled.input`
|
|
|
76
76
|
`;
|
|
77
77
|
|
|
78
78
|
type Props = {
|
|
79
|
-
onSubmit: (event:
|
|
80
|
-
value
|
|
79
|
+
onSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
|
80
|
+
value?: string;
|
|
81
81
|
onChange: (value: string) => void;
|
|
82
82
|
filters?: PopupFilterProps;
|
|
83
83
|
activeFilters?: {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React from 'react';
|
|
9
|
+
import React, { FormEvent } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
11
|
import { breakpoints, fonts, mq, spacing } from '@ndla/core';
|
|
12
12
|
|
|
@@ -75,7 +75,7 @@ type Props = {
|
|
|
75
75
|
searchPhrase?: string;
|
|
76
76
|
searchPhraseSuggestion?: string;
|
|
77
77
|
searchPhraseSuggestionOnClick?: () => void;
|
|
78
|
-
searchValue
|
|
78
|
+
searchValue?: string;
|
|
79
79
|
filters?: PopupFilterProps;
|
|
80
80
|
activeFilters?: {
|
|
81
81
|
filters: FilterProps[];
|
|
@@ -83,7 +83,7 @@ type Props = {
|
|
|
83
83
|
};
|
|
84
84
|
competenceGoals?: CompetenceGoalsItemType[];
|
|
85
85
|
onSearchValueChange: (value: string) => void;
|
|
86
|
-
onSubmit: () => void;
|
|
86
|
+
onSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
|
87
87
|
noResults?: boolean;
|
|
88
88
|
};
|
|
89
89
|
|