Skip to content

Commit

Permalink
[DONE] Feature/opencast studio v2 (#1005)
Browse files Browse the repository at this point in the history
* Uprage opencast-studio to be compliant with oc-studio v.2.0

* Apply Studio styles to render type added by Pod

* Dark Mode for Opencast studio

* render root statics Opencast files + add missing configs in settings_toml

* Rename view studio_root -> studio_root_file

* improve constrast on icon
  • Loading branch information
Badatos authored Nov 20, 2023
1 parent d9cab36 commit f51650f
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 87 deletions.
4 changes: 4 additions & 0 deletions pod/main/static/css/pod.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
--third-background-color: var(--pod-background-neutre1-bloc) !important;
}

.progress, .progress-stacked{
--bs-progress-bar-bg: var(--pod-primary);
}

:root[data-dyslexia="on"] {
--bs-body-font-family: var(--pod-font-family-dyslexie);
}
Expand Down
1 change: 1 addition & 0 deletions pod/main/templates/admin/base_site.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
// Set the body data-theme attribute to match the local storage item
document.documentElement.dataset.theme = currentTheme?currentTheme:"light";
document.documentElement.dataset.bsTheme = currentTheme?currentTheme:"light";
document.documentElement.dataset.colorScheme = currentTheme?currentTheme:"light";
</script>
{% endif %}

Expand Down
3 changes: 3 additions & 0 deletions pod/main/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ <h1 class="page_title">{{page_title|capfirst}}</h1>
// Set the body data-theme attribute to match the local storage item
document.documentElement.dataset.theme = currentTheme?currentTheme:"light";
document.documentElement.dataset.bsTheme = currentTheme?currentTheme:"light";
document.documentElement.dataset.colorScheme = currentTheme?currentTheme:"light";
// If the current theme is dark, check the theme toggle
if (currentTheme === "dark") {
themeToggle.checked = true;
Expand All @@ -236,10 +237,12 @@ <h1 class="page_title">{{page_title|capfirst}}</h1>
if (e.target.checked) {
document.documentElement.dataset.theme = "dark";
document.documentElement.dataset.bsTheme = "dark";
document.documentElement.dataset.colorScheme = "dark";
localStorage.setItem("theme", "dark");
} else {
document.documentElement.dataset.theme = "light";
document.documentElement.dataset.bsTheme = "light";
document.documentElement.dataset.colorScheme = "light";
localStorage.setItem("theme", "light");
}
}
Expand Down
56 changes: 14 additions & 42 deletions pod/playlist/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ class PlaylistFormTest(TestCase):

@override_settings(USE_PLAYLIST=True)
def test_valid_data_for_public_playlist(self):
"""
Test the form with valid data for a public playlist.
"""
"""Test the form with valid data for a public playlist."""
form = PlaylistForm(
data={
"name": "Test Playlist",
Expand All @@ -42,9 +40,7 @@ def test_valid_data_for_public_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_valid_data_for_private_playlist(self):
"""
Test the form with valid data for a private playlist.
"""
"""Test the form with valid data for a private playlist."""
form = PlaylistForm(
data={
"name": "Test Playlist",
Expand All @@ -60,9 +56,7 @@ def test_valid_data_for_private_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_valid_data_for_protected_playlist(self):
"""
Test the form with valid data for a protected playlist.
"""
"""Test the form with valid data for a protected playlist."""
form = PlaylistForm(
data={
"name": "Test Playlist",
Expand All @@ -78,9 +72,7 @@ def test_valid_data_for_protected_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_invalid_data_for_protected_playlist(self):
"""
Test the form with invalid data for a protected playlist.
"""
"""Test the form with invalid data for a protected playlist."""
form = PlaylistForm(
data={
"name": "Test Playlist",
Expand All @@ -96,9 +88,7 @@ def test_invalid_data_for_protected_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_name_validation_for_public_playlist(self):
"""
Test if the name validation works correctly for a public playlist.
"""
"""Test if the name validation works correctly for a public playlist."""
valid_form = PlaylistForm(
data={
"name": "Valid Name",
Expand All @@ -121,9 +111,7 @@ def test_name_validation_for_public_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_name_validation_for_private_playlist(self):
"""
Test if the name validation works correctly for a private playlist.
"""
"""Test if the name validation works correctly for a private playlist."""
valid_form = PlaylistForm(
data={
"name": "Valid Name",
Expand All @@ -146,9 +134,7 @@ def test_name_validation_for_private_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_name_validation_for_protected_playlist(self):
"""
Test if the name validation works correctly for a protected playlist.
"""
"""Test if the name validation works correctly for a protected playlist."""
valid_form = PlaylistForm(
data={
"name": "Valid Name",
Expand All @@ -173,9 +159,7 @@ def test_name_validation_for_protected_playlist(self):

@override_settings(USE_PLAYLIST=True)
def test_blank_data_for_public_playlist(self):
"""
Test the form with blank data for a public playlist.
"""
"""Test the form with blank data for a public playlist."""
form = PlaylistForm(data={})
self.assertFalse(form.is_valid())
self.assertLessEqual(1, len(form.errors))
Expand All @@ -192,18 +176,14 @@ class PlaylistRemoveFormTest(TestCase):

@override_settings(USE_PLAYLIST=True)
def test_valid_data(self):
"""
Test the form with valid data.
"""
"""Test the form with valid data."""
form = PlaylistRemoveForm(data={"agree": True})
self.assertTrue(form.is_valid())
print(" ---> test_valid_data ok")

@override_settings(USE_PLAYLIST=True)
def test_agree_required(self):
"""
Test the form with agree field not selected and not provided.
"""
"""Test the form with agree field not selected and not provided."""
agree_not_selected_form = PlaylistRemoveForm(data={"agree": False})
agree_not_provided_form = PlaylistRemoveForm(data={})
self.assertFalse(agree_not_selected_form.is_valid())
Expand All @@ -220,9 +200,7 @@ def test_agree_required(self):

@override_settings(USE_PLAYLIST=True)
def test_blank_data(self):
"""
Test the form with empty data.
"""
"""Test the form with empty data."""
form = PlaylistRemoveForm(data={})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
Expand All @@ -240,18 +218,14 @@ class PlaylistPasswordFormTests(TestCase):

@override_settings(USE_PLAYLIST=True)
def test_valid_data(self):
"""
Test the form with valid data.
"""
"""Test the form with valid data."""
form = PlaylistPasswordForm(data={"password": PWD})
self.assertTrue(form.is_valid())
print(" ---> test_valid_data ok")

@override_settings(USE_PLAYLIST=True)
def test_password_required(self):
"""
Test the form with password field empty and not provided.
"""
"""Test the form with password field empty and not provided."""
password_not_provided_form = PlaylistPasswordForm(data={})
empty_password_form = PlaylistPasswordForm(data={"password": ""})
self.assertFalse(password_not_provided_form.is_valid())
Expand All @@ -268,9 +242,7 @@ def test_password_required(self):

@override_settings(USE_PLAYLIST=True)
def test_blank_data(self):
"""
Test the form with empty data.
"""
"""Test the form with empty data."""
form = PlaylistPasswordForm(data={})
self.assertFalse(form.is_valid())
self.assertEqual(len(form.errors), 1)
Expand Down
10 changes: 8 additions & 2 deletions pod/recorder/studio_urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Opencast Studio urls for Esup-Pod Integration."""
from django.conf.urls import url
from .views import studio_pod, studio_static, settings_toml, info_me_json
from .views import studio_pod, studio_static, studio_root_file
from .views import ingest_createMediaPackage, ingest_addDCCatalog
from .views import ingest_addAttachment, ingest_addTrack
from .views import ingest_addCatalog, ingest_ingest
from .views import presenter_post
from .views import presenter_post, settings_toml, info_me_json

app_name = "recorder"
urlpatterns = [
Expand Down Expand Up @@ -32,6 +33,11 @@
studio_static,
name="studio_static",
),
url(
r"^(?P<file>[a-zA-Z0-9\.]*)$",
studio_root_file,
name="studio_root_file",
),
url(
r"^ingest/createMediaPackage$",
ingest_createMediaPackage,
Expand Down
120 changes: 80 additions & 40 deletions pod/recorder/templates/recorder/opencast-studio.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

{% block page_extra_head %}
<style>
/* OpenCast v1.x colors */
:root {
--theme-ui-colors-background: var(--pod-background);
--theme-ui-colors-text: var(--pod-font-color);
Expand All @@ -15,6 +16,19 @@
--theme-ui-colors-element_bg: var(--pod-background);
}

/* OpenCast v2.x colors */
.pod-opencast-studio{
/*--color-accent5: var(--pod-btn-text);*/
--color-accent6: var(--pod-primary);
--color-accent7: var(--pod-link-color);
--color-accent8: var(--pod-activelink-color);
}
html[data-color-scheme="dark"] .pod-opencast-studio{
--color-accent6: var(--pod-primary-lighten);
--color-accent8: var(--pod-primary-lighten);
}


.pod-opencast-studio .loading-indicator>svg>circle {
stroke: var(--pod-font-color);
}
Expand All @@ -25,7 +39,7 @@
--theme-ui-colors-error: var(--bs-danger);
}

.pod-opencast-studio a[role="button"]:hover {
.pod-opencast-studio div>a[role="button"]:hover {
color: var(--pod-btn-text);
}

Expand Down Expand Up @@ -94,67 +108,93 @@

{% block more_script %}
<script>
//Create array of options to be added
// Create array of options to be added
{% if default_presenter and default_presenter == "pipb" %}
const list_value = [["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"], ["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"], ["mid", "50/50 - {% trans 'Same size for screen and camera' %}"]];
{% elif default_presenter and default_presenter == "piph" %}
const list_value = [["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"], ["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"], ["mid", "50/50 - {% trans 'Same size for screen and camera' %}"]];
const list_value = [
["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"],
["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"],
["mid", "50/50 - {% trans 'Same size for screen and camera' %}"]
];
{% elif default_presenter and default_presenter == "piph" %}
const list_value = [
["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"],
["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"],
["mid", "50/50 - {% trans 'Same size for screen and camera' %}"]
];
{% else %}
const list_value = [["mid", "50/50 - {% trans 'Same size for screen and camera' %}"], ["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"], ["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"]];
const list_value = [
["mid", "50/50 - {% trans 'Same size for screen and camera' %}"],
["piph", "Pip - {% trans 'Camera inside the screen video to top right' %}"],
["pipb", "Pip - {% trans 'Camera inside the screen video to bottom right' %}"]
];
{% endif %}

//Create and append select list
let selectList = document.createElement("select");
selectList.id = "input_presenter";
selectList.name = "presenter_list";
//myParent.appendChild(selectList);
// Create a render type select box
let renderTypeSelector = document.createElement("select");
renderTypeSelector.id = "render_type";
renderTypeSelector.name = "presenter_list";
renderTypeSelector.classList.add("form-select");

//Create and append the options
for (var i = 0; i < list_value.length; i++) {
var option = document.createElement("option");
// Create and append the render type options
for (let i = 0; i < list_value.length; i++) {
let option = document.createElement("option");
option.value = list_value[i][0];
option.text = list_value[i][1];
selectList.appendChild(option);
renderTypeSelector.appendChild(option);
}
let label = document.createElement("label");
label.innerHTML = "{% trans 'Please select the render you want' %}";
label.setAttribute("for", "input_presenter");
let renderTypeLabel = document.createElement("label");
renderTypeLabel.innerHTML = "{% trans 'Please select the render you want' %}";
renderTypeLabel.setAttribute("for", "render_type");
renderTypeLabel.classList.add("form-label");

let divselect = document.createElement("div");
divselect.appendChild(selectList)
label.appendChild(divselect)
let renderTypeDiv = document.createElement("div");
renderTypeDiv.appendChild(renderTypeLabel)
renderTypeDiv.appendChild(renderTypeSelector)

const input_title = "input[name='title'][type='text']";
let data_send = false;
$(document).on('DOMSubtreeModified', '#root>div>main', function () {
if ($(input_title).html() === "" && $(input_title).length && $("#root video").length == 2 && $("#input_presenter").length == 0 && data_send == false) {
let div = $(input_title).first().parent("div").parent("label").parent("div");
label.setAttribute("class", $(input_title).first().parent("div").parent("label").attr("class"));
div.append(label);
send_presenter_value($('#input_presenter').val());
data_send = true;
}
});
$(document).on('change', '#input_presenter', function () {
// call ajax to send value
send_presenter_value($('#input_presenter').val());
});

(function() {
body_element = document.querySelector("body");
body_element.addEventListener('DOMSubtreeModified', function () {
let inputTitle = document.querySelector("input[name='title'][type='text']");
let renderTypeInput = document.getElementById("render_type");
// If we are at last step and renderTypeInput has not been injected yet.
if (inputTitle && !renderTypeInput) {
// If we have 2 video sources
if (document.querySelectorAll("#root video").length == 2) {
let parent_div = inputTitle.parentNode.parentNode;
renderTypeDiv.classList.add(parent_div.className);
renderTypeLabel.classList.add(parent_div.firstChild.className);
parent_div.parentNode.insertBefore(renderTypeDiv, parent_div.nextSibling);
renderTypeInput = document.getElementById("render_type");
renderTypeInput.addEventListener("change", (event) => {
// call ajax to send value
send_presenter_value(event.target.value);
});
send_presenter_value(renderTypeInput.value);
}
}
}, false);
})();

/**
* [send_presenter_value description]
* @param {[type]} val [description]
*/
function send_presenter_value(val) {
console.log("VAL : " + val);
// console.log("[send_presenter_value] VAL: " + val);
$.ajax({
type: 'POST',
url: "{% url 'recorder:presenter_post' %}",
data: { "presenter": val },
success: function (response) {
success: function(response) {
data_send = false;
},
error: function (response) {
error: function(response) {
// alert the error if any error occured
console.log(response)
console.log("[send_presenter_value] response: " +response)
}
});
}

</script>
{% endblock more_script %}
Loading

0 comments on commit f51650f

Please sign in to comment.