Commit eabfba48 by Mushtaq Ali

Change video image requirements text hover - EDUCATOR-577

parent 9750cd2a
...@@ -717,7 +717,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): ...@@ -717,7 +717,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
'width': 16, # 16x9 'width': 16, # 16x9
'height': 9 'height': 9
}, },
'The minimum allowed image resolution is {image_file_min_width}x{image_file_min_height}.'.format( 'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
) )
...@@ -727,7 +729,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): ...@@ -727,7 +729,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
'width': settings.VIDEO_IMAGE_MIN_WIDTH - 10, 'width': settings.VIDEO_IMAGE_MIN_WIDTH - 10,
'height': settings.VIDEO_IMAGE_MIN_HEIGHT 'height': settings.VIDEO_IMAGE_MIN_HEIGHT
}, },
'The minimum allowed image resolution is {image_file_min_width}x{image_file_min_height}.'.format( 'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
) )
...@@ -737,7 +741,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): ...@@ -737,7 +741,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
'width': settings.VIDEO_IMAGE_MIN_WIDTH, 'width': settings.VIDEO_IMAGE_MIN_WIDTH,
'height': settings.VIDEO_IMAGE_MIN_HEIGHT - 10 'height': settings.VIDEO_IMAGE_MIN_HEIGHT - 10
}, },
'The minimum allowed image resolution is {image_file_min_width}x{image_file_min_height}.'.format( 'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
) )
...@@ -747,7 +753,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): ...@@ -747,7 +753,9 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
'width': 1200, # not 16:9, but width/height check first. 'width': 1200, # not 16:9, but width/height check first.
'height': 100 'height': 100
}, },
'The minimum allowed image resolution is {image_file_min_width}x{image_file_min_height}.'.format( 'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
) )
......
...@@ -187,7 +187,10 @@ def validate_video_image(image_file): ...@@ -187,7 +187,10 @@ def validate_video_image(image_file):
return _('This image file is corrupted.') return _('This image file is corrupted.')
image_file_aspect_ratio = abs(image_file_width / float(image_file_height) - settings.VIDEO_IMAGE_ASPECT_RATIO) image_file_aspect_ratio = abs(image_file_width / float(image_file_height) - settings.VIDEO_IMAGE_ASPECT_RATIO)
if image_file_width < settings.VIDEO_IMAGE_MIN_WIDTH or image_file_height < settings.VIDEO_IMAGE_MIN_HEIGHT: if image_file_width < settings.VIDEO_IMAGE_MIN_WIDTH or image_file_height < settings.VIDEO_IMAGE_MIN_HEIGHT:
error = _('The minimum allowed image resolution is {image_file_min_width}x{image_file_min_height}.').format( error = _('Recommended image resolution is {image_file_max_width}x{image_file_max_height}. '
'The minimum resolution is {image_file_min_width}x{image_file_min_height}.').format(
image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH,
image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT,
image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH,
image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT image_file_min_height=settings.VIDEO_IMAGE_MIN_HEIGHT
) )
......
...@@ -201,12 +201,12 @@ define( ...@@ -201,12 +201,12 @@ define(
AjaxHelpers.respondWithError(requests, 400); AjaxHelpers.respondWithError(requests, 400);
verifyStateInfo($thumbnail, 'error'); verifyStateInfo($thumbnail, 'edit');
}); });
it('calls readMessage with correct message', function() { it('calls readMessage with correct message', function() {
var errorMessage = 'This image file type is not supported. Supported file types are ' + var errorMessage = 'Image upload failed. This image file type is not supported. Supported file ' +
videoThumbnailView.getVideoImageSupportedFileFormats().humanize + '.', 'types are ' + videoThumbnailView.getVideoImageSupportedFileFormats().humanize + '.',
successData = { successData = {
files: [createFakeImageFile()], files: [createFakeImageFile()],
submit: function() {} submit: function() {}
...@@ -255,7 +255,7 @@ define( ...@@ -255,7 +255,7 @@ define(
// Verify error message // Verify error message
expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html() expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html()
.trim()).toEqual( .trim()).toEqual(
'The selected image must be larger than ' + 'Image upload failed. The selected image must be larger than ' +
videoThumbnailView.getVideoImageMinSize().humanize + '.' videoThumbnailView.getVideoImageMinSize().humanize + '.'
); );
}); });
...@@ -270,7 +270,7 @@ define( ...@@ -270,7 +270,7 @@ define(
// Verify error message // Verify error message
expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html() expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html()
.trim()).toEqual( .trim()).toEqual(
'The selected image must be smaller than ' + 'Image upload failed. The selected image must be smaller than ' +
videoThumbnailView.getVideoImageMaxSize().humanize + '.' videoThumbnailView.getVideoImageMaxSize().humanize + '.'
); );
}); });
...@@ -307,7 +307,7 @@ define( ...@@ -307,7 +307,7 @@ define(
// Verify error message // Verify error message
expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html() expect($videoListEl.find('.thumbnail-error-wrapper').find('.action-text').html()
.trim()).toEqual( .trim()).toEqual(
'This image file type is not supported. Supported file types are ' + 'Image upload failed. This image file type is not supported. Supported file types are ' +
videoThumbnailView.getVideoImageSupportedFileFormats().humanize + '.' videoThumbnailView.getVideoImageSupportedFileFormats().humanize + '.'
); );
}); });
......
...@@ -26,26 +26,42 @@ define( ...@@ -26,26 +26,42 @@ define(
this.videoImageSettings = options.videoImageSettings; this.videoImageSettings = options.videoImageSettings;
this.actionsInfo = { this.actionsInfo = {
upload: { upload: {
name: 'upload',
icon: '', icon: '',
text: gettext('Add Thumbnail') text: gettext('Add Thumbnail')
}, },
edit: { edit: {
name: 'edit',
actionText: gettext('Edit Thumbnail'),
icon: '<span class="icon fa fa-pencil" aria-hidden="true"></span>', icon: '<span class="icon fa fa-pencil" aria-hidden="true"></span>',
text: gettext('Edit Thumbnail') text: HtmlUtils.interpolateHtml(
// Translators: This is a 2 part text which tells the image requirements.
gettext('{InstructionsSpanStart}{videoImageResoultion}{lineBreak} {videoImageSupportedFileFormats}{spanEnd}'), // eslint-disable-line max-len
{
videoImageResoultion: this.getVideoImageResolution(),
videoImageSupportedFileFormats: this.getVideoImageSupportedFileFormats().humanize,
lineBreak: HtmlUtils.HTML('<br>'),
InstructionsSpanStart: HtmlUtils.HTML('<span class="requirements-instructions">'),
spanEnd: HtmlUtils.HTML('</span>')
}
).toString()
}, },
error: { error: {
name: 'error',
icon: '', icon: '',
text: gettext('Image upload failed') text: gettext('Image upload failed')
}, },
progress: { progress: {
name: 'progress-action',
icon: '<span class="icon fa fa-spinner fa-pulse fa-spin" aria-hidden="true"></span>', icon: '<span class="icon fa fa-spinner fa-pulse fa-spin" aria-hidden="true"></span>',
text: gettext('Uploading') text: gettext('Uploading')
}, },
requirements: { requirements: {
name: 'requirements',
icon: '', icon: '',
text: HtmlUtils.interpolateHtml( text: HtmlUtils.interpolateHtml(
// Translators: This is a 3 part text which tells the image requirements. // Translators: This is a 3 part text which tells the image requirements.
gettext('{ReqTextSpanStart}Image requirements{spanEnd}{lineBreak}{InstructionsSpanStart}{videoImageResoultion}{lineBreak} {videoImageSupportedFileFormats}{spanEnd}'), // eslint-disable-line max-len gettext('{ReqTextSpanStart}Requirements{spanEnd}{lineBreak}{InstructionsSpanStart}{videoImageResoultion}{lineBreak} {videoImageSupportedFileFormats}{spanEnd}'), // eslint-disable-line max-len
{ {
videoImageResoultion: this.getVideoImageResolution(), videoImageResoultion: this.getVideoImageResolution(),
videoImageSupportedFileFormats: this.getVideoImageSupportedFileFormats().humanize, videoImageSupportedFileFormats: this.getVideoImageSupportedFileFormats().humanize,
...@@ -259,26 +275,40 @@ define( ...@@ -259,26 +275,40 @@ define(
}, },
setActionInfo: function(action, showText, additionalSRText) { setActionInfo: function(action, showText, additionalSRText) {
var hasError = this.$('.thumbnail-wrapper').hasClass('error');
this.$('.thumbnail-action').toggle(showText); this.$('.thumbnail-action').toggle(showText);
HtmlUtils.setHtml(
// In case of error, we don't want to show any icon on the image. this.$('.thumbnail-action .action-icon'),
if (action === 'error') { HtmlUtils.HTML(this.actionsInfo[action].icon)
HtmlUtils.setHtml( );
this.$('.thumbnail-action .action-icon'),
HtmlUtils.HTML('')
);
} else {
HtmlUtils.setHtml(
this.$('.thumbnail-action .action-icon'),
HtmlUtils.HTML(this.actionsInfo[action].icon)
);
}
HtmlUtils.setHtml( HtmlUtils.setHtml(
this.$('.thumbnail-action .action-text'), this.$('.thumbnail-action .action-text'),
HtmlUtils.HTML(this.actionsInfo[action].text) HtmlUtils.HTML(this.actionsInfo[action].text)
); );
this.$('.thumbnail-action .action-text-sr').text(additionalSRText || ''); this.$('.thumbnail-action .action-text-sr').text(additionalSRText || '');
this.$('.thumbnail-wrapper').attr('class', 'thumbnail-wrapper {action}'.replace('{action}', action)); this.$('.thumbnail-wrapper').attr('class', 'thumbnail-wrapper {action}'.replace('{action}', action));
this.$('.thumbnail-action .action-icon')
.attr('class', 'action-icon {action}'.replace('{action}', action));
// Add error class if it was already present.
if (hasError) {
this.$('.thumbnail-wrapper').addClass('error');
}
// Don't show edit-container layout on progress action.
if (action === 'progress') {
this.$('.thumbnail-action .edit-container').toggle(false);
} else if (action === 'edit') {
this.$('.thumbnail-action .edit-container').toggle(true);
HtmlUtils.setHtml(
this.$('.thumbnail-action .edit-container .action-icon'),
HtmlUtils.HTML(this.actionsInfo[action].icon)
);
HtmlUtils.setHtml(
this.$('.thumbnail-action .edit-container .edit-action-text'),
HtmlUtils.HTML(this.actionsInfo[action].actionText)
);
}
}, },
validateImageFile: function(imageFile) { validateImageFile: function(imageFile) {
...@@ -320,22 +350,29 @@ define( ...@@ -320,22 +350,29 @@ define(
if ($thumbnailWrapperEl.length) { if ($thumbnailWrapperEl.length) {
$thumbnailWrapperEl.remove(); $thumbnailWrapperEl.remove();
} }
// Remove error class from thumbnail wrapper as well.
$('.thumbnail-wrapper').removeClass('error');
}, },
showErrorMessage: function(errorText) { showErrorMessage: function(errorText) {
var videoId = this.model.get('edx_video_id'), var videoId = this.model.get('edx_video_id'),
$parentRowEl = $(this.$el.parent()); $parentRowEl = $(this.$el.parent());
this.action = 'error'; // If image url is not this.defaultVideoImageURL then it means image is uploaded
// so we should treat it as edit action otherwise default upload action.
this.action = this.$('.thumbnail-wrapper img').attr('src') !== this.defaultVideoImageURL
? 'edit' : 'upload';
this.setActionInfo(this.action, true); this.setActionInfo(this.action, true);
this.readMessages([gettext('Could not upload the video image file'), errorText]); this.readMessages([gettext('Could not upload the video image file'), errorText]);
errorText = gettext('Image upload failed. ') + errorText; // eslint-disable-line no-param-reassign
// Add error wrapper html to current video element row. // Add error wrapper html to current video element row.
$parentRowEl.before( // safe-lint: disable=javascript-jquery-insertion $parentRowEl.before( // xss-lint: disable=javascript-jquery-insertion
HtmlUtils.ensureHtml( HtmlUtils.ensureHtml(
this.thumbnailErrorTemplate({videoId: videoId, errorText: errorText}) this.thumbnailErrorTemplate({videoId: videoId, errorText: errorText})
).toString() ).toString()
); );
this.$el.find('.thumbnail-wrapper').addClass('error');
}, },
readMessages: function(messages) { readMessages: function(messages) {
......
...@@ -179,23 +179,15 @@ ...@@ -179,23 +179,15 @@
display: table-cell; display: table-cell;
} }
.thumbnail-col {
width: 15%;
}
.name-col { .name-col {
width: 25%; width: 25%;
} }
.date-col { .thumbnail-col, .video-id-col {
width: 10%;
}
.video-id-col {
width: 15%; width: 15%;
} }
.status-col { .date-col, .status-col {
width: 10%; width: 10%;
} }
...@@ -203,20 +195,18 @@ ...@@ -203,20 +195,18 @@
width: 5%; width: 5%;
} }
.video-head-col.thumbnail-col {
width: 17% !important;
}
} }
} }
.thumbnail-error-wrapper { .thumbnail-error-wrapper {
display: table-row; display: table-row;
white-space: nowrap; white-space: nowrap;
color: $red;
.thumbnail-error-text { .icon {
color: $red; margin: ($baseline*0.75) ($baseline/4) 0 ($baseline/2);
padding: 10px 10px 0;
.action-text {
margin-left: 5px;
}
} }
} }
...@@ -250,7 +240,7 @@ ...@@ -250,7 +240,7 @@
font-size: 15px; font-size: 15px;
font-family: "Open Sans"; font-family: "Open Sans";
text-align: left; text-align: left;
color: #4c4c4c; color: $gray-d2;
line-height: 1.5; line-height: 1.5;
} }
.video-duration { .video-duration {
...@@ -271,7 +261,6 @@ ...@@ -271,7 +261,6 @@
} }
} }
&.error,
&.progress { &.progress {
background: white; background: white;
...@@ -285,10 +274,6 @@ ...@@ -285,10 +274,6 @@
} }
} }
&.error .thumbnail-action {
color: $red;
}
&.upload .thumbnail-action { &.upload .thumbnail-action {
color: $blue; color: $blue;
} }
...@@ -299,10 +284,24 @@ ...@@ -299,10 +284,24 @@
} }
} }
&.edit .thumbnail-action { &.edit {
background-color: white; background-color: #4e4e4e;
}
&.edit .thumbnail-action .action-icon.edit {
display: none;
}
&.edit .thumbnail-action .edit-container {
background-color: $white;
padding: ($baseline/4); padding: ($baseline/4);
border-radius: ($baseline/5); border-radius: ($baseline/5);
margin-top: ($baseline/2);
display: none;
}
&.edit .action-text {
color: $white;
} }
.thumbnail-action { .thumbnail-action {
...@@ -316,6 +315,7 @@ ...@@ -316,6 +315,7 @@
left: 5px;; left: 5px;;
right: 5px; right: 5px;
@include transform(translateY(-50%)); @include transform(translateY(-50%));
z-index: 1;
} }
.upload-image-input { .upload-image-input {
...@@ -344,5 +344,9 @@ ...@@ -344,5 +344,9 @@
&.focused { &.focused {
box-shadow: 0 0 ($baseline/5) 1px $blue; box-shadow: 0 0 ($baseline/5) 1px $blue;
} }
&.error {
box-shadow: 0 0 ($baseline/5) 1px $red;
}
} }
} }
<div class="thumbnail-error-wrapper thumbnail-error" data-video-id="<%- videoId %>"> <div class="thumbnail-error-wrapper thumbnail-error" data-video-id="<%- videoId %>">
<div class="thumbnail-error-text"> <span class="icon fa fa-exclamation-triangle" aria-hidden="true"></span>
<span class="action-icon" aria-hidden="true"> <span class="action-text"><%- errorText %></span>
<span class="icon fa fa-exclamation-triangle" aria-hidden="true"></span>
</span>
<span class="action-text"><%- errorText %></span>
</div>
</div> </div>
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
<div class="thumbnail-overlay"> <div class="thumbnail-overlay">
<input id="thumb-<%- videoId %>" class="upload-image-input" type="file" name="file" accept=".bmp, .jpg, .jpeg, .png, .gif"/> <input id="thumb-<%- videoId %>" class="upload-image-input" type="file" name="file" accept=".bmp, .jpg, .jpeg, .png, .gif"/>
<label for="thumb-<%- videoId %>" class="thumbnail-action"> <label for="thumb-<%- videoId %>" class="thumbnail-action">
<span class="action-icon" aria-hidden="true"><%- actionInfo.icon %></span> <span class="main-icon action-icon <%- actionInfo.name %>" aria-hidden="true"><%- actionInfo.icon %></span>
<span class="action-text-sr sr"></span> <span class="action-text-sr sr"></span>
<span class="action-text"><%- actionInfo.text %></span> <span class="action-text"><%- actionInfo.text %></span>
<div class="edit-container">
<span class="action-icon" aria-hidden="true"><%- actionInfo.icon %></span>
<span class="edit-action-text"><%- actionInfo.actionText %></span>
</div>
</label> </label>
<span class="requirements-text-sr sr"> <span class="requirements-text-sr sr">
......
...@@ -77,7 +77,7 @@ git+https://github.com/edx/lettuce.git@0.2.20.002#egg=lettuce==0.2.20.002 ...@@ -77,7 +77,7 @@ git+https://github.com/edx/lettuce.git@0.2.20.002#egg=lettuce==0.2.20.002
git+https://github.com/edx/edx-ora2.git@1.4.3#egg=ora2==1.4.3 git+https://github.com/edx/edx-ora2.git@1.4.3#egg=ora2==1.4.3
-e git+https://github.com/edx/edx-submissions.git@2.0.0#egg=edx-submissions==2.0.0 -e git+https://github.com/edx/edx-submissions.git@2.0.0#egg=edx-submissions==2.0.0
git+https://github.com/edx/ease.git@release-2015-07-14#egg=ease==0.1.3 git+https://github.com/edx/ease.git@release-2015-07-14#egg=ease==0.1.3
git+https://github.com/edx/edx-val.git@0.0.15#egg=edxval==0.0.15 git+https://github.com/edx/edx-val.git@ammar/auto-generated-images-fixes
git+https://github.com/pmitros/RecommenderXBlock.git@v1.2#egg=recommender-xblock==1.2 git+https://github.com/pmitros/RecommenderXBlock.git@v1.2#egg=recommender-xblock==1.2
git+https://github.com/solashirai/crowdsourcehinter.git@518605f0a95190949fe77bd39158450639e2e1dc#egg=crowdsourcehinter-xblock==0.1 git+https://github.com/solashirai/crowdsourcehinter.git@518605f0a95190949fe77bd39158450639e2e1dc#egg=crowdsourcehinter-xblock==0.1
-e git+https://github.com/pmitros/RateXBlock.git@367e19c0f6eac8a5f002fd0f1559555f8e74bfff#egg=rate-xblock -e git+https://github.com/pmitros/RateXBlock.git@367e19c0f6eac8a5f002fd0f1559555f8e74bfff#egg=rate-xblock
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment