learningtribes-studio-frontend 1.4.1 → 1.4.2-alpha.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/dist/common.min.css +1 -1
- package/dist/common.min.js +1 -1
- package/dist/common.min.js.map +1 -1
- package/dist/editImageModal.min.css +1 -1
- package/dist/editImageModal.min.js +1 -1
- package/dist/editImageModal.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AssetsDropZone/AssetsDropZone.scss +88 -18
- package/src/components/AssetsDropZone/displayMessages.jsx +2 -2
- package/src/components/AssetsDropZone/index.jsx +18 -17
- package/src/components/AssetsList/AssetsList.scss +132 -0
- package/src/components/AssetsList/index.jsx +75 -68
- package/src/components/EditImageModal/EditImageModal.scss +70 -0
- package/src/components/EditImageModal/displayMessages.jsx +2 -2
- package/src/components/EditImageModal/index.jsx +37 -26
package/package.json
CHANGED
|
@@ -5,25 +5,42 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.drop-zone-compact {
|
|
8
|
-
border:
|
|
9
|
-
|
|
8
|
+
border: 1px dashed #d0d0d0;
|
|
9
|
+
border-radius: 8px;
|
|
10
|
+
padding: 24px 20px;
|
|
11
|
+
background-color: #fafafa;
|
|
12
|
+
transition: all 0.2s ease;
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
|
|
15
|
+
&:hover {
|
|
16
|
+
border-color: #4a90d9;
|
|
17
|
+
background-color: #fff;
|
|
18
|
+
}
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
margin-
|
|
14
|
-
|
|
20
|
+
[data-identifier="asset-drop-zone-icon"] {
|
|
21
|
+
color: #4a90d9;
|
|
22
|
+
margin-bottom: 12px;
|
|
23
|
+
|
|
24
|
+
span {
|
|
25
|
+
font-size: 32px;
|
|
26
|
+
}
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
h2 {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.label-or {
|
|
34
|
+
display: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
button.btn {
|
|
38
|
+
display: none;
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
p {
|
|
25
|
-
font-size:
|
|
26
|
-
margin-bottom:
|
|
42
|
+
font-size: 12px;
|
|
43
|
+
margin-bottom: 0;
|
|
27
44
|
}
|
|
28
45
|
}
|
|
29
46
|
|
|
@@ -31,16 +48,53 @@
|
|
|
31
48
|
@extend .drop-zone-compact;
|
|
32
49
|
|
|
33
50
|
@media (min-width: map-get($grid-breakpoints, 'md')) {
|
|
34
|
-
padding:
|
|
35
|
-
h2 {
|
|
36
|
-
margin-bottom: inherit;
|
|
37
|
-
}
|
|
51
|
+
padding: 30px 20px;
|
|
38
52
|
}
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
.drop-active {
|
|
42
|
-
outline:
|
|
43
|
-
|
|
56
|
+
outline: none;
|
|
57
|
+
border: 2px dashed #4a90d9;
|
|
58
|
+
background-color: rgba(74, 144, 217, 0.05);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.upload-prompt {
|
|
62
|
+
text-align: center;
|
|
63
|
+
margin-bottom: 6px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.upload-link {
|
|
67
|
+
background: none;
|
|
68
|
+
border: none;
|
|
69
|
+
color: #4a90d9;
|
|
70
|
+
font-size: 14px;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
padding: 0;
|
|
74
|
+
text-decoration: none;
|
|
75
|
+
|
|
76
|
+
&:hover {
|
|
77
|
+
text-decoration: underline;
|
|
78
|
+
color: darken(#4a90d9, 10%);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&:focus {
|
|
82
|
+
outline: 2px solid rgba(74, 144, 217, 0.5);
|
|
83
|
+
outline-offset: 2px;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.upload-text {
|
|
88
|
+
color: #333;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
font-weight: 400;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.size-limit {
|
|
94
|
+
text-align: center;
|
|
95
|
+
color: #4a90d9;
|
|
96
|
+
font-size: 12px;
|
|
97
|
+
margin-bottom: 0;
|
|
44
98
|
}
|
|
45
99
|
|
|
46
100
|
.supported-files-types {
|
|
@@ -54,3 +108,19 @@
|
|
|
54
108
|
font-size: 12px !important;
|
|
55
109
|
font-weight: 400;
|
|
56
110
|
}
|
|
111
|
+
|
|
112
|
+
// Collapsed zone in image modal
|
|
113
|
+
.collapsedZoneStyle {
|
|
114
|
+
.drop-zone-compact,
|
|
115
|
+
.drop-zone {
|
|
116
|
+
padding: 20px 16px;
|
|
117
|
+
|
|
118
|
+
[data-identifier="asset-drop-zone-icon"] {
|
|
119
|
+
margin-bottom: 8px;
|
|
120
|
+
|
|
121
|
+
span {
|
|
122
|
+
font-size: 28px;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -8,12 +8,12 @@ const messages = defineMessages({
|
|
|
8
8
|
},
|
|
9
9
|
assetsDropZoneBrowseLabel: {
|
|
10
10
|
id: 'assetsDropZoneBrowseLabel',
|
|
11
|
-
defaultMessage: '
|
|
11
|
+
defaultMessage: 'Click to upload',
|
|
12
12
|
description: 'Upload label for the "Browse" button',
|
|
13
13
|
},
|
|
14
14
|
assetsDropZoneHeader: {
|
|
15
15
|
id: 'assetsDropZoneHeader',
|
|
16
|
-
defaultMessage: '
|
|
16
|
+
defaultMessage: 'or drag and drop',
|
|
17
17
|
description: 'Upload with dropzone section heading',
|
|
18
18
|
},
|
|
19
19
|
assetsDropZoneMaxFileSizeLabel: {
|
|
@@ -37,7 +37,9 @@ export default class AssetsDropZone extends React.Component {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
setUploadButtonRef = (ref) => {
|
|
40
|
-
this.props.buttonRef
|
|
40
|
+
if (this.props.buttonRef) {
|
|
41
|
+
this.props.buttonRef(ref);
|
|
42
|
+
}
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
handleClick = () => {
|
|
@@ -66,30 +68,29 @@ export default class AssetsDropZone extends React.Component {
|
|
|
66
68
|
<div className={styles['center-text']} data-identifier="asset-drop-zone-icon">
|
|
67
69
|
<span
|
|
68
70
|
aria-hidden
|
|
69
|
-
className={'
|
|
71
|
+
className={'far fa-image '+classNames(
|
|
70
72
|
styles['center-text'],
|
|
71
|
-
//FontAwesomeStyles.fa,
|
|
72
|
-
//FontAwesomeStyles['fa-cloud-upload'],
|
|
73
73
|
FontAwesomeStyles['fa-3x'])}
|
|
74
74
|
/>
|
|
75
75
|
</div>
|
|
76
|
-
<
|
|
77
|
-
{ displayText => (
|
|
78
|
-
<h2 data-identifier="asset-drop-zone-header">{displayText}</h2>
|
|
79
|
-
)}
|
|
80
|
-
</WrappedMessage>
|
|
81
|
-
<span className="label-or">or</span>
|
|
82
|
-
<div className={styles['center-text']}>
|
|
76
|
+
<div className={styles['upload-prompt']}>
|
|
83
77
|
<WrappedMessage message={messages.assetsDropZoneBrowseLabel} >
|
|
84
78
|
{ displayText => (
|
|
85
|
-
<
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
86
81
|
aria-describedby="asset-drop-zone-max-file-size-label"
|
|
87
|
-
className={['
|
|
82
|
+
className={styles['upload-link']}
|
|
88
83
|
data-identifier="asset-drop-zone-browse-button"
|
|
89
|
-
label={displayText}
|
|
90
84
|
onClick={this.handleClick}
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
ref={this.setUploadButtonRef}
|
|
86
|
+
>
|
|
87
|
+
{displayText}
|
|
88
|
+
</button>
|
|
89
|
+
)}
|
|
90
|
+
</WrappedMessage>
|
|
91
|
+
<WrappedMessage message={messages.assetsDropZoneHeader}>
|
|
92
|
+
{ displayText => (
|
|
93
|
+
<span className={styles['upload-text']} data-identifier="asset-drop-zone-header"> {displayText}</span>
|
|
93
94
|
)}
|
|
94
95
|
</WrappedMessage>
|
|
95
96
|
</div>
|
|
@@ -102,7 +103,7 @@ export default class AssetsDropZone extends React.Component {
|
|
|
102
103
|
{ displayText => (
|
|
103
104
|
<p
|
|
104
105
|
aria-hidden
|
|
105
|
-
className={styles['
|
|
106
|
+
className={styles['size-limit']}
|
|
106
107
|
data-identifier="asset-drop-zone-max-file-size-label"
|
|
107
108
|
id="asset-drop-zone-max-file-size-label"
|
|
108
109
|
>
|
|
@@ -1,6 +1,138 @@
|
|
|
1
1
|
@import 'edx-bootstrap';
|
|
2
2
|
@import 'utils/scss/focus';
|
|
3
3
|
|
|
4
|
+
// Horizontal scrollable grid
|
|
5
|
+
.assets-grid {
|
|
6
|
+
display: flex;
|
|
7
|
+
gap: 10px;
|
|
8
|
+
overflow-x: auto;
|
|
9
|
+
padding: 8px 0;
|
|
10
|
+
margin-bottom: 10px;
|
|
11
|
+
|
|
12
|
+
&:focus {
|
|
13
|
+
@include focus();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Custom scrollbar
|
|
17
|
+
&::-webkit-scrollbar {
|
|
18
|
+
height: 6px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&::-webkit-scrollbar-track {
|
|
22
|
+
background: #f0f0f0;
|
|
23
|
+
border-radius: 3px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&::-webkit-scrollbar-thumb {
|
|
27
|
+
background: #c0c0c0;
|
|
28
|
+
border-radius: 3px;
|
|
29
|
+
|
|
30
|
+
&:hover {
|
|
31
|
+
background: #a0a0a0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.asset-grid-item {
|
|
37
|
+
flex-shrink: 0;
|
|
38
|
+
width: 100px;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
transition: all 0.2s ease;
|
|
41
|
+
|
|
42
|
+
&:hover {
|
|
43
|
+
.asset-preview {
|
|
44
|
+
border-color: #c0c0c0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&.selected {
|
|
49
|
+
.asset-preview {
|
|
50
|
+
border-color: #4a90d9;
|
|
51
|
+
border-width: 2px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.asset-name {
|
|
55
|
+
color: #4a90d9;
|
|
56
|
+
background-color: rgba(74, 144, 217, 0.1);
|
|
57
|
+
padding: 2px 4px;
|
|
58
|
+
border-radius: 4px;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.asset-preview {
|
|
64
|
+
width: 100px;
|
|
65
|
+
height: 100px;
|
|
66
|
+
border: 1px solid #e0e0e0;
|
|
67
|
+
border-radius: 8px;
|
|
68
|
+
background-color: #fff;
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
position: relative;
|
|
74
|
+
margin-bottom: 8px;
|
|
75
|
+
transition: border-color 0.2s ease;
|
|
76
|
+
overflow: hidden;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.file-type-badge {
|
|
80
|
+
position: absolute;
|
|
81
|
+
top: 6px;
|
|
82
|
+
left: 6px;
|
|
83
|
+
background-color: #e8f4fd;
|
|
84
|
+
color: #1976d2;
|
|
85
|
+
font-size: 10px;
|
|
86
|
+
font-weight: 700;
|
|
87
|
+
padding: 2px 6px;
|
|
88
|
+
border-radius: 4px;
|
|
89
|
+
text-transform: lowercase;
|
|
90
|
+
z-index: 1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.asset-thumbnail {
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: 100%;
|
|
96
|
+
object-fit: cover;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.asset-icon {
|
|
100
|
+
font-size: 36px;
|
|
101
|
+
color: #9e9e9e;
|
|
102
|
+
|
|
103
|
+
i {
|
|
104
|
+
display: block;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.asset-info {
|
|
109
|
+
text-align: center;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.asset-name {
|
|
113
|
+
font-size: 12px;
|
|
114
|
+
font-weight: 500;
|
|
115
|
+
color: #333;
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
text-overflow: ellipsis;
|
|
119
|
+
max-width: 100px;
|
|
120
|
+
margin-bottom: 2px;
|
|
121
|
+
|
|
122
|
+
&.selected {
|
|
123
|
+
color: #4a90d9;
|
|
124
|
+
background-color: rgba(74, 144, 217, 0.1);
|
|
125
|
+
padding: 2px 4px;
|
|
126
|
+
border-radius: 4px;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.asset-size {
|
|
131
|
+
font-size: 11px;
|
|
132
|
+
color: #666;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Old styles
|
|
4
136
|
.assets-list-image-preview-container {
|
|
5
137
|
background-color: theme-color('light');
|
|
6
138
|
color: theme-color('dark');
|
|
@@ -72,57 +72,64 @@ export default class AssetsList extends React.Component {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
getFileExtension = (displayName) => {
|
|
76
|
+
if (!displayName) return '';
|
|
77
|
+
const lastDot = displayName.lastIndexOf('.');
|
|
78
|
+
if (lastDot === -1 || lastDot === displayName.length - 1) {
|
|
79
|
+
return 'file';
|
|
80
|
+
}
|
|
81
|
+
return displayName.substring(lastDot + 1).toLowerCase();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
formatFileSize = (bytes) => {
|
|
85
|
+
if (!bytes || bytes === 0) return '';
|
|
86
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
87
|
+
const k = 1024;
|
|
88
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
89
|
+
const size = (bytes / Math.pow(k, i)).toFixed(i === 0 ? 0 : 1);
|
|
90
|
+
return `${size} ${units[i]}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getAssetGridItem = (asset, index) => {
|
|
83
94
|
const isSelected = this.props.selectedAsset.id === asset.id;
|
|
95
|
+
const baseUrl = this.props.courseDetails.base_url || '';
|
|
96
|
+
const fileExt = this.getFileExtension(asset.display_name);
|
|
97
|
+
const fileSize = this.formatFileSize(asset.file_size);
|
|
84
98
|
|
|
85
99
|
return (
|
|
86
|
-
<
|
|
87
|
-
// prevent clicking on list item from triggering parent's focus
|
|
100
|
+
<div
|
|
88
101
|
onMouseDown={(e) => { e.preventDefault(); this.onAssetClick(asset, index); }}
|
|
89
|
-
className={classNames('
|
|
102
|
+
className={classNames(styles['asset-grid-item'], { [styles.selected]: isSelected })}
|
|
90
103
|
id={`asset-list-option-${index}`}
|
|
91
104
|
aria-selected={isSelected}
|
|
92
105
|
role="option"
|
|
93
|
-
key={asset.display_name}
|
|
106
|
+
key={asset.id || asset.display_name}
|
|
94
107
|
tabIndex="-1"
|
|
95
|
-
aria-labelledby={`name-header asset-name-${index} date-added-header asset-date-${index}`}
|
|
96
108
|
>
|
|
97
|
-
<div className=
|
|
98
|
-
{
|
|
99
|
-
{
|
|
100
|
-
|
|
109
|
+
<div className={styles['asset-preview']}>
|
|
110
|
+
<span className={styles['file-type-badge']}>{fileExt}</span>
|
|
111
|
+
{asset.thumbnail ? (
|
|
112
|
+
<img
|
|
113
|
+
className={styles['asset-thumbnail']}
|
|
114
|
+
src={`${baseUrl}${asset.thumbnail}`}
|
|
115
|
+
alt=""
|
|
116
|
+
/>
|
|
117
|
+
) : (
|
|
118
|
+
<div className={styles['asset-icon']}>
|
|
119
|
+
<i className="far fa-image" />
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
<div className={styles['asset-info']}>
|
|
124
|
+
<div className={classNames(styles['asset-name'], { [styles.selected]: isSelected })} title={asset.display_name}>
|
|
125
|
+
{asset.display_name}
|
|
126
|
+
</div>
|
|
127
|
+
{fileSize && (
|
|
128
|
+
<div className={styles['asset-size']}>
|
|
129
|
+
{fileSize}
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
101
132
|
</div>
|
|
102
|
-
</li>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
getDateAddedElement = (dateAdded, index) => (
|
|
107
|
-
<span id={`asset-date-${index}`} className="col-3" data-identifier="asset-date-added">{dateAdded}</span>
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
getDisplayNameElement = (displayName, index) => (
|
|
111
|
-
<span id={`asset-name-${index}`} className="col-6" data-identifier="asset-file-name">{displayName}</span>
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
getImageThumbnail(thumbnail) {
|
|
115
|
-
const baseUrl = this.props.courseDetails.base_url || '';
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<div className={styles['assets-list-image-preview-container']}>
|
|
119
|
-
{
|
|
120
|
-
thumbnail ?
|
|
121
|
-
<img className={styles['assets-list-image-preview-image']} src={`${baseUrl}${thumbnail}`} alt="" data-identifier="asset-image-thumbnail" /> :
|
|
122
|
-
<WrappedMessage message={messages.assetsListNoPreview} >
|
|
123
|
-
{displayText => <span className={classNames('text-center')} data-identifier="asset-image-thumbnail">{displayText}</span>}
|
|
124
|
-
</WrappedMessage>
|
|
125
|
-
}
|
|
126
133
|
</div>
|
|
127
134
|
);
|
|
128
135
|
}
|
|
@@ -130,17 +137,11 @@ export default class AssetsList extends React.Component {
|
|
|
130
137
|
getSelectedAssetIndex = (assetsList, selectedAsset) => (assetsList.findIndex(
|
|
131
138
|
asset => asset.id === selectedAsset.id));
|
|
132
139
|
|
|
133
|
-
getThumbnailElement = thumbnail => (
|
|
134
|
-
<span aria-hidden className="col">{this.getImageThumbnail(thumbnail)}</span>
|
|
135
|
-
);
|
|
136
|
-
|
|
137
140
|
handleKeyDown = (e) => {
|
|
138
141
|
switch (e.key) {
|
|
139
|
-
case '
|
|
140
|
-
// prevent scrolling entire modal body with arrow keys
|
|
142
|
+
case 'ArrowRight': {
|
|
141
143
|
e.preventDefault();
|
|
142
|
-
|
|
143
|
-
if (this.state.selectedAssetIndex < this.props.paginationMetadata.pageSize - 1) {
|
|
144
|
+
if (this.state.selectedAssetIndex < this.props.assetsList.length - 1) {
|
|
144
145
|
this.setState(
|
|
145
146
|
(state, props) => ({
|
|
146
147
|
selectedAssetIndex: this.state.selectedAssetIndex + 1,
|
|
@@ -151,10 +152,8 @@ export default class AssetsList extends React.Component {
|
|
|
151
152
|
}
|
|
152
153
|
break;
|
|
153
154
|
}
|
|
154
|
-
case '
|
|
155
|
-
// prevent scrolling entire modal body with arrow keys
|
|
155
|
+
case 'ArrowLeft': {
|
|
156
156
|
e.preventDefault();
|
|
157
|
-
|
|
158
157
|
if (this.state.selectedAssetIndex > 0) {
|
|
159
158
|
this.setState(
|
|
160
159
|
(state, props) => ({
|
|
@@ -171,29 +170,36 @@ export default class AssetsList extends React.Component {
|
|
|
171
170
|
}
|
|
172
171
|
|
|
173
172
|
render = () => {
|
|
174
|
-
const
|
|
175
|
-
this.
|
|
173
|
+
const assetsGridItems = this.props.assetsList.map((asset, index) =>
|
|
174
|
+
this.getAssetGridItem(asset, index));
|
|
176
175
|
|
|
177
176
|
return (
|
|
178
|
-
<
|
|
179
|
-
{this.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
{assetsListItems}
|
|
189
|
-
</ol>
|
|
190
|
-
</React.Fragment>
|
|
177
|
+
<div
|
|
178
|
+
aria-activedescendant={this.state.selectedAssetIndex > -1 ? `asset-list-option-${this.state.selectedAssetIndex}` : null}
|
|
179
|
+
className={styles['assets-grid']}
|
|
180
|
+
onFocus={this.onListBoxFocus}
|
|
181
|
+
onKeyDown={this.handleKeyDown}
|
|
182
|
+
role="listbox"
|
|
183
|
+
tabIndex="0"
|
|
184
|
+
>
|
|
185
|
+
{assetsGridItems}
|
|
186
|
+
</div>
|
|
191
187
|
);
|
|
192
188
|
};
|
|
193
189
|
}
|
|
194
190
|
|
|
195
191
|
AssetsList.propTypes = {
|
|
196
|
-
assetsList: PropTypes.arrayOf(PropTypes.
|
|
192
|
+
assetsList: PropTypes.arrayOf(PropTypes.shape({
|
|
193
|
+
display_name: PropTypes.string,
|
|
194
|
+
content_type: PropTypes.string,
|
|
195
|
+
url: PropTypes.string,
|
|
196
|
+
date_added: PropTypes.string,
|
|
197
|
+
id: PropTypes.string,
|
|
198
|
+
portable_url: PropTypes.string,
|
|
199
|
+
thumbnail: PropTypes.string,
|
|
200
|
+
external_url: PropTypes.string,
|
|
201
|
+
file_size: PropTypes.number,
|
|
202
|
+
})).isRequired,
|
|
197
203
|
courseDetails: PropTypes.shape({
|
|
198
204
|
lang: PropTypes.string,
|
|
199
205
|
url_name: PropTypes.string,
|
|
@@ -222,5 +228,6 @@ AssetsList.propTypes = {
|
|
|
222
228
|
portable_url: PropTypes.string,
|
|
223
229
|
thumbnail: PropTypes.string,
|
|
224
230
|
external_url: PropTypes.string,
|
|
231
|
+
file_size: PropTypes.number,
|
|
225
232
|
}).isRequired,
|
|
226
233
|
};
|
|
@@ -76,3 +76,73 @@
|
|
|
76
76
|
.invalid-feedback {
|
|
77
77
|
font-size: $font-size-base;
|
|
78
78
|
}
|
|
79
|
+
|
|
80
|
+
.modal-body {
|
|
81
|
+
// Form fields
|
|
82
|
+
form {
|
|
83
|
+
.paragon-fieldset {
|
|
84
|
+
margin-bottom: 1.5rem;
|
|
85
|
+
|
|
86
|
+
fieldset {
|
|
87
|
+
legend {
|
|
88
|
+
font-size: 14px;
|
|
89
|
+
font-weight: 500;
|
|
90
|
+
color: #333;
|
|
91
|
+
margin-bottom: 0.5rem;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.form-group {
|
|
97
|
+
margin-bottom: 1rem;
|
|
98
|
+
|
|
99
|
+
label {
|
|
100
|
+
font-size: 14px;
|
|
101
|
+
font-weight: 500;
|
|
102
|
+
color: #333;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.form-control {
|
|
106
|
+
border-radius: 8px;
|
|
107
|
+
border: 1px solid #e0e0e0;
|
|
108
|
+
padding: 10px 14px;
|
|
109
|
+
font-size: 14px;
|
|
110
|
+
|
|
111
|
+
&:focus {
|
|
112
|
+
border-color: #4a90d9;
|
|
113
|
+
box-shadow: 0 0 0 2px rgba(74, 144, 217, 0.1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.form-text {
|
|
118
|
+
font-size: 12px;
|
|
119
|
+
color: #666;
|
|
120
|
+
margin-top: 4px;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Dimensions row
|
|
126
|
+
.form-row {
|
|
127
|
+
.col {
|
|
128
|
+
.form-group {
|
|
129
|
+
label {
|
|
130
|
+
font-size: 14px;
|
|
131
|
+
font-weight: 500;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Checkbox
|
|
139
|
+
.form-check {
|
|
140
|
+
.form-check-input {
|
|
141
|
+
margin-top: 0.25rem;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.form-check-label {
|
|
145
|
+
font-size: 14px;
|
|
146
|
+
color: #333;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -83,8 +83,8 @@ const messages = defineMessages({
|
|
|
83
83
|
},
|
|
84
84
|
editImageModalInsertImageButton: {
|
|
85
85
|
id: 'editImageModalInsertImageButton',
|
|
86
|
-
defaultMessage: '
|
|
87
|
-
description: 'Text inside the
|
|
86
|
+
defaultMessage: 'Save',
|
|
87
|
+
description: 'Text inside the Save button at the bottom of the modal',
|
|
88
88
|
},
|
|
89
89
|
editImageModalLearnMore: {
|
|
90
90
|
id: 'editImageModalLearnMore',
|