diff --git a/app/assets/javascripts/thyme/annotations/annotation.js b/app/assets/javascripts/thyme/annotations/annotation.js index c13e901e2..348bb80d3 100644 --- a/app/assets/javascripts/thyme/annotations/annotation.js +++ b/app/assets/javascripts/thyme/annotations/annotation.js @@ -82,7 +82,7 @@ class Annotation { categoryLocale() { const c = this.category; const s = this.subcategory; - return s == null ? c.locale() : c.locale() + " (" + s.locale() + ")"; + return s ? c.locale() + " (" + s.locale() + ")" : c.locale(); } /* diff --git a/app/assets/javascripts/thyme/annotations/annotation_area.js b/app/assets/javascripts/thyme/annotations/annotation_area.js index 149a6f52d..fcaf1bfa6 100644 --- a/app/assets/javascripts/thyme/annotations/annotation_area.js +++ b/app/assets/javascripts/thyme/annotations/annotation_area.js @@ -69,7 +69,7 @@ class AnnotationArea { Update the annotation area with the content of the given annotation. */ update(annotation) { - if (annotation == null) { + if (!annotation) { return; } this.annotation = annotation; diff --git a/app/assets/javascripts/thyme/annotations/annotation_manager.js b/app/assets/javascripts/thyme/annotations/annotation_manager.js index 3e5ab05d0..e269d740d 100644 --- a/app/assets/javascripts/thyme/annotations/annotation_manager.js +++ b/app/assets/javascripts/thyme/annotations/annotation_manager.js @@ -61,7 +61,7 @@ class AnnotationManager { function onClick() { annotationManager.onClick(a); } - if (this.sizeFunc !== null && this.sizeFunc(a)) { + if (this.sizeFunc && this.sizeFunc(a)) { a.createBigMarker(this.colorFunc(a), this.strokeColorFunc(a), onClick); } else { a.createMarker(this.colorFunc(a), this.strokeColorFunc(a), onClick); @@ -81,6 +81,10 @@ class AnnotationManager { successfully updated. */ updateAnnotations() { + if (!thymeAttributes.annotationFeatureActive) { + return; + } + this.isDbCalledForFreshAnnotations = true; // Lock resource const manager = this; @@ -114,7 +118,7 @@ class AnnotationManager { if (!thymeAttributes.annotations) { return; } - thymeAttributes.annotations.sort(function(ann1, ann2) { + thymeAttributes.annotations.sort(function (ann1, ann2) { return ann1.seconds - ann2.seconds; }); } @@ -125,7 +129,7 @@ class AnnotationManager { */ static find(id) { const annotations = thymeAttributes.annotations; - if (annotations == null) { + if (!annotations) { return null; } for (let a of annotations) { @@ -142,7 +146,7 @@ class AnnotationManager { */ static findIndex(id) { const annotations = thymeAttributes.annotations; - if (annotations == null) { + if (!annotations) { return undefined; } for (let i = 0; i < annotations.length; i++) { diff --git a/app/assets/javascripts/thyme/attributes.js b/app/assets/javascripts/thyme/attributes.js index 85207f8ed..3882d4a5b 100644 --- a/app/assets/javascripts/thyme/attributes.js +++ b/app/assets/javascripts/thyme/attributes.js @@ -10,6 +10,9 @@ const thymeAttributes = { /* Saves a reference on the annotation area. */ annotationArea: null, + /* Use this to check if the annotation feature is activated. */ + annotationFeatureActive: false, + /* When callig the updateMarkers() method this will be used to save an array containing all annotations. */ annotations: null, diff --git a/app/assets/javascripts/thyme/components/annotations_toggle.js b/app/assets/javascripts/thyme/components/annotations_toggle.js index 684e990b1..4e9b868dc 100644 --- a/app/assets/javascripts/thyme/components/annotations_toggle.js +++ b/app/assets/javascripts/thyme/components/annotations_toggle.js @@ -11,7 +11,11 @@ class AnnotationsToggle extends Component { add() { const toggle = this; const $check = this.$check; - + + if (!thymeAttributes.annotationFeatureActive) { + return; + } + /* User is teacher/editor for the given medium and visible_for_teacher ist activated? -> add toggle annotations button */ $.ajax(Routes.check_annotation_visibility_path(thymeAttributes.mediumId), { diff --git a/app/assets/javascripts/thyme/components/full_screen_button.js b/app/assets/javascripts/thyme/components/full_screen_button.js index 30fa04e30..8575dd7f4 100644 --- a/app/assets/javascripts/thyme/components/full_screen_button.js +++ b/app/assets/javascripts/thyme/components/full_screen_button.js @@ -46,7 +46,7 @@ class FullScreenButton extends Component { } #fullscreenChange() { - if (document.fullscreenElement !== null) { + if (document.fullscreenElement) { this.element.innerHTML = 'fullscreen_exit'; this.element.dataset.status = 'true'; /* Set height to 100vh in fullscreen mode as it otherwise diff --git a/app/assets/javascripts/thyme/components/ia_back_button.js b/app/assets/javascripts/thyme/components/ia_back_button.js index d75b958cd..0de777ac4 100644 --- a/app/assets/javascripts/thyme/components/ia_back_button.js +++ b/app/assets/javascripts/thyme/components/ia_back_button.js @@ -26,7 +26,7 @@ class IaBackButton extends Component { const currentChapter = $('#' + this.chapterListId + ' .current'); if (currentChapter.length > 0) { let backInfo = currentChapter.data('text').split(':', 1)[0]; - if ((backInfo != null) && backInfo.length > 20) { + if (backInfo && backInfo.length > 20) { backInfo = this.element.dataset.back; } else { backInfo = this.element.dataset.backto + backInfo; diff --git a/app/assets/javascripts/thyme/components/ia_button.js b/app/assets/javascripts/thyme/components/ia_button.js index 429b47c92..542274acf 100644 --- a/app/assets/javascripts/thyme/components/ia_button.js +++ b/app/assets/javascripts/thyme/components/ia_button.js @@ -6,18 +6,18 @@ class IaButton extends Component { /* - toHide = An array consisting of all the components that - should be hidden/shown when this button is clicked. - These components must provide a show() and hide() - method, but they havn't to be a JQuery reference - on a HTML element. + toHide = An array consisting of all the components that + should be hidden/shown when this button is clicked. + These components must provide a show() and hide() + method, but they havn't to be a JQuery reference + on a HTML element. - toShrink = An array consisting of JQuery references of all - the components that should grow/shrink when this - button is clicked. + toShrink = An array consisting of JQuery references of all + the components that should grow/shrink when this + button is clicked. - shrink = The percentage telling how much the elements of toShrink - should shrink when the components of toHide are shown. + shrink = The percentage telling how much the elements of toShrink + should shrink when the components of toHide are shown. */ constructor(element, toHide, toShrink, shrink) { super(element); @@ -27,10 +27,8 @@ class IaButton extends Component { } add() { - const video = thymeAttributes.video; const element = this.element; const button = this; - const shrink = this.shrink; element.addEventListener('click', function() { if (element.dataset.status === 'true') { @@ -46,16 +44,7 @@ class IaButton extends Component { toHide elements and shrinks all toShrink elements. */ plus() { - this.element.dataset.status = 'false'; - this.element.innerHTML = 'remove_from_queue'; - for (let e of this.toHide) { - e.hide(); - } - for (let e of this.toShrink) { - e.css('width', '100%'); - } - $(window).trigger('resize'); - thymeAttributes.annotationManager.updateMarkers(); + this.#aux('false', 'remove_from_queue', false, '100%'); } /* @@ -63,20 +52,26 @@ class IaButton extends Component { toHide elements and enlarges all toShrink elements. */ minus() { - this.element.dataset.status = 'true'; - this.element.innerHTML = 'add_to_queue'; + this.#aux('true', 'add_to_queue', true, this.shrink); + } + + getStatus() { + return this.element.dataset.status === 'true'; + } + + + + #aux(status, innerHTML, sh, size) { + this.element.dataset.status = status; + this.element.innerHTML = innerHTML; for (let e of this.toHide) { - e.show(); + sh ? e.show() : e.hide(); } for (let e of this.toShrink) { - e.css('width', this.shrink); + e.css('width', size); } $(window).trigger('resize'); thymeAttributes.annotationManager.updateMarkers(); } - getStatus() { - return this.element.dataset.status === 'true'; - } - } diff --git a/app/assets/javascripts/thyme/components/next_chapter_button (Kopie).js b/app/assets/javascripts/thyme/components/next_chapter_button (Kopie).js deleted file mode 100644 index 7e4db886e..000000000 --- a/app/assets/javascripts/thyme/components/next_chapter_button (Kopie).js +++ /dev/null @@ -1,16 +0,0 @@ -class NextChapterButton extends Component { - - add() { - const video = thymeAttributes.video; - const element = this.element; - - // Event handler for the nextChapter button - element.addEventListener('click', function() { - const next = thymeAttributes.chapterManager.nextChapterStart(); - if (next != null) { - video.currentTime = thymeAttributes.chapterManager.nextChapterStart(); - } - }); - } - -} diff --git a/app/assets/javascripts/thyme/components/next_chapter_button.js b/app/assets/javascripts/thyme/components/next_chapter_button.js index 7e4db886e..977fc8e09 100644 --- a/app/assets/javascripts/thyme/components/next_chapter_button.js +++ b/app/assets/javascripts/thyme/components/next_chapter_button.js @@ -7,7 +7,7 @@ class NextChapterButton extends Component { // Event handler for the nextChapter button element.addEventListener('click', function() { const next = thymeAttributes.chapterManager.nextChapterStart(); - if (next != null) { + if (next) { video.currentTime = thymeAttributes.chapterManager.nextChapterStart(); } }); diff --git a/app/assets/javascripts/thyme/components/previous_chapter_button.js b/app/assets/javascripts/thyme/components/previous_chapter_button.js index 3cde02063..6d778a1b4 100644 --- a/app/assets/javascripts/thyme/components/previous_chapter_button.js +++ b/app/assets/javascripts/thyme/components/previous_chapter_button.js @@ -7,7 +7,7 @@ class PreviousChapterButton extends Component { // Event handler for the previousChapter button element.addEventListener('click', function() { const previous = thymeAttributes.chapterManager.previousChapterStart(); - if (previous != null) { + if (previous) { video.currentTime = thymeAttributes.chapterManager.previousChapterStart(); } }); diff --git a/app/assets/javascripts/thyme/components/seek_bar.js b/app/assets/javascripts/thyme/components/seek_bar.js index f2b9b8912..aca8efd19 100644 --- a/app/assets/javascripts/thyme/components/seek_bar.js +++ b/app/assets/javascripts/thyme/components/seek_bar.js @@ -17,7 +17,7 @@ class SeekBar extends Component { // if videomedtadata have been loaded, set up seek bar video.addEventListener('loadedmetadata', function() { - if (video.dataset.time != null) { + if (video.dataset.time) { const time = video.dataset.time; element.value = video.currentTime / video.duration * 100; } else { diff --git a/app/assets/javascripts/thyme/components/speed_selector.js b/app/assets/javascripts/thyme/components/speed_selector.js index 4bab67024..743902101 100644 --- a/app/assets/javascripts/thyme/components/speed_selector.js +++ b/app/assets/javascripts/thyme/components/speed_selector.js @@ -11,11 +11,11 @@ class SpeedSelector extends Component { const element = this.element; element.addEventListener('click', function() { - if (video.preservesPitch != null) { + if (video.preservesPitch) { video.preservesPitch = true; - } else if (video.mozPreservesPitch != null) { + } else if (video.mozPreservesPitch) { video.mozPreservesPitch = true; - } else if (video.webkitPreservesPitch != null) { + } else if (video.webkitPreservesPitch) { video.webkitPreservesPitch = true; } video.playbackRate = this.options[this.selectedIndex].value; diff --git a/app/assets/javascripts/thyme/heatmap.js b/app/assets/javascripts/thyme/heatmap.js index 7f9338f88..0dfbc7f3e 100644 --- a/app/assets/javascripts/thyme/heatmap.js +++ b/app/assets/javascripts/thyme/heatmap.js @@ -18,7 +18,7 @@ class Heatmap { draw() { - if (thymeAttributes.annotations == null) { + if (!thymeAttributes.annotations) { return; } this.heatmap.empty(); diff --git a/app/assets/javascripts/thyme/thyme_feedback.js b/app/assets/javascripts/thyme/thyme_feedback.js index 3f4e5e326..f3835026c 100644 --- a/app/assets/javascripts/thyme/thyme_feedback.js +++ b/app/assets/javascripts/thyme/thyme_feedback.js @@ -61,6 +61,7 @@ $(document).on('turbolinks:load', function() { function colorFunc(annotation) { return annotation.category.color; } + function isValid(annotation) { for (let toggle of annotationCategoryToggles) { if (annotation.category === toggle.category && toggle.getValue()) { @@ -69,20 +70,26 @@ $(document).on('turbolinks:load', function() { } return false; } + const annotationArea = new AnnotationArea(false, colorFunc, null, isValid); thymeAttributes.annotationArea = annotationArea; + function strokeColorFunc(annotation) { return annotation.category === Category.MISTAKE ? 'darkred' : 'black'; } + function sizeFunc(annotation) { return annotation.category === Category.MISTAKE; } + function onClick(annotation) { annotationArea.update(annotation); } + function onUpdate() { heatmap.draw(); } + const annotationManager = new AnnotationManager(colorFunc, strokeColorFunc, sizeFunc, onClick, onUpdate, isValid); thymeAttributes.annotationManager = annotationManager; @@ -108,6 +115,7 @@ $(document).on('turbolinks:load', function() { resize.resizeContainer(thymeContainer, 1.22, 70); annotationManager.updateMarkers(); }; + window.onresize = resizeContainer; video.onloadedmetadata = resizeContainer; diff --git a/app/assets/javascripts/thyme/thyme_player.js b/app/assets/javascripts/thyme/thyme_player.js index 07c3c2cb3..7a80c6f26 100644 --- a/app/assets/javascripts/thyme/thyme_player.js +++ b/app/assets/javascripts/thyme/thyme_player.js @@ -20,13 +20,19 @@ $(document).on('turbolinks:load', function() { - /* COMPONENTS */ + // annotation components + const annotationFeatureActive = (document.getElementById('annotation-button') != null); + thymeAttributes.annotationFeatureActive = annotationFeatureActive; + if (annotationFeatureActive) { + (new AnnotationButton('annotation-button')).add(); + } const annotationsToggle = new AnnotationsToggle('annotations-toggle'); annotationsToggle.add(); - (new AnnotationButton('annotation-button')).add(); + + // regular components (new FullScreenButton('full-screen', thymeContainer)).add(); (new MuteButton('mute')).add(); (new NextChapterButton('next-chapter')).add(); @@ -52,35 +58,43 @@ $(document).on('turbolinks:load', function() { function colorFunc(annotation) { return annotation.color; } + function onClose() { iaButton.minus(); } + function isValid(annotation) { return (!annotationsToggle.getValue() && !annotation.belongsToCurrentUser ? false : true); } + const annotationArea = new AnnotationArea(true, colorFunc, onClose, isValid); thymeAttributes.annotationArea = annotationArea; + function strokeColorFunc(annotation) { return 'black'; } + function sizeFunc(annotation) { return false; } + function onClick(annotation) { iaButton.minus(); annotationArea.update(annotation); annotationArea.show(); $('#caption').hide(); } + function onUpdate() { /* update might change the annotation which is currently shown in the annotation area -> find the updated annotation in the annotation array and update the area. */ - if (annotationArea.annotation != null) { + if (annotationArea.annotation) { const id = annotationArea.annotation.id; annotationArea.update(AnnotationManager.find(id)); } } + const annotationManager = new AnnotationManager(colorFunc, strokeColorFunc, sizeFunc, onClick, onUpdate, isValid); thymeAttributes.annotationManager = annotationManager; @@ -144,6 +158,7 @@ $(document).on('turbolinks:load', function() { function onEnlarge() { iaButton.plus(); } + const elements = [$('#caption'), $('#annotation-caption'), $('#video-controlBar')]; const displayManager = new DisplayManager(elements, onEnlarge); @@ -154,6 +169,7 @@ $(document).on('turbolinks:load', function() { resize.resizeContainer(thymeContainer, factor, 0); annotationManager.updateMarkers(); }; + window.onresize = resizeContainer; video.onloadedmetadata = resizeContainer; diff --git a/app/assets/javascripts/thyme/utility.js b/app/assets/javascripts/thyme/utility.js index 2ec0f45f0..88b46a59c 100644 --- a/app/assets/javascripts/thyme/utility.js +++ b/app/assets/javascripts/thyme/utility.js @@ -58,7 +58,7 @@ const thymeUtility = { /* Installs a listener which lets the video play/pause when clicked. */ - playOnClick() { + playOnClick: function() { const video = thymeAttributes.video; video.addEventListener('click', function() { if (video.paused) { @@ -112,12 +112,12 @@ const thymeUtility = { (In order to make this work, we have to wait for the video's metadata to be loaded.) */ - setUpMaxTime(maxTimeId) { + setUpMaxTime: function(maxTimeId) { const video = thymeAttributes.video; video.addEventListener('loadedmetadata', function() { const maxTime = document.getElementById(maxTimeId); maxTime.innerHTML = thymeUtility.secondsToTime(video.duration); - if (video.dataset.time != null) { + if (video.dataset.time) { const time = video.dataset.time; video.currentTime = time; } @@ -135,8 +135,8 @@ const thymeUtility = { Converts a given integer between 0 and 255 into a hexadecimal, s.t. e.g. "15" becomes "0f" (instead of just "f") -> needed for correct format. */ - toHexaDecimal: function(int) { - return int.toString(16).padStart(2, '0'); + toHexaDecimal: function(integer) { + return integer.toString(16).padStart(2, '0'); }, }; diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb index cb8f34a5d..4172525b6 100644 --- a/app/controllers/annotations_controller.rb +++ b/app/controllers/annotations_controller.rb @@ -34,15 +34,12 @@ def edit def create @annotation = Annotation.new(annotation_params) - return unless valid_color?(@annotation.color) - return if @annotation.category_for_database == Annotation.categories[:content] and - @annotation.subcategory.nil? - @annotation.public_comment_id = post_comment(@annotation) - @annotation.user_id = current_user.id @total_seconds = annotation_auxiliary_params[:total_seconds] @annotation.timestamp = TimeStamp.new(total_seconds: @total_seconds) + return unless create_and_update_shared(@annotation) + @annotation.save render :update end @@ -51,10 +48,7 @@ def update @annotation = Annotation.find(params[:id]) @annotation.assign_attributes(annotation_params) - return unless valid_color?(@annotation.color) - return if @annotation.category_for_database == Annotation.categories[:content] and - @annotation.subcategory.nil? - @annotation.public_comment_id = post_comment(@annotation) + return unless create_and_update_shared(@annotation) @annotation.save end @@ -115,17 +109,11 @@ def update_annotations end def num_nearby_posted_mistake_annotations - annotations = Annotation.where(medium: params[:mediumId]) + annotations = Annotation.where(medium: params[:mediumId], category: 'mistake').commented # the time (!) radius in which annotation are considered as "nearby" radius = params[:radius].to_i timestamp = params[:timestamp].to_i - counter = 0 - for annotation in annotations - next unless annotation.category == "mistake" && - (annotation.timestamp.total_seconds - timestamp).abs() < radius && - !annotation.public_comment_id.nil? - counter += 1 - end + counter = annotations.to_a.count { |annotation| annotation.nearby?(timestamp, radius) } render json: counter end @@ -153,11 +141,37 @@ def valid_color?(color) color&.match?(/\A#([0-9]|[A-F]){6}\z/) end + def valid_time?(annotation) + time = annotation.timestamp.total_seconds + time >= 0 and time <= annotation.medium.video["duration"] + end + + # checks that the subcategory is non-nil if the category is "content" and + # resets the subcategory to "nil" if the selected category isn't "content" + def subcategory_nil(annotation) + return if annotation.category_for_database == Annotation.categories[:content] and + annotation.subcategory.nil? + if annotation.category_for_database != Annotation.categories[:content] + annotation.subcategory = nil + end + return true + end + + # common code for the create and update method + def create_and_update_shared(annotation) + return unless valid_color?(annotation.color) and + valid_time?(annotation) and + subcategory_nil(annotation) + annotation.public_comment_id = post_comment(annotation) + return true + end + + # Run all the Commontator::Comment related code here def post_comment(annotation) public_comment_id = annotation.public_comment_id # return if checkbox "post_as_comment" is not checked and if there is no comment to update - return if annotation_auxiliary_params[:post_as_comment] != '1' && public_comment_id.nil? + return if annotation_auxiliary_params[:post_as_comment] != '1' and public_comment_id.nil? comment = annotation_params[:comment] @@ -166,9 +180,9 @@ def post_comment(annotation) commontator_comment = Commontator::Comment.create( thread: medium.commontator_thread, creator: current_user, - body: comment + body: comment, + annotation: annotation ) - commontator_comment.annotation = annotation else # comment already exists -> update it commontator_comment = Commontator::Comment.find_by(id: public_comment_id) commontator_comment.update(editor: current_user, diff --git a/app/controllers/lectures_controller.rb b/app/controllers/lectures_controller.rb index 946d171a3..54fa4dad4 100644 --- a/app/controllers/lectures_controller.rb +++ b/app/controllers/lectures_controller.rb @@ -35,6 +35,8 @@ def edit end def update + return unless @lecture.valid_annotations_status? + editor_ids = lecture_params[:editor_ids] if editor_ids != nil # removes the empty String "" in the NEW array of editor ids diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb index 9174711b2..5b00c2b5e 100644 --- a/app/controllers/media_controller.rb +++ b/app/controllers/media_controller.rb @@ -66,6 +66,8 @@ def update @errors = @medium.errors return unless @errors.empty? + return unless @medium.valid_annotations_status? + # make sure the medium is touched # (it will not be touched automatically in some cases (e.g. if you only # update the associated tags), causing trouble for caching) @@ -130,6 +132,9 @@ def update def create @medium = Medium.new(medium_params) + + return unless @medium.valid_annotations_status? + @medium.locale = @medium.teachable&.locale @medium.editors = [current_user] if @medium.teachable.class.to_s == 'Lesson' diff --git a/app/models/annotation.rb b/app/models/annotation.rb index 73147eb4f..645696d92 100644 --- a/app/models/annotation.rb +++ b/app/models/annotation.rb @@ -4,6 +4,8 @@ class Annotation < ApplicationRecord belongs_to :public_comment, class_name: 'Commontator::Comment', optional: true + scope :commented, -> { where.not(public_comment_id: nil) } + # the timestamp for the annotation position is serialized as text in the db serialize :timestamp, TimeStamp @@ -11,12 +13,12 @@ class Annotation < ApplicationRecord enum subcategory: { definition: 0, argument: 1, strategy: 2 } def get_comment - if self.public_comment_id.nil? - return self.comment - else - commontator_comment = Commontator::Comment.find_by(id: public_comment_id) - return commontator_comment.body - end + return self.comment if self.public_comment_id.nil? + commontator_comment = Commontator::Comment.find_by(id: public_comment_id).body + end + + def nearby?(other_timestamp, radius) + (timestamp.total_seconds - other_timestamp).abs() < radius end def self.colors diff --git a/app/models/lecture.rb b/app/models/lecture.rb index 9552b1461..51ce0e501 100644 --- a/app/models/lecture.rb +++ b/app/models/lecture.rb @@ -819,6 +819,12 @@ def stale? older_than?(1.year) end + def valid_annotations_status? + [-1, 1].include?(self.annotations_status) + end + + + private # used for after save callback @@ -922,4 +928,5 @@ def only_one_lecture errors.add(:course, :already_present) end + end diff --git a/app/models/medium.rb b/app/models/medium.rb index ac903bcee..3bb081a17 100644 --- a/app/models/medium.rb +++ b/app/models/medium.rb @@ -1125,19 +1125,29 @@ def subscribed_users Lecture.find_by(id: teachable.lecture_id).user_ids end - + + # Returns either the annotations status (1 = activated, -1 = deactivated) + # of this medium or the annotations status of the associated lecture + # if "inherit from lecture" was selected (i.e. if the annotations status of + # this medium is 0). def get_annotations_status return annotations_status if annotations_status != 0 lecture.annotations_status end - + def annotations_visible?(user) lecture = lesson.lecture unless lesson.nil? is_teacher = edited_with_inheritance_by?(user) is_activated = (get_annotations_status == 1) return is_teacher && is_activated end - + + def valid_annotations_status? + [-1, 0, 1].include?(self.annotations_status) + end + + + private # media of type kaviar associated to a lesson and script do not require @@ -1311,4 +1321,5 @@ def answers_count becomes(Question).answers.count end + end diff --git a/app/models/time_stamp.rb b/app/models/time_stamp.rb index 94d3c5d86..1924e36bb 100644 --- a/app/models/time_stamp.rb +++ b/app/models/time_stamp.rb @@ -5,7 +5,7 @@ class TimeStamp validates :milliseconds, presence: true attr_reader :hours, :minutes, :seconds, :milliseconds - + # extract from YAML def self.load(text) YAML.safe_load(text, permitted_classes: [TimeStamp, diff --git a/app/views/annotations/edit.js.erb b/app/views/annotations/edit.js.erb index 8d5fb1803..2bdd7ab7f 100644 --- a/app/views/annotations/edit.js.erb +++ b/app/views/annotations/edit.js.erb @@ -4,6 +4,7 @@ $('#annotation-modal').modal('show'); var submitButton = document.getElementById('annotation-modal-submit-button'); var postAsComment = document.getElementById('annotation_post_as_comment'); +var posted = <%= @posted %>; postAsComment.addEventListener('change', function() { if (this.checked) { @@ -179,6 +180,7 @@ function visibleForTeacher(boolean) { } function postComment(boolean) { + boolean = posted ? true : boolean; $('#annotation_post_as_comment').prop("checked", boolean); } @@ -239,7 +241,7 @@ previewToggle.addEventListener('change', function() { }); // disable post comment checkbox if annotation was already posted -if (<%= @posted %>) { +if (posted) { postComment(true); postAsComment.disabled = true; } diff --git a/app/views/media/play.html.erb b/app/views/media/play.html.erb index 9e53f981b..8c07891b4 100644 --- a/app/views/media/play.html.erb +++ b/app/views/media/play.html.erb @@ -62,11 +62,13 @@ -
+ <% if user_signed_in? %> + + <% end %> -<%= render partial: "annotations/annotation_modal" %> -<%= render partial: "annotations/annotation_locales" %> +<% if user_signed_in? %> + <%= render partial: "annotations/annotation_modal" %> + <%= render partial: "annotations/annotation_locales" %> +<% end %> \ No newline at end of file diff --git a/db/migrate/20230117124508_add_annotations_status_to_medium.rb b/db/migrate/20230117124508_add_annotations_status_to_medium.rb index ca48b67d7..6942012d0 100644 --- a/db/migrate/20230117124508_add_annotations_status_to_medium.rb +++ b/db/migrate/20230117124508_add_annotations_status_to_medium.rb @@ -1,5 +1,5 @@ class AddAnnotationsStatusToMedium < ActiveRecord::Migration[7.0] def change - add_column :media, :annotations_status, :integer, default: 0 + add_column :media, :annotations_status, :integer, default: 0, null: false end end diff --git a/db/migrate/20230117124528_add_annotations_status_to_lecture.rb b/db/migrate/20230117124528_add_annotations_status_to_lecture.rb index e829fcc1a..469ce474f 100644 --- a/db/migrate/20230117124528_add_annotations_status_to_lecture.rb +++ b/db/migrate/20230117124528_add_annotations_status_to_lecture.rb @@ -1,5 +1,5 @@ class AddAnnotationsStatusToLecture < ActiveRecord::Migration[7.0] def change - add_column :lectures, :annotations_status, :integer, default: -1 + add_column :lectures, :annotations_status, :integer, default: -1, null: false end end diff --git a/db/migrate/20231108164701_add_default_annotations_status_to_lecture_and_media.rb b/db/migrate/20231108164701_add_default_annotations_status_to_lecture_and_media.rb new file mode 100644 index 000000000..735c2e053 --- /dev/null +++ b/db/migrate/20231108164701_add_default_annotations_status_to_lecture_and_media.rb @@ -0,0 +1,6 @@ +class AddDefaultAnnotationsStatusToLectureAndMedia < ActiveRecord::Migration[7.0] + def change + Lecture.update_all(annotations_status: -1) + Medium.update_all(annotations_status: 0) + end +end diff --git a/db/schema.rb b/db/schema.rb index 34b39a078..dd43d1536 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_08_093848) do +ActiveRecord::Schema[7.0].define(version: 2023_11_08_164701) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql"